diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f0dae4..ce1f7fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +#### v0.6.0 + +- Pagination + #### v0.5.3 - Logical Operator diff --git a/README.md b/README.md index fb9a76a..aac40fb 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ All Features:
=g&&(b=b[m-(e+.5>>0)],b=b[c]||(b[c]=[]),b[b.length]=d);return e}function O(b,a){if(b){const c=Object.keys(b);for(let d=0,e=c.length;db?1:b?-1:0}function ba(b,a){b=b[u];a=a[u];return ba?1:0}function aa(b,a){const c=u.length;for(let d=0;d a?1:0}function I(b,a,c){return b?{page:b,next:a?""+a:null,result:c}:c}function R(b,a,c,d,e,h,g){let m;h=[];let n;const f=b.length;!0===c?(c="0",n=""):n=c&& +c.split(":");if(1 k;c--)v=g.substring(k,c),M(y,m,v,b,a,n,l,p-1)}break;default:if(f=M(y,m,g,b,1,n,l,p-1),q&&1 =l)for(f=m._ctx[g]||(m._ctx[g]=x()),g=this.h[g]||(this.h[g]=U(p-(l||0))),n=a-q,v=a+q+1,0>n&&(n=0),v>r&&(v=r);n =g&&(this.F= -this.i),this.F===this.i&&(this.cache&&this.v.set(b,this.A),this.I&&this.I(this.A)));return this}function q(a,b){for(var c=a.length,g=N(b),k=[],G=0,e=0;G =e&&(a=a[f-(k+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=g);return k}function P(a,b){if(a)for(var c=Object.keys(a),g=0,k=c.length;g a?1:a?-1:0}function da(a,b){a=a[H];b=b[H];return ab?1:0}function ea(a,b){for(var c=H.length,g=0;g b?1:0}function Q(a,b,c,g,k,e){c=[];var f=a.length;if(1 b&&(c=c.slice(0,b)));return c}function I(a){return"string"===typeof a}function E(a){return a.constructor===Array}function N(a){return"function"=== -typeof a}function L(a){return"object"===typeof a}function y(a){return"undefined"===typeof a}function U(a){for(var b=Array(a),c=0;c=this.b.length&&(this.w=0),this.b[this.w].postMessage({add:!0,id:a,content:b}),this.f[e]=""+this.w,c&&c(),this;if(!k){if(this.async&&"function"!==typeof importScripts){var d=this;e=new Promise(function(c){setTimeout(function(){d.add(a,b,null,g,!0);d=null;c()})});if(c)e.then(c);else return e;return this}if(c)return this.add(a,b,null,g,!0),c(),this}b=this.encode(b);if(!b.length)return this;c=this.h; -k=N(c)?c(b):b.split(W);this.filter&&(k=q(k,this.filter));var f=C();f._ctx=C();for(var h=k.length,l=this.threshold,p=this.depth,n=this.c,u=this.u,D=this.H,w=0;w v;t--)B=r.substring(v,t),F(u,f,B,a,y,A,l,n-1);break; -default:if(z=F(u,f,r,a,1,A,l,n-1),p&&1 =l)for(z=f._ctx[r]||(f._ctx[r]=C()),r=this.s[r]||(this.s[r]=U(n-(l||0))),A=w-p,B=w+p+1,0>A&&(A=0),B>h&&(B=h);Ae;b--)h=f[b-1],f[b]=h,d[h]=b;f[e]=a;d[a]=e}}}return c};return a}();return f}(function(){var h={},m="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(f,l,q,K,d){q=m?URL.createObjectURL(new Blob(["("+q.toString()+")()"],{type:"text/javascript"})): -f+".es5.js";f+="-"+l;h[f]||(h[f]=[]);h[f][d]=new Worker(q);h[f][d].onmessage=K;console.log("Register Worker: "+f+"@"+d);return h[f][d]}}()),this); +'use strict';function P(d){var m=0;return function(){return m = +g&&(this.D=this.i),this.D===this.i&&(this.cache&&this.v.set(b,this.A),this.H&&this.H(this.A)));return this}function p(a,b){for(var c=a.length,g=R(b),k=[],u=0,e=0;u =e&&(a=a[d-(k+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=g);return k}function S(a,b){if(a)for(var c=Object.keys(a),g=0,k=c.length;g a?1:a?-1:0}function oa(a,b){a=a[F];b=b[F];return ab?1:0}function pa(a,b){for(var c=F.length,g=0;g b?1:0}function M(a,b,c){return a?{page:a,next:b?""+b:null,result:c}:c}function da(a,b,c,g,k,u,e){u=[];var d=a.length;if(!0===c){c="0";var f=""}else f=c&&c.split(":");if(1 =this.b.length&&(this.w=0),this.b[this.w].postMessage({add:!0,id:a,content:b}),this.f[e]=""+this.w,c&&c(),this;if(!d){if(this.async&&"function"!==typeof importScripts){var k=this;e=new Promise(function(c){setTimeout(function(){k.add(a,b,null,g,!0);k=null;c()})});if(c)e.then(c);else return e;return this}if(c)return this.add(a,b,null,g,!0),c(),this}b=this.encode(b);if(!b.length)return this;c=this.h;d=R(c)?c(b):b.split(ha);this.filter&&(d=p(d,this.filter)); +var f=G();f._ctx=G();for(var h=d.length,B=this.threshold,l=this.depth,q=this.c,t=this.u,n=this.G,C=0;C z;E--)r=v.substring(z,E),D(t,f,r,a,x,w,B,q-1);break;default:if(y=D(t,f,v,a,1,w,B,q-1),l&&1 =B)for(y= +f._ctx[v]||(f._ctx[v]=G()),v=this.s[v]||(this.s[v]=ea(q-(B||0))),w=C-l,r=C+l+1,0>w&&(w=0),r>h&&(r=h);w f;d--)l=h[d-1],h[d]=l,e[l]=d;h[f]=a;e[a]=f}}}return b};return a}();return f}(function(){var d={},m="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(f,l,p,Q, +h){p=m?URL.createObjectURL(new Blob(["("+p.toString()+")()"],{type:"text/javascript"})):f+".es5.js";f+="-"+l;d[f]||(d[f]=[]);d[f][h]=new Worker(p);d[f][h].onmessage=Q;console.log("Register Worker: "+f+"@"+h);return d[f][h]}}()),this); diff --git a/dist/flexsearch.light.js b/dist/flexsearch.light.js index 967c40e..34f9cab 100644 --- a/dist/flexsearch.light.js +++ b/dist/flexsearch.light.js @@ -1,18 +1,19 @@ /* - FlexSearch v0.5.31 + FlexSearch v0.6.0 Copyright 2019 Nextapps GmbH Author: Thomas Wilkerling Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';(function(d,w,x){let m;(m=x.define)&&m.amd?m([],function(){return w}):(m=x.modules)?m[d.toLowerCase()]=w:"object"===typeof exports?module.exports=w:x[d]=w})("FlexSearch",function(){function d(a,c){const b=c?c.id:a&&a.id;this.id=b||0===b?b:J++;this.init(a,c);x(this,"index",function(){return this.b});x(this,"length",function(){return Object.keys(this.index).length})}function w(a,c){const b=a.length,f=z(c),e=[];for(let k=0,g=0;k=g&&(a=a[l-(e+.5>>0)],a=a[b]||(a[b]=[]),a[a.length]=f);return e}function D(a,c){if(a){const b=Object.keys(a);for(let f=0,e=b.length;f a?1:a?-1:0}function B(a){return"string"===typeof a}function z(a){return"function"===typeof a}function C(a){return"undefined"===typeof a}function F(a){const c=Array(a);for(let b=0;bh;c--)n=k.substring(h,c),A(t,f,n,a,b,l,q,p-1)}break;default:if(g=A(t,f,k,a,1,l,q,p-1),u&&1 =q)for(g=f._ctx[k]||(f._ctx[k]=v()),k=this.f[k]||(this.f[k]=F(p-(q||0))),l=d-u,n=d+u+1,0>l&&(l=0),n>e&&(n=e);l c&&(e=e.slice(0,c)));return e};d.prototype.clear=function(){return this.destroy().init()};d.prototype.destroy=function(){this.h=this.f=this.b=null;return this};const y={icase:function(a){return a.toLowerCase()}};return d}(!1),this); +'use strict';(function(e,z,t){let k;(k=t.define)&&k.amd?k([],function(){return z}):(k=t.modules)?k[e.toLowerCase()]=z:"object"===typeof exports?module.exports=z:t[e]=z})("FlexSearch",function(){function e(a,c){const b=c?c.id:a&&a.id;this.id=b||0===b?b:L++;this.init(a,c);t(this,"index",function(){return Object.keys(this.b)});t(this,"length",function(){return this.index.length})}function z(a,c){const b=a.length,f=A(c),d=[];for(let l=0,g=0;l=g&&(a=a[h-(d+.5>>0)],a=a[b]||(a[b]=[]),a[a.length]=f);return d}function E(a,c){if(a){const b=Object.keys(a);for(let f=0,d=b.length;f a?1:a?-1:0}function F(a,c,b){return a?{page:a,next:c?""+c:null,result:b}:b}function C(a){return"string"===typeof a}function A(a){return"function"===typeof a}function D(a){return"undefined"===typeof a}function H(a){const c=Array(a);for(let b=0;bm;c--)n=l.substring(m,c),B(r,f,n,a,b,h,q,p-1)}break;default:if(g=B(r,f,l,a,1,h,q,p-1),k&&1 =q)for(g=f._ctx[l]||(f._ctx[l]=y()),l=this.f[l]||(this.f[l]=H(p-(q||0))),h=e-k,n=e+k+1,0>h&&(h=0),n>d&&(n=d);h = -d&&(this.v=this.g),this.v===this.g&&(this.cache&&this.l.set(c,this.o),this.G&&this.G(this.o)));return this}function L(a,c){const b=a.length,d=G(c),e=[];for(let h=0,f=0;h=f&&(a=a[l-(e+.5>>0)],a=a[b]||(a[b]=[]),a[a.length]=d);return e}function Q(a,c){if(a){const b=Object.keys(a);for(let d=0,e=b.length;d a?1:a?-1:0}function ea(a,c){a=a[D];c=c[D];return a c?1:0}function da(a,c){const b=D.length;for(let d=0;dc?1:0}function U(a, -c,b,d,e,h){b=[];const f=a.length;if(1 c&&(b=b.slice(0,c)));return b}function E(a){return"string"===typeof a}function z(a){return a.constructor=== -Array}function G(a){return"function"===typeof a}function F(a){return"object"===typeof a}function y(a){return"undefined"===typeof a}function W(a){const c=Array(a);for(let b=0;b=this.m.length&&(this.D=0),this.m[this.D].postMessage({add:!0,id:a,content:c}),this.c[h]=""+this.D,b&&b(),this;if(!e){if(this.async&&"function"!==typeof importScripts){let e=this;h=new Promise(function(b){setTimeout(function(){e.add(a,c,null,d,!0);e=null;b()})});if(b)h.then(b);else return h;return this}if(b)return this.add(a,c,null,d,!0),b(),this}c=this.encode(c);if(!c.length)return this; -b=this.f;e=G(b)?b(c):c.split(Y);this.filter&&(e=L(e,this.filter));const k=r();k._ctx=r();const n=e.length,p=this.threshold,B=this.depth,v=this.b,x=this.j,w=this.F;for(let c=0;c m;b--)g=f.substring(m,b), -O(x,k,g,a,c,q,p,v-1)}break;default:if(l=O(x,k,f,a,1,q,p,v-1),B&&1 =p)for(l=k._ctx[f]||(k._ctx[f]=r()),f=this.i[f]||(this.i[f]=W(v-(p||0))),q=c-B,g=c+B+1,0>q&&(q=0),g>n&&(g=n);q d;c--)e=f[c-1],f[c]=e,b[e]=c;f[d]=a;b[a]=d}}}return b};return a}();return k}(function(){const A= -{},J="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(k,C,L,N,K){L=J?URL.createObjectURL(new Blob(["("+L.toString()+")()"],{type:"text/javascript"})):k+".min.js";k+="-"+C;A[k]||(A[k]=[]);A[k][K]=new Worker(L);A[k][K].onmessage=N;return A[k][K]}}()),this); +'use strict';(function(t,M,l){let E;(E=l.define)&&E.amd?E([],function(){return M}):(E=l.modules)?E[t.toLowerCase()]=M:"object"===typeof exports?module.exports=M:l[t]=M})("FlexSearch",function ca(t){function l(a,b){const c=b?b.id:a&&a.id;this.id=c||0===c?c:da++;this.init(a,b);N(this,"index",function(){return this.a?Object.keys(this.a.index[this.a.keys[0]].c):Object.keys(this.c)});N(this,"length",function(){return this.index.length})}function E(a,b,c,d){this.u!==this.g&&(this.o=this.o.concat(c),this.u++, +d&&this.o.length>=d&&(this.u=this.g),this.u===this.g&&(this.cache&&this.l.set(b,this.o),this.F&&this.F(this.o)));return this}function O(a,b){const c=a.length,d=J(b),e=[];for(let f=0,g=0;f =g&&(a=a[m-(e+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=d);return e}function T(a,b){if(a){const c=Object.keys(a);for(let d=0,e=c.length;d a?1:a?-1:0}function fa(a,b){a=a[F];b=b[F];return ab?1:0}function ea(a, +b){const c=F.length;for(let d=0;d b?1:0}function K(a,b,c){return a?{page:a,next:b?""+b:null,result:c}:c}function V(a,b,c,d,e,f,g){let m;f=[];let n;const r=a.length;!0===c?(c="0",n=""):n=c&&c.split(":");if(1 =this.m.length&&(this.C=0),this.m[this.C].postMessage({add:!0,id:a,content:b}),this.c[f]=""+this.C,c&&c(),this;if(!e){if(this.async&&"function"!==typeof importScripts){let e=this;f=new Promise(function(c){setTimeout(function(){e.add(a,b,null,d,!0);e=null;c()})});if(c)f.then(c);else return f;return this}if(c)return this.add(a,b,null,d,!0),c(),this}b=this.encode(b);if(!b.length)return this;c=this.f;e=J(c)?c(b):b.split(Z);this.filter&&(e=O(e,this.filter));const l=q();l._ctx= +q();const p=e.length,r=this.threshold,u=this.depth,y=this.b,z=this.j,v=this.D;for(let b=0;b k;c--)h=g.substring(k,c),R(z,l,h,a,b,n,r,y-1)}break;default:if(m=R(z,l,g,a,1,n,r,y-1),u&&1
=r)for(m=l._ctx[g]|| +(l._ctx[g]=q()),g=this.i[g]||(this.i[g]=X(y-(r||0))),n=b-u,h=b+u+1,0>n&&(n=0),h>p&&(h=p);n
c;d--)e=f[d-1],f[d]=e,a[e]=d;f[c]=b;a[b]=c}}}return a};return a}();return l}(function(){const t= +{},M="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(l,E,O,Q,N){O=M?URL.createObjectURL(new Blob(["("+O.toString()+")()"],{type:"text/javascript"})):l+".min.js";l+="-"+E;t[l]||(t[l]=[]);t[l][N]=new Worker(O);t[l][N].onmessage=Q;return t[l][N]}}()),this); diff --git a/dist/flexsearch.node.js b/dist/flexsearch.node.js index a4dee2a..349aac3 100644 --- a/dist/flexsearch.node.js +++ b/dist/flexsearch.node.js @@ -1,35 +1,36 @@ /* - FlexSearch v0.5.31 + FlexSearch v0.6.0 Copyright 2019 Nextapps GmbH Author: Thomas Wilkerling Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';(function(l,E,F){let C;(C=F.define)&&C.amd?C([],function(){return E}):(C=F.modules)?C[l.toLowerCase()]=E:"object"===typeof exports?module.exports=E:F[l]=E})("FlexSearch",function(){function l(a,b){const c=b?b.id:a&&a.id;this.id=c||0===c?c:Y++;this.init(a,b);C(this,"index",function(){return this.a?this.a.index[this.a.keys[0]].f:this.f});C(this,"length",function(){return Object.keys(this.index).length})}function E(a,b){const c=a.length,d=G(b),e=[];for(let h=0,f=0;h =f&&(a=a[k-(e+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=d);return e}function N(a,b){if(a){const c=Object.keys(a);for(let d=0,e=c.length;d a?1:a?-1:0}function aa(a,b){a=a[A];b=b[A];return ab?1:0}function Z(a,b){const c=A.length;for(let d=0;d b?1:0}function R(a,b,c,d,e,h){c=[];const f=a.length;if(1 b&&(c=c.slice(0,b)));return c}function B(a){return"string"===typeof a}function x(a){return a.constructor===Array}function G(a){return"function"===typeof a}function D(a){return"object"===typeof a}function y(a){return"undefined"===typeof a}function T(a){const b=Array(a);for(let c= -0;cm;c--)g=f.substring(m,c),L(l,r,g,a,b,t,p,u-1)}break;default:if(k=L(l,r,f,a,1,t,p,u-1),z&&1 =p)for(k=r._ctx[f]||(r._ctx[f]=q()),f=this.h[f]||(this.h[f]=T(u-(p||0))),t=b-z,g=b+z+1,0>t&&(t=0),g>n&&(g=n);t c;d--)e=f[d-1],f[d]=e,a[e]=d;f[c]=b;a[b]=c}}}return a};return a}();return l}(!1),this); +'use strict';(function(l,I,J){let G;(G=J.define)&&G.amd?G([],function(){return I}):(G=J.modules)?G[l.toLowerCase()]=I:"object"===typeof exports?module.exports=I:J[l]=I})("FlexSearch",function(){function l(b,a){const c=a?a.id:b&&b.id;this.id=c||0===c?c:Z++;this.init(b,a);G(this,"index",function(){return this.a?Object.keys(this.a.index[this.a.keys[0]].f):Object.keys(this.f)});G(this,"length",function(){return this.index.length})}function I(b,a){const c=b.length,d=H(a),e=[];for(let f=0,g=0;f =g&&(b=b[m-(e+.5>>0)],b=b[c]||(b[c]=[]),b[b.length]=d);return e}function P(b,a){if(b){const c=Object.keys(b);for(let d=0,e=c.length;d b?1:b?-1:0}function ba(b,a){b=b[v];a=a[v];return ba?1:0}function aa(b,a){const c=v.length;for(let d=0;d a?1:0}function K(b,a,c){return b?{page:b,next:a?""+a:null,result:c}:c}function R(b,a,c,d,e,f,g){let m;f=[];let n;const q=b.length; +!0===c?(c="0",n=""):n=c&&c.split(":");if(1 +k;c--)h=g.substring(k,c),N(z,t,h,b,a,n,q,l-1)}break;default:if(m=N(z,t,g,b,1,n,q,l-1),u&&1=q)for(m=t._ctx[g]||(t._ctx[g]=r()),g=this.h[g]||(this.h[g]=U(l-(q||0))),n=a-u,h=a+u+1,0>n&&(n=0),h>p&&(h=p);n
c;d--)e=f[d-1],f[d]=e,b[e]=d;f[c]=a;b[a]=c}}}return b};return b}();return l}(!1),this); diff --git a/flexsearch.js b/flexsearch.js index 3d975d9..ccdd19f 100644 --- a/flexsearch.js +++ b/flexsearch.js @@ -1,24 +1,27 @@ /**! - * @preserve FlexSearch v0.5.31 + * @preserve FlexSearch v0.6.0 * Copyright 2019 Nextapps GmbH * Author: Thomas Wilkerling * Released under the Apache 2.0 Licence * https://github.com/nextapps-de/flexsearch */ -/** @define {string} */ const RELEASE = ""; +/** @define {string} */ const RELEASE = ""; /** @define {boolean} */ const DEBUG = true; /** @define {boolean} */ const PROFILER = false; /** @define {boolean} */ const SUPPORT_WORKER = true; /** @define {boolean} */ const SUPPORT_ENCODER = true; /** @define {boolean} */ const SUPPORT_CACHE = true; /** @define {boolean} */ const SUPPORT_ASYNC = true; -/** @define {boolean} */ const SUPPORT_PRESETS = true; -/** @define {boolean} */ const SUPPORT_SUGGESTIONS = true; +/** @define {boolean} */ const SUPPORT_PRESET = true; +/** @define {boolean} */ const SUPPORT_SUGGESTION = true; /** @define {boolean} */ const SUPPORT_SERIALIZE = true; /** @define {boolean} */ const SUPPORT_INFO = true; -/** @define {boolean} */ const SUPPORT_DOCUMENTS = true; +/** @define {boolean} */ const SUPPORT_DOCUMENT = true; /** @define {boolean} */ const SUPPORT_WHERE = true; +/** @define {boolean} */ const SUPPORT_PAGINATION = true; +/** @define {boolean} */ const SUPPORT_OPERATOR = true; +/** @define {boolean} */ const SUPPORT_CALLBACK = true; // noinspection ThisExpressionReferencesGlobalObjectJS (function(){ @@ -36,13 +39,14 @@ encode: "icase", tokenize: "forward", - suggest: false, + // enrich: true, + // clone: false, + // suggest: false, cache: false, async: false, worker: false, rtl: false, doc: false, - paging: false, // maximum scoring resolution: 9, @@ -177,17 +181,17 @@ register_property(this, "index", /** @this {FlexSearch} */ function(){ - if(SUPPORT_DOCUMENTS && this.doc){ + if(SUPPORT_DOCUMENT && this.doc){ - return this.doc.index[this.doc["keys"][0]]._ids; + return get_keys(this.doc.index[this.doc.keys[0]]._ids); } - return this._ids; + return get_keys(this._ids); }); register_property(this, "length", /** @this {FlexSearch} */ function(){ - return get_keys(this.index).length; + return this.index.length; }); } @@ -339,7 +343,7 @@ let preset = {}; - if(SUPPORT_PRESETS){ + if(SUPPORT_PRESET){ if(is_string(options)){ @@ -470,7 +474,7 @@ /** @private */ this.depth = ( - is_undefined(custom = options["depth"]) ? + (this.tokenize !== "strict") || is_undefined(custom = options["depth"]) ? preset.depth || this.depth || @@ -479,17 +483,6 @@ custom ); - /** @private */ - this.paging = ( - - is_undefined(custom = options["paging"]) ? - - this.paging || - defaults.paging - : - custom - ); - // TODO: provide boost /** @private */ @@ -500,19 +493,19 @@ ); */ - if(SUPPORT_SUGGESTIONS){ - - /** @private */ - this.suggest = ( - - is_undefined(custom = options["suggest"]) ? - - this.suggest || - defaults.suggest - : - custom - ); - } + // if(SUPPORT_SUGGESTION){ + // + // /** @private */ + // this.suggest = ( + // + // is_undefined(custom = options["suggest"]) ? + // + // this.suggest || + // defaults.suggest + // : + // custom + // ); + // } custom = is_undefined(custom = options["encode"]) ? @@ -565,7 +558,7 @@ let doc; - if(SUPPORT_DOCUMENTS) { + if(SUPPORT_DOCUMENT) { /** @private */ this.doc = doc = ( @@ -593,8 +586,8 @@ options["doc"] = null; - const index = doc["index"] = {}; - const keys = doc["keys"] = []; + const index = doc.index = {}; + const keys = doc.keys = []; let field = doc["field"]; let tag = doc["tag"]; @@ -820,7 +813,7 @@ FlexSearch.prototype.add = function(id, content, callback, _skip_update, _recall){ - if(SUPPORT_DOCUMENTS && this.doc && is_object(id)){ + if(SUPPORT_DOCUMENT && this.doc && is_object(id)){ return this.handle_docs("add", id, /** @type {Function} */ (content)); } @@ -1107,7 +1100,7 @@ return this; }; - if(SUPPORT_DOCUMENTS){ + if(SUPPORT_DOCUMENT){ /** * @param {!string} job @@ -1134,8 +1127,8 @@ } else{ - const index = this.doc["index"]; - const keys = this.doc["keys"]; + const index = this.doc.index; + const keys = this.doc.keys; const tags = this.doc["tag"]; let tree = this.doc["id"]; let id; @@ -1239,7 +1232,7 @@ FlexSearch.prototype.update = function(id, content, callback){ - if(SUPPORT_DOCUMENTS && this.doc && is_object(id)){ + if(SUPPORT_DOCUMENT && this.doc && is_object(id)){ return this.handle_docs("update", id, /** @type {Function} */ (content)); } @@ -1274,7 +1267,7 @@ FlexSearch.prototype.remove = function(id, callback, _recall){ - if(SUPPORT_DOCUMENTS && this.doc && is_object(id)){ + if(SUPPORT_DOCUMENT && this.doc && is_object(id)){ return this.handle_docs("remove", id, callback); } @@ -1388,15 +1381,27 @@ return result; } - function merge_and_sort(query, bool, result, sort, limit, where, cursor, has_not){ + function merge_and_sort(query, bool, result, sort, limit, suggest, where, cursor, has_and, has_not){ - result = intersect(result, where ? 0 : limit, cursor, SUPPORT_SUGGESTIONS && this.suggest, bool, has_not); - result = enrich_documents(result, this._doc); + result = intersect(result, where ? 0 : limit, cursor, SUPPORT_SUGGESTION && suggest, bool, has_and, has_not); + + let next; + + if(cursor){ + + cursor = result.page; + next = result.next; + result = result.result; + } if(where){ result = this.where(where, null, limit, result); } + else{ + + result = enrich_documents(result, this._doc); + } // TODO: pre-sort when indexing @@ -1420,6 +1425,8 @@ result.sort(sort); } + result = create_page(cursor, next, result); + if(SUPPORT_CACHE && this.cache){ this._cache.set(query, result); @@ -1441,7 +1448,7 @@ FlexSearch.prototype.search = function(query, limit, callback, _recall){ - if(SUPPORT_DOCUMENTS && is_object(limit)){ + if(SUPPORT_DOCUMENT && is_object(limit)){ if(is_array(limit)){ @@ -1464,14 +1471,17 @@ let threshold; let cursor; let sort; + let suggest; + let enrich; + let clone; - if(is_object(query) && (!SUPPORT_DOCUMENTS || !is_array(query))){ + if(is_object(query) && (!SUPPORT_DOCUMENT || !is_array(query))){ // re-assign properties if(SUPPORT_ASYNC){ - callback = query["callback"] || /** @type {?Function} */ (limit); + callback = query["callback"] || (is_function(limit) && /** @type {?Function} */ (limit)); if(callback) { @@ -1479,22 +1489,26 @@ } } - //cursor = this.paging && query["cursor"]; - sort = SUPPORT_DOCUMENTS && query["sort"]; + sort = SUPPORT_DOCUMENT && query["sort"]; + cursor = query["page"]; limit = query["limit"]; threshold = query["threshold"]; + enrich = query["enrich"]; + clone = query["clone"]; + suggest = SUPPORT_SUGGESTION && query["suggest"]; query = query["query"]; } - if(SUPPORT_DOCUMENTS && this.doc){ + if(SUPPORT_DOCUMENT && this.doc){ - const doc_idx = this.doc["index"]; + const doc_idx = this.doc.index; const where = SUPPORT_WHERE && _query["where"]; - const bool_main = _query["bool"] || "or"; + const bool_main = (SUPPORT_OPERATOR && _query["bool"]) || "or"; let field = _query["field"]; let bool = bool_main; let queries; let has_not; + let has_and; if(field){ @@ -1509,10 +1523,12 @@ field = []; bool = []; + // TODO: make some unit tests and check if the fields should be sorted (not > and > or)? + for(let i = 0; i < _query.length; i++){ const current = _query[i]; - const current_bool = current["bool"] || bool_main; + const current_bool = (SUPPORT_OPERATOR && current["bool"]) || bool_main; field[i] = current["field"]; bool[i] = current_bool; @@ -1521,11 +1537,15 @@ has_not = true; } + else if(current_bool === "and"){ + + has_and = true; + } } } else{ - field = this.doc["keys"]; + field = this.doc.keys; } const len = field.length; @@ -1537,12 +1557,32 @@ _query = queries[i]; } - result[i] = doc_idx[field[i]].search(_query); + if(!is_string(_query)){ + + _query["page"] = null; + _query["limit"] = 0; + } + + result[i] = doc_idx[field[i]].search(_query, 0); } if(callback){ - return callback(merge_and_sort.call(this, query, bool, result, sort, limit, where, cursor, has_not)); + return callback( + + merge_and_sort.call(this, + query, + bool, + result, + sort, + limit, + suggest, + where, + cursor, + has_and, + has_not + ) + ); } else if(SUPPORT_ASYNC && this.async){ @@ -1552,13 +1592,38 @@ Promise.all(/** @type {!Iterable } */ (result)).then(function(values){ - resolve(merge_and_sort.call(self, query, bool, values, sort, limit, where, cursor, has_not)); + resolve( + + merge_and_sort.call(self, + query, + bool, + values, + sort, + limit, + suggest, + where, + cursor, + has_and, + has_not + ) + ); }); }); } else{ - return merge_and_sort.call(this, query, bool, result, sort, limit, where, cursor, has_not); + return merge_and_sort.call(this, + query, + bool, + result, + sort, + limit, + suggest, + where, + cursor, + has_and, + has_not + ); } } @@ -1686,7 +1751,7 @@ tokenizer(_query) :( - // NOTE: ngram matches inconsistently, research or remove + // TODO: ngram matches inconsistently, research or remove //SUPPORT_ENCODER && (tokenizer === "ngram") ? /** @type {!Array } */ @@ -1760,7 +1825,7 @@ const resolution = this.resolution; // TODO: boost on custom search is actually not possible, move to adding index instead - // if(SUPPORT_DOCUMENTS && boost){ + // if(SUPPORT_DOCUMENT && boost){ // // threshold = (threshold || 1) / boost; // } @@ -1812,7 +1877,7 @@ // handled by intersection: //check[check.length] = map_check; } - else if(!SUPPORT_SUGGESTIONS || !this.suggest){ + else if(!SUPPORT_SUGGESTION || !suggest){ found = false; break; @@ -1830,15 +1895,15 @@ found = false; } - if(!SUPPORT_DOCUMENTS || !this.doc){ + //if(!SUPPORT_DOCUMENT || !this.doc){ if(found){ // Not handled by intersection: - result = intersect(check, limit, cursor, SUPPORT_SUGGESTIONS && this.suggest); + result = /** @type {Array} */ (intersect(check, limit, cursor, SUPPORT_SUGGESTION && suggest)); // Handled by intersection: - //result = intersect_3d(check, limit, this.suggest); + //result = intersect_3d(check, limit, suggest); } // store result to cache @@ -1847,7 +1912,7 @@ this._cache.set(query, result); } - } + //} if(PROFILER){ @@ -1857,7 +1922,7 @@ return result; }; - if(SUPPORT_DOCUMENTS && SUPPORT_WHERE){ + if(SUPPORT_DOCUMENT && SUPPORT_WHERE){ /** * @export @@ -1879,7 +1944,7 @@ FlexSearch.prototype.where = function(key, value, limit, result){ - const doc = result || this._doc; + const doc = this._doc; const results = []; let count = 0; @@ -1888,46 +1953,7 @@ let has_value; let tree; - if(typeof key === "number"){ - - return [doc[key]]; - } - - if(is_string(key)){ - - if(is_undefined(value)){ - - return [doc[key]]; - } - - if(key === "id"){ - - return [doc[value]]; - } - - keys = [key]; - keys_len = 1; - tree = [key.split(":")]; - has_value = true; - } - else if(is_function(key)){ - - const ids = result || get_keys(doc); - const length = ids.length; - - for(let x = 0; x < length; x++){ - - const obj = result ? result[x] : doc[ids[x]]; - - if(key(obj)){ - - results[count++] = obj; - } - } - - return results; - } - else{ + if(is_object(key)){ limit || (limit = value); keys = get_keys(key); @@ -1965,11 +1991,6 @@ break; } } - - // for(let i = 0; i < result.length; i++){ - // - // result[i] = this._doc[result[i]]; - // } } tree = new Array(keys_len); @@ -1979,13 +2000,47 @@ tree[i] = keys[i].split(":"); } } + else if(is_function(key)){ + + const ids = result || get_keys(doc); + const length = ids.length; + + for(let x = 0; x < length; x++){ + + const obj = doc[ids[x]]; + + if(key(obj)){ + + results[count++] = obj; + } + } + + return results; + } + else{ + + if(is_undefined(value)){ + + return [doc[key]]; + } + + if(key === "id"){ + + return [doc[value]]; + } + + keys = [key]; + keys_len = 1; + tree = [key.split(":")]; + has_value = true; + } const ids = result || get_keys(doc); // this._ids; const length = ids.length; for(let x = 0; x < length; x++){ - const obj = result ? result[x] : doc[ids[x]]; + const obj = doc[ids[x]]; let found = true; for(let i = 0; i < keys_len; i++){ @@ -2127,9 +2182,9 @@ this._ctx = this._ids = null; - if(SUPPORT_DOCUMENTS && this.doc){ + if(SUPPORT_DOCUMENT && this.doc){ - const keys = this.doc["keys"]; + const keys = this.doc.keys; for(let i = 0; i < keys.length; i++){ @@ -2152,9 +2207,9 @@ FlexSearch.prototype.export = function(){ - if(SUPPORT_DOCUMENTS && this.doc){ + if(SUPPORT_DOCUMENT && this.doc){ - const keys = this.doc["keys"]; + const keys = this.doc.keys; const length = keys.length; const payload = new Array(length + 1); @@ -2166,7 +2221,7 @@ payload[i] = [ - idx._map, idx._ctx, idx._ids + idx._map, idx._ctx, get_keys(idx._ids) ]; } @@ -2179,7 +2234,7 @@ this._map, this._ctx, - this._ids + get_keys(this._ids) ]); }; @@ -2191,10 +2246,18 @@ payload = JSON.parse(payload); - if(SUPPORT_DOCUMENTS && this.doc){ + const ids = create_object(); - const keys = this.doc["keys"]; + if(SUPPORT_DOCUMENT && this.doc){ + + const keys = this.doc.keys; const length = keys.length; + const current = payload[0][2]; + + for(let i = 0; i < current.length; i++){ + + ids[current[i]] = 1; + } for(let i = 0; i < length; i++){ @@ -2202,7 +2265,7 @@ idx._map = payload[i][0]; idx._ctx = payload[i][1]; - idx._ids = payload[i][2]; + idx._ids = ids; idx._doc = payload[length]; } @@ -2210,10 +2273,16 @@ } else{ + const current = payload[2]; + + for(let i = 0; i < current.length; i++){ + + ids[current[i]] = 1; + } + this._map = payload[0]; this._ctx = payload[1]; - this._ids = payload[2]; - //this._doc = payload[3]; + this._ids = ids; } }; } @@ -2505,6 +2574,7 @@ this.count[key] = -1; this.cache[key] = value; + // TODO: remove extra call // shift up counter +1 this.get(key); @@ -3052,22 +3122,52 @@ ); } + function create_page(cursor, page, result){ + + return cursor ? { + + "page": cursor, + "next": page ? "" + page : null, + "result": result + + } : result; + } + /** + * This is the main hot spot. + * Any possible performance improvements should be applied here. + * TODO: Do not return the original array as reference! + * TODO: Make use of performance benefits of a cursor when no "and" operator was used + * * @param {!Array >} arrays* * @param {number=} limit - * @param {number=} cursor + * @param {string|boolean=} cursor * @param {boolean=} suggest * @param {Array =} bool + * @param {boolean=} has_and * @param {boolean=} has_not - * @returns {Array} + * @returns {Array|Object} */ - function intersect(arrays, limit, cursor, suggest, bool, has_not) { + function intersect(arrays, limit, cursor, suggest, bool, has_and, has_not) { + let page; let result = []; - let suggestions; + let pointer; const length_z = arrays.length; + if(cursor === true){ + + cursor = "0"; + pointer = ""; + } + else{ + + pointer = cursor && cursor.split(":"); + } + + // use complex handler when length > 1 + if(length_z > 1){ // TODO: test strategy @@ -3076,6 +3176,7 @@ const check = create_object(); + let suggestions = []; let check_not; let arr; let z = -1; // start from 0 @@ -3088,7 +3189,25 @@ let bool_main; let last_index; - if(SUPPORT_DOCUMENTS){ + let pointer_suggest; + + if(pointer){ + + if(pointer.length === 2){ + + pointer_suggest = pointer; + pointer = false; + } + else{ + + pointer = parseInt(pointer[0], 10); + } + } + + if(SUPPORT_DOCUMENT && SUPPORT_OPERATOR){ + + // there are two possible strategies: 1. pre-fill (actually), 2. filter during last round + // TODO: compare both strategies if(has_not){ @@ -3111,13 +3230,19 @@ } else{ + // this additional loop provides a proofed last result + // TODO: could be handled before intersection, or use sorted fields + last_index = z + 1; } } + // there was no field with "and" / "or" + // TODO: this could also checked before intersection + if(!last_index){ - return result; + return create_page(cursor, page, result); } z = -1; @@ -3141,7 +3266,7 @@ let bool_and; let bool_or; - if(SUPPORT_DOCUMENTS){ + if(SUPPORT_DOCUMENT && SUPPORT_OPERATOR){ if(!bool_main || !z){ @@ -3157,6 +3282,8 @@ } else{ + // already done, go next + continue; } } @@ -3171,9 +3298,11 @@ if(!length){ + // return empty on specific conditions + if(bool_and && !suggest){ - return arr; + return create_page(cursor, page, arr); } continue; @@ -3181,6 +3310,8 @@ if(init){ + // pre-fill first just right before an additional result + if(first_result){ const result_length = first_result.length; @@ -3199,6 +3330,8 @@ } else{ + // hold first result and wait for additional result + first_result = arr; continue; @@ -3208,14 +3341,14 @@ let found = false; i = 0; - suggestions = []; + //suggestions = []; while(i < length){ tmp = arr[i++]; const index = "@" + tmp; - const check_val = check[index]; + const check_val = bool_or ? z : check[index]; if(check_val){ @@ -3224,28 +3357,25 @@ continue; } - if(bool_or || (check_val === z)){ + if(check_val === z){ // fill in during last round if(is_final_loop){ - result[count++] = tmp; + // sadly the pointer could just applied here at the earliest + // that's why pagination cannot reduce complexity actually + // should only happened when at least one "and" bool was set + // TODO: check bool and provide complexity reduction - if(limit && (count === limit)){ + if(!pointer || (--pointer < count)){ - // if(cursor){ - // - // return { - // - // "current": cursor, - // "prev": null, - // "next": z + ":" + i, - // "result": result - // }; - // } + result[count++] = tmp; - return result; + if(limit && (count === limit)){ + + return create_page(cursor, count, result); + } } } else{ @@ -3253,8 +3383,6 @@ check[index] = z + 1; } - // apply count status - found = true; } else if(suggest){ @@ -3272,19 +3400,30 @@ } } - if(!found && !suggest){ + // nothing found, break the main loop + + if(bool_and && !found && !suggest){ break; } } + // a first result was hold + if(first_result){ + const result_length = first_result.length; + if(has_not){ - const result_length = first_result.length; + if(pointer){ - i = 0; + i = parseInt(pointer, 10); + } + else{ + + i = 0; + } while(i < result_length){ @@ -3292,7 +3431,15 @@ if(!check_not["@" + id]){ - result[count++] = id; + if(!pointer || (--pointer < count)){ + + result[count++] = id; + + if(limit && (count === limit)){ + + return create_page(cursor, i, result); + } + } } } } @@ -3305,23 +3452,35 @@ if(suggest){ count = result.length; - z = suggestions.length; - if(z && (!limit || (count < limit))){ + if(pointer_suggest){ - while(z--){ + z = parseInt(pointer_suggest[0], 10) + 1; + i = parseInt(pointer_suggest[1], 10); + } + else{ - tmp = suggestions[z]; + z = suggestions.length; + i = 0; + } - if(tmp){ + while(z--){ - for(i = 0, length = tmp.length; i < length; i++){ + tmp = suggestions[z]; - result[count++] = tmp[i]; + if(tmp){ + + for(length = tmp.length; i < length; i++){ + + const id = tmp[i]; + + if(!has_not || !check_not["@" + id]){ + + result[count++] = id; if(limit && (count === limit)){ - return result; + return create_page(cursor, z + ":" + i, result); } } } @@ -3331,23 +3490,31 @@ } else if(length_z){ - if(!bool || (bool[0] !== "not")){ + if(!bool || (SUPPORT_OPERATOR && (bool[0] !== "not"))){ result = arrays[0]; - if(limit && (result.length > limit)){ - - // Note: do not modify the original index array! - - result = result.slice(0, limit); - } - - // Note: handle references to the original index array - //return result.slice(0); + // TODO: handle references to the original index array + // return result.slice(0); } } - return result; + if(limit){ + + const start = cursor ? parseInt(cursor, 10) : 0; + page = start + limit; + + if(page < result.length){ + + result = result.slice(start, page); + } + else if(start){ + + result = result.slice(start); + } + } + + return create_page(cursor, page, result); } /** @@ -3767,15 +3934,18 @@ "var RELEASE = '" + RELEASE + "';" + "var DEBUG = " + (DEBUG ? "true" : "false") + ";" + "var PROFILER = " + (PROFILER ? "true" : "false") + ";" + - "var SUPPORT_PRESETS = " + (SUPPORT_PRESETS ? "true" : "false") + ";" + - "var SUPPORT_SUGGESTIONS = " + (SUPPORT_SUGGESTIONS ? "true" : "false") + ";" + + "var SUPPORT_PRESET = " + (SUPPORT_PRESET ? "true" : "false") + ";" + + "var SUPPORT_SUGGESTION = " + (SUPPORT_SUGGESTION ? "true" : "false") + ";" + "var SUPPORT_ENCODER = " + (SUPPORT_ENCODER ? "true" : "false") + ";" + "var SUPPORT_CACHE = " + (SUPPORT_CACHE ? "true" : "false") + ";" + "var SUPPORT_ASYNC = " + (SUPPORT_ASYNC ? "true" : "false") + ";" + "var SUPPORT_SERIALIZE = " + (SUPPORT_SERIALIZE ? "true" : "false") + ";" + "var SUPPORT_INFO = " + (SUPPORT_INFO ? "true" : "false") + ";" + - "var SUPPORT_DOCUMENTS = " + (SUPPORT_DOCUMENTS ? "true" : "false") + ";" + + "var SUPPORT_DOCUMENT = " + (SUPPORT_DOCUMENT ? "true" : "false") + ";" + "var SUPPORT_WHERE = " + (SUPPORT_WHERE ? "true" : "false") + ";" + + "var SUPPORT_WHERE = " + (SUPPORT_PAGINATION ? "true" : "false") + ";" + + "var SUPPORT_WHERE = " + (SUPPORT_OPERATOR ? "true" : "false") + ";" + + "var SUPPORT_WHERE = " + (SUPPORT_CALLBACK ? "true" : "false") + ";" + "var SUPPORT_WORKER = true;" ) + "(" + _worker.toString() + ")()" diff --git a/package.json b/package.json index 73abfda..e5bcdb8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flexsearch", - "version": "0.5.31", + "version": "0.6.0", "description": "Next-Generation full text search library with zero dependencies.", "homepage": "https://github.com/nextapps-de/flexsearch/", "author": "Thomas Wilkerling", @@ -26,12 +26,12 @@ "url": "https://github.com/nextapps-de/flexsearch.git" }, "scripts": { - "build": "node compile RELEASE=min DEBUG=false PROFILER=false SUPPORT_WORKER=true SUPPORT_ENCODER=true SUPPORT_CACHE=true SUPPORT_ASYNC=true SUPPORT_PRESETS=true SUPPORT_SUGGESTIONS=true SUPPORT_SERIALIZE=true SUPPORT_INFO=true SUPPORT_DOCUMENTS=true SUPPORT_WHERE=true SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", - "build-light": "node compile RELEASE=light DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=false SUPPORT_CACHE=false SUPPORT_ASYNC=false SUPPORT_PRESETS=false SUPPORT_SUGGESTIONS=false SUPPORT_SERIALIZE=false SUPPORT_INFO=false SUPPORT_DOCUMENTS=false SUPPORT_WHERE=false SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", - "build-compact": "node compile RELEASE=compact DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=true SUPPORT_CACHE=false SUPPORT_ASYNC=true SUPPORT_PRESETS=true SUPPORT_SUGGESTIONS=false SUPPORT_SERIALIZE=false SUPPORT_INFO=false SUPPORT_DOCUMENTS=true SUPPORT_WHERE=false SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", - "build-custom": "node compile RELEASE=custom DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=false SUPPORT_CACHE=false SUPPORT_ASYNC=false SUPPORT_PRESETS=false SUPPORT_SUGGESTIONS=false SUPPORT_SERIALIZE=false SUPPORT_INFO=false SUPPORT_DOCUMENTS=false SUPPORT_WHERE=false SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", - "build-es5": "node compile RELEASE=es5 DEBUG=true PROFILER=false SUPPORT_WORKER=true SUPPORT_ENCODER=true SUPPORT_CACHE=true SUPPORT_ASYNC=true SUPPORT_PRESETS=true SUPPORT_SUGGESTIONS=true SUPPORT_SERIALIZE=true SUPPORT_INFO=true SUPPORT_DOCUMENTS=true SUPPORT_WHERE=true SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false LANGUAGE_OUT=ECMASCRIPT5_STRICT", - "build-node": "node compile RELEASE=node DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=true SUPPORT_CACHE=true SUPPORT_ASYNC=true SUPPORT_PRESETS=true SUPPORT_SUGGESTIONS=true SUPPORT_SERIALIZE=true SUPPORT_INFO=true SUPPORT_DOCUMENTS=true SUPPORT_WHERE=true SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", + "build": "node compile RELEASE=min DEBUG=false PROFILER=false SUPPORT_WORKER=true SUPPORT_ENCODER=true SUPPORT_CACHE=true SUPPORT_ASYNC=true SUPPORT_PRESET=true SUPPORT_SUGGESTION=true SUPPORT_SERIALIZE=true SUPPORT_INFO=true SUPPORT_DOCUMENT=true SUPPORT_WHERE=true SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", + "build-light": "node compile RELEASE=light DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=false SUPPORT_CACHE=false SUPPORT_ASYNC=false SUPPORT_PRESET=false SUPPORT_SUGGESTION=false SUPPORT_SERIALIZE=false SUPPORT_INFO=false SUPPORT_DOCUMENT=false SUPPORT_WHERE=false SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", + "build-compact": "node compile RELEASE=compact DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=true SUPPORT_CACHE=false SUPPORT_ASYNC=true SUPPORT_PRESET=true SUPPORT_SUGGESTION=false SUPPORT_SERIALIZE=false SUPPORT_INFO=false SUPPORT_DOCUMENT=true SUPPORT_WHERE=false SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", + "build-custom": "node compile RELEASE=custom DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=false SUPPORT_CACHE=false SUPPORT_ASYNC=false SUPPORT_PRESET=false SUPPORT_SUGGESTION=false SUPPORT_SERIALIZE=false SUPPORT_INFO=false SUPPORT_DOCUMENT=false SUPPORT_WHERE=false SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", + "build-es5": "node compile RELEASE=es5 DEBUG=true PROFILER=false SUPPORT_WORKER=true SUPPORT_ENCODER=true SUPPORT_CACHE=true SUPPORT_ASYNC=true SUPPORT_PRESET=true SUPPORT_SUGGESTION=true SUPPORT_SERIALIZE=true SUPPORT_INFO=true SUPPORT_DOCUMENT=true SUPPORT_WHERE=true SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false LANGUAGE_OUT=ECMASCRIPT5_STRICT", + "build-node": "node compile RELEASE=node DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=true SUPPORT_CACHE=true SUPPORT_ASYNC=true SUPPORT_PRESET=true SUPPORT_SUGGESTION=true SUPPORT_SERIALIZE=true SUPPORT_INFO=true SUPPORT_DOCUMENT=true SUPPORT_WHERE=true SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", "build-lang": "node compile RELEASE=lang", "build-all": "npm run build && npm run build-light && npm run build-compact && npm run build-es5 && npm run build-node", "test-production": "nyc --reporter=html --reporter=text mocha --timeout=3000 test --exit", diff --git a/test/test.js b/test/test.js index b04c312..494ac30 100644 --- a/test/test.js +++ b/test/test.js @@ -212,7 +212,7 @@ describe("Add (Sync)", function(){ flexsearch_sync.add(2, "bar"); flexsearch_sync.add(1, "foobar"); - expect(flexsearch_sync.index).to.have.keys(["@0", "@1", "@2"]); + expect(flexsearch_sync.index).to.have.members(["@0", "@1", "@2"]); expect(flexsearch_sync.length).to.equal(3); }); @@ -416,7 +416,7 @@ if(env !== "light"){ setTimeout(function(){ expect(flexsearch_async.length).to.equal(3); - expect(flexsearch_async.index).to.have.keys(["@0", "@1", "@2"]); + expect(flexsearch_async.index).to.have.members(["@0", "@1", "@2"]); done(); @@ -438,7 +438,7 @@ if(env !== "light"){ setTimeout(function(){ expect(flexsearch_async.length).to.equal(3); - expect(flexsearch_async.index).to.have.keys(["@0", "@1", "@2"]); + expect(flexsearch_async.index).to.have.members(["@0", "@1", "@2"]); done(); @@ -632,7 +632,7 @@ if(env !== "light"){ setTimeout(function(){ expect(flexsearch_worker.length).to.equal(3); - expect(flexsearch_worker.index).to.have.keys(["@0", "@1", "@2"]); + expect(flexsearch_worker.index).to.have.members(["@0", "@1", "@2"]); flexsearch_worker.search("foo", function(result){ @@ -661,7 +661,7 @@ if(env !== "light"){ setTimeout(function(){ expect(flexsearch_worker.length).to.equal(3); - expect(flexsearch_worker.index).to.have.keys(["@0", "@1", "@2"]); + expect(flexsearch_worker.index).to.have.members(["@0", "@1", "@2"]); done(); @@ -1149,7 +1149,7 @@ describe("Relevance", function(){ index = new FlexSearch({ encode: "extra", - tokenize: "ngram", + tokenize: "strict", threshold: 5, depth: 3 }); @@ -1178,18 +1178,18 @@ if(env !== "light") describe("Suggestions", function(){ var index = new FlexSearch({ encode: "advanced", - tokenize: "strict", - suggest: true + tokenize: "strict" }); index.add(0, "1 2 3 2 4 1 5 3"); index.add(1, "zero one two three four five six seven eight nine ten"); index.add(2, "four two zero one three ten five seven eight six nine"); - expect(index.search("1 3 4 7")).to.have.members([0]); - expect(index.search("1 3 9 7")).to.have.members([0]); - expect(index.search("one foobar two")).to.have.members([1, 2]); - expect(index.search("zero one foobar two foobar")).to.have.members([1, 2]); + expect(index.search("1 3 4 7", { suggest: false })).to.have.lengthOf(0); + expect(index.search("1 3 4 7", { suggest: true })).to.have.members([0]); + expect(index.search("1 3 9 7", { suggest: true })).to.have.members([0]); + expect(index.search("one foobar two", { suggest: true })).to.have.members([1, 2]); + expect(index.search("zero one foobar two foobar", { suggest: true })).to.have.members([1, 2]); //TODO //expect(index.search("zero one foobar two foobar")[0]).to.equal(1); @@ -1231,7 +1231,7 @@ if(env === "" || env === "min") describe("Where/Find", function(){ index.add(data); expect(index.length).to.equal(3); - expect(index.index).to.have.keys(["@0", "@1", "@2"]); + expect(index.index).to.have.members(["@0", "@1", "@2"]); expect(index.find(0)).to.equal(data[0]); expect(index.find("id", 0)).to.equal(data[0]); @@ -1762,6 +1762,166 @@ if(env !== "light") describe("Index Multi-Field Documents", function(){ } }); +if(env !== "light") describe("Pagination", function(){ + + it("Should have been properly paged", function(){ + + var index = new FlexSearch(); + + index.add(0, "test").add(1, "test").add(2, "test").add(3, "test").add(4, "test"); + + expect(index.index).to.have.members(["@0", "@1", "@2", "@3", "@4"]); + expect(index.search("test")).to.have.lengthOf(5); + expect(index.search("test", 2)).to.have.lengthOf(2); + + expect(index.search("test", { + page: true, + limit: 2 + })).to.have.keys(["page", "next", "result"]); + + var result = index.search("test", { + page: true, + limit: 2 + }); + + expect(result.result).to.have.members([0, 1]); + + result = index.search("test", { + page: result.next, + limit: 2 + }); + + expect(result.result).to.have.members([2, 3]); + + result = index.search("test", { + page: result.page, + limit: 2 + }); + + expect(result.result).to.have.members([2, 3]); + + result = index.search("test", { + page: result.next, + limit: 2 + }); + + expect(result.result).to.have.members([4]); + }); + + it("Should have been properly paged (documents)", function(){ + + var data = [{ + id: 0, + title: "Title 1", + body: "Body 1" + },{ + id: 1, + title: "Title 2", + body: "Body 2" + },{ + id: 2, + title: "Title 3", + body: "Body 3" + },{ + id: 3, + title: "Title 4", + body: "Body 4" + },{ + id: 4, + title: "Title 5", + body: "Body 5" + }]; + + var index = new FlexSearch({ + doc: { + id: "id", + field: ["title", "body"] + } + }); + + index.add(data); + + if(env === ""){ + + expect(index.doc.index["title"].index).to.have.members(["@0", "@1", "@2", "@3", "@4"]); + expect(index.doc.index["body"].index).to.have.members(["@0", "@1", "@2", "@3", "@4"]); + } + + expect(index.search("title")).to.have.lengthOf(5); + expect(index.search("title", 2)).to.have.lengthOf(2); + + expect(index.search("title", { + page: true, + limit: 2 + })).to.have.keys(["page", "next", "result"]); + + var result = index.search("title", { + page: true, + limit: 2 + }); + + expect(result.result).to.have.members([data[0], data[1]]); + + result = index.search("title", { + page: result.next, + limit: 2 + }); + + expect(result.result).to.have.members([data[2], data[3]]); + + result = index.search("title", { + page: result.page, + limit: 2 + }); + + expect(result.result).to.have.members([data[2], data[3]]); + + result = index.search("title", { + page: result.next, + limit: 2 + }); + + expect(result.result).to.have.members([data[4]]); + }); +}); + +describe("Github Issues", function(){ + + if(env !== "light") it("#48", function(){ + + const fs = new FlexSearch({ + encode: "extra", + tokenize: "full", + threshold: 1, + depth: 4, + resolution: 9, + async: false, + worker: 1, + cache: true, + suggest: true, + doc: { + id: "id", + field: [ "intent", "text" ] + } + }); + + const doc = [{ + id: 0, + intent: "intent", + text: "text" + },{ + id: 1, + intent: "intent", + text: "howdy - how are you doing" + }]; + + fs.add(doc); + + expect(fs.search("howdy", { bool: "or" })).to.have.members([doc[1]]); + expect(fs.search("howdy -", { bool: "or" })).to.have.members([doc[1]]); + }); +}); + if(env !== "light") describe("Operators", function(){ var data = [{ @@ -1872,6 +2032,20 @@ if(env !== "light") describe("Operators", function(){ bool: "not" }])).to.have.length(0); + expect(index.search([{ + field: "blacklist", + query: "x1", + bool: "not" + },{ + field: "title", + query: "title", + bool: "or" + },{ + field: "body", + query: "body", + bool: "or" + }])).to.have.length(2); + expect(index.search([{ field: "title", query: "body", @@ -1932,7 +2106,7 @@ if(env !== "light") describe("Operators", function(){ describe("Reserved Words", function(){ - it("Should have been exported properly", function(){ + it("Should have been indexed properly", function(){ var index = new FlexSearch({ encode: false, @@ -2004,7 +2178,7 @@ if(env !== "light") describe("Export / Import", function(){ [ index.doc.index["title"]._map, index.doc.index["title"]._ctx, - index.doc.index["title"]._ids + Object.keys(index.doc.index["title"]._ids) ], index._doc ]));