From f1a162137e8f76d330df459a31e7a544e8bf15ef Mon Sep 17 00:00:00 2001 From: Thomas Wilkerling Date: Tue, 12 Feb 2019 18:29:38 +0100 Subject: [PATCH] v0.5.2 Intersect Partial Results, Fix: #38 #39 --- CHANGELOG.md | 4 + dist/flexsearch.compact.js | 44 ++-- dist/flexsearch.es5.js | 78 +++--- dist/flexsearch.light.js | 24 +- dist/flexsearch.min.js | 65 ++--- dist/flexsearch.node.js | 57 ++--- flexsearch.js | 475 ++++++++++++++++--------------------- package.json | 2 +- test/test.es6.js | 70 ++++-- test/test.js | 267 +++++++++++++++------ 10 files changed, 597 insertions(+), 489 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9411ff0..5ea3929 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +#### v0.5.2 + +- Intersect Partial Results + #### v0.5.1 - Provide customizable scoring resolution diff --git a/dist/flexsearch.compact.js b/dist/flexsearch.compact.js index e490606..2f81426 100644 --- a/dist/flexsearch.compact.js +++ b/dist/flexsearch.compact.js @@ -1,28 +1,28 @@ /* - FlexSearch v0.5.1 + FlexSearch v0.5.2 Copyright 2019 Nextapps GmbH Author: Thomas Wilkerling Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';(function(n,u,A){let f;(f=A.define)&&f.amd?f([],function(){return u}):(f=A.modules)?f[n.toLowerCase()]=u:"object"===typeof exports?module.exports=u:A[n]=u})("FlexSearch",function(){function n(a,b){const c=b?b.id:a&&a.id;this.id=c||0===c?c:Q++;this.init(a,b);A(this,"index",function(){return this.f});A(this,"length",function(){return Object.keys(this.f).length})}function u(a,b){a=a.concat.apply([],a);b&&(F(b)||(x=b.split(":"),1=e&&(a=a[k-(g+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=d);return g}function I(a,b){if(a){const c=Object.keys(a);for(let d=0,g=c.length;da?1:a?-1:0}function U(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function S(a,b){a=a[x];b=b[x];return ab?1:0}function R(a,b){const c=x.length;for(let d= -0;db?1:0}function V(a,b,c,d,g){c=[];let h;const e=a.length;if(1b&&(c=c.slice(0,b));return c}function H(a){return"string"===typeof a}function F(a){return"function"===typeof a}function y(a){return"object"===typeof a}function D(a){return"undefined"===typeof a}function L(a){const b=Array(a);for(let c=0;cl;c--)m=e.substring(l,c),G(t,h,m,a,b,q,p,r-1)}break;default:if(k=G(t,h,e,a,1,q,p,r-1),n&&1=p)for(k=h._ctx[e]||(h._ctx[e]=v()),e=this.h[e]||(this.h[e]=L(r-(p||0))),q=b-n,m=b+n+1,0>q&&(q=0),m>C&&(m=C);q=g&&(b=b[l-(f+.5>>0)],b=b[c]|| +(b[c]=[]),b[b.length]=d);return f}function K(b,a){if(b){const c=Object.keys(b);for(let d=0,f=c.length;db?1:b?-1:0}function V(b,a){b=b[v];a=a[v];return ba?1:0}function U(b,a){const c=v.length;for(let d=0;da?1:0}function N(b,a,c,d){c=[];let f;const h=b.length;if(1a&&(c=c.slice(0,a)));return c}function F(b){return"string"===typeof b}function w(b){return b.constructor===Array}function E(b){return"function"===typeof b}function C(b){return"object"===typeof b}function G(b){return"undefined"===typeof b}function O(b){const a= +Array(b);for(let c=0;ck;c--)m=g.substring(k,c),I(J,p,m,b,a,t,l,D-1)}break;default:if(e=I(J,p,g,b,1,t,l,D-1),n&&1=l)for(e=p._ctx[g]||(p._ctx[g]=u()),g=this.h[g]||(this.h[g]=O(D-(l||0))), +t=a-n,m=a+n+1,0>t&&(t=0),m>q&&(m=q);t=g&&(this.D=this.i),this.I&&this.D===this.i&&(this.cache&& -this.A.set(b,this.v),this.I(this.v),this.v=[]));return this}function l(a,b){a=a.concat.apply([],a);b&&(L(b)||(F=b.split(":"),1=e&&(a=a[h-(m+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=g);return m} -function H(a,b){if(a)for(var c=Object.keys(a),g=0,m=c.length;ga?1:a?-1:0}function ca(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function da(a,b){a=a[F];b=b[F];return ab?1:0}function ea(a,b){for(var c=F.length,g=0;gb?1:0}function Q(a,b,c,g,d){c=[];var e=a.length;if(1b&&(c=c.slice(0,b));return c}function M(a){return"string"===typeof a}function I(a){return a.constructor===Array}function L(a){return"function"===typeof a}function J(a){return"object"=== -typeof a}function E(a){return"undefined"===typeof a}function U(a){for(var b=Array(a),c=0;c=this.a.length&&(this.w=0),this.a[this.w].postMessage({add:!0,id:a,content:b}),this.c[g]=""+this.w,c&&c(),this;if(!e){if(this.async&&"function"!==typeof importScripts){var m=this;g=new Promise(function(c){setTimeout(function(){m.add(a,b,null,d,!0);m=null;c()})});if(c)g.then(c);else return g;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.h; -e=L(c)?c(b):b.split(W);var h=C();h._ctx=C();for(var f=this.threshold,p=this.depth,q=this.f,z=this.o,r=e.length,n=this.H,l=0;lx;y--)A=u.substring(x,y),B(z,h,A,a,t,w,f,q-1);break;default:if(v=B(z,h,u,a,1,w,f,q- -1),p&&1=f)for(v=h._ctx[u]||(h._ctx[u]=C()),u=this.u[u]||(this.u[u]=U(q-(f||0))),w=l-p,A=l+p+1,0>w&&(w=0),A>r&&(A=r);wf;d--)h=l[d-1],l[d]=h,e[h]=d;l[f]=a;e[a]=f}}}return b};return a}();return e}(function(){var f={},k="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(e,n,l,K,d){l=k?URL.createObjectURL(new Blob(["("+l.toString()+")()"],{type:"text/javascript"})): -e+".es5.js";e+="-"+n;f[e]||(f[e]=[]);f[e][d]=new Worker(l);f[e][d].onmessage=K;console.log("Register Worker: "+e+"@"+d);return f[e][d]}}()),this); +'use strict';function S(h){var l=0;return function(){return l=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 A(a,b){for(var c=a.length,g=M(b),k=[],p=0,e=0;p=e&&(a=a[f-(k+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=g);return k}function Q(a,b){if(a)for(var c=Object.keys(a),g=0,k=c.length;ga?1:a?-1:0}function da(a,b){a=a[G];b=b[G];return ab?1:0}function ea(a,b){for(var c=G.length,g=0;gb?1:0}function O(a,b,c,g){c=[];var k=a.length;if(1b&&(c=c.slice(0,b)));return c}function L(a){return"string"===typeof a}function I(a){return a.constructor=== +Array}function M(a){return"function"===typeof a}function K(a){return"object"===typeof a}function F(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.c[e]=""+this.w,c&&c(),this;if(!k){if(this.async&&"function"!==typeof importScripts){var f=this;e=new Promise(function(c){setTimeout(function(){f.add(a,b,null,g,!0);f=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=M(c)?c(b):b.split(W);this.filter&&(k=A(k,this.filter));var d=C();d._ctx=C();for(var h=k.length,r=this.threshold,q=this.depth,n=this.f,m=this.o,v=this.H,B=0;B +w;z--)E=y.substring(w,z),H(m,d,E,a,t,D,r,n-1);break;default:if(x=H(m,d,y,a,1,D,r,n-1),q&&1=r)for(x=d._ctx[y]||(d._ctx[y]=C()),y=this.u[y]||(this.u[y]=U(n-(r||0))),D=B-q,E=B+q+1,0>D&&(D=0),E>h&&(E=h);Df;d--)m=h[d- +1],h[d]=m,e[m]=d;h[f]=a;e[a]=f}}}return b};return a}();return f}(function(){var h={},l="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(f,m,A,J,d){A=l?URL.createObjectURL(new Blob(["("+A.toString()+")()"],{type:"text/javascript"})):f+".es5.js";f+="-"+m;h[f]||(h[f]=[]);h[f][d]=new Worker(A);h[f][d].onmessage=J;console.log("Register Worker: "+f+"@"+d);return h[f][d]}}()),this); diff --git a/dist/flexsearch.light.js b/dist/flexsearch.light.js index c2ff7af..4bcbdb1 100644 --- a/dist/flexsearch.light.js +++ b/dist/flexsearch.light.js @@ -1,18 +1,18 @@ /* - FlexSearch v0.5.1 + FlexSearch v0.5.2 Copyright 2019 Nextapps GmbH Author: Thomas Wilkerling Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';(function(d,l,v){let t;(t=v.define)&&t.amd?t([],function(){return l}):(t=v.modules)?t[d.toLowerCase()]=l:"object"===typeof exports?module.exports=l:v[d]=l})("FlexSearch",function(){function d(a,c){const b=c?c.id:a&&a.id;this.id=b||0===b?b:G++;this.init(a,c);l(this,"index",function(){return this.b});l(this,"length",function(){return Object.keys(this.b).length})}function l(a,c,b){Object.defineProperty(a,c,{get:b})}function v(a,c){for(let b=0;b=g&&(a=a[h-(e+.5>>0)],a=a[b]||(a[b]=[]),a[a.length]=f);return e}function A(a,c){if(a){const b=Object.keys(a);for(let f=0,e=b.length;fa?1:a?-1:0}function I(a,c){a=a.length-c.length;return 0>a?-1:a?1:0}function z(a){return"function"=== -typeof a}function y(a){return"undefined"===typeof a}function C(a){const c=Array(a);for(let b=0;b -k;c--)m=p.substring(k,c),t(q,f,m,a,b,h,e,r-1)}break;default:if(g=t(q,f,p,a,1,h,e,r-1),n&&1=e)for(g=f._ctx[p]||(f._ctx[p]=u()),p=this.f[p]||(this.f[p]=C(r-(e||0))),h=d-n,m=d+n+1,0>h&&(h=0),m>x&&(m=x);hc&&(g=g.slice(0,c)));d=g}return d};d.prototype.clear=function(){return this.destroy().init()};d.prototype.destroy=function(){this.h=this.f=this.b=null;return this};const w={icase:function(a){return a.toLowerCase()}};return d}(!1),this); +'use strict';(function(e,u,r){let l;(l=r.define)&&l.amd?l([],function(){return u}):(l=r.modules)?l[e.toLowerCase()]=u:"object"===typeof exports?module.exports=u:r[e]=u})("FlexSearch",function(){function e(a,c){const b=c?c.id:a&&a.id;this.id=b||0===b?b:I++;this.init(a,c);r(this,"index",function(){return this.b});r(this,"length",function(){return Object.keys(this.b).length})}function u(a,c){const b=a.length,f=x(c),d=[];for(let n=0,g=0;n=g&&(a=a[h-(d+.5>>0)],a=a[b]||(a[b]=[]),a[a.length]=f);return d}function C(a,c){if(a){const b=Object.keys(a);for(let f=0,d=b.length;fa?1:a?-1:0}function z(a){return"string"===typeof a}function x(a){return"function"===typeof a}function A(a){return"undefined"===typeof a}function E(a){const c=Array(a);for(let b=0;bk;c--)m=n.substring(k,c),y(B,f,m,a,b,h,v,q-1)}break;default:if(g=y(B,f,n,a,1,h,v,q-1),l&&1=v)for(g=f._ctx[n]||(f._ctx[n]=t()),n=this.f[n]||(this.f[n]=E(q-(v||0))),h=e-l,m=e+l+1,0>h&&(h=0),m>d&&(m=d);hc&&(g=g.slice(0,c)));e=g}return e};e.prototype.clear=function(){return this.destroy().init()};e.prototype.destroy=function(){this.h=this.f=this.b=null;return this};const w={icase:function(a){return a.toLowerCase()}};return e}(!1),this); diff --git a/dist/flexsearch.min.js b/dist/flexsearch.min.js index df8a329..dee2187 100644 --- a/dist/flexsearch.min.js +++ b/dist/flexsearch.min.js @@ -1,38 +1,39 @@ /* - FlexSearch v0.5.1 + FlexSearch v0.5.2 Copyright 2019 Nextapps GmbH Author: Thomas Wilkerling Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';(function(w,F,g){let y;(y=g.define)&&y.amd?y([],function(){return F}):(y=g.modules)?y[w.toLowerCase()]=F:"object"===typeof exports?module.exports=F:g[w]=F})("FlexSearch",function U(w){function g(a,b){const c=b?b.id:a&&a.id;this.id=c||0===c?c:V++;this.init(a,b);K(this,"index",function(){return this.b});K(this,"length",function(){return Object.keys(this.b).length})}function y(a,b,c,d){this.u!==this.g&&(this.l=this.l.concat(c),this.u++,d&&this.l.length>=d&&(this.u=this.g),this.G&&this.u=== -this.g&&(this.cache&&this.o.set(b,this.l),this.G(this.l),this.l=[]));return this}function B(a,b){a=a.concat.apply([],a);b&&(G(b)||(z=b.split(":"),1=k&&(a=a[h-(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;da?1:a?-1:0}function Z(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function X(a,b){a=a[z];b=b[z];return ab?1:0}function W(a,b){const c=z.length;for(let d=0;db?1:0}function aa(a,b,c,d,e){c=[];let l;const k=a.length;if(1b&&(c=c.slice(0,b));return c}function H(a){return"string"===typeof a}function x(a){return a.constructor=== -Array}function G(a){return"function"===typeof a}function A(a){return"object"===typeof a}function v(a){return"undefined"===typeof a}function P(a){const b=Array(a);for(let c=0;c=this.m.length&&(this.D=0),this.m[this.D].postMessage({add:!0,id:a,content:b}),this.b[l]=""+this.D,c&&c(),this;if(!e){if(this.async&&"function"!==typeof importScripts){let e=this;l=new Promise(function(c){setTimeout(function(){e.add(a,b,null,d,!0);e=null;c()})});if(c)l.then(c);else return l;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=G(c)?c(b):b.split(R);const m=r();m._ctx=r();const p=this.threshold,C=this.depth,t=this.c,q=this.i,D=e.length,L=this.F;for(let b=0;bg;c--)n=k.substring(g,c),J(q,m,n,a,b,f,p,t-1)}break;default:if(h=J(q, -m,k,a,1,f,p,t-1),C&&1=p)for(h=m._ctx[k]||(m._ctx[k]=r()),k=this.j[k]||(this.j[k]=P(t-(p||0))),f=b-C,n=b+C+1,0>f&&(f=0),n>D&&(n=D);fc;d--)e=f[d-1],f[d]=e,b[e]=d;f[c]=a;b[a]=c}}}return b};return a}();return g}(function(){const w= -{},F="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(g,y,B,K,f){B=F?URL.createObjectURL(new Blob(["("+B.toString()+")()"],{type:"text/javascript"})):g+".min.js";g+="-"+y;w[g]||(w[g]=[]);w[g][f]=new Worker(B);w[g][f].onmessage=K;return w[g][f]}}()),this); +'use strict';(function(x,G,h){let y;(y=h.define)&&y.amd?y([],function(){return G}):(y=h.modules)?y[x.toLowerCase()]=G:"object"===typeof exports?module.exports=G:h[x]=G})("FlexSearch",function X(x){function h(a,b){const c=b?b.id:a&&a.id;this.id=c||0===c?c:Y++;this.init(a,b);H(this,"index",function(){return this.b});H(this,"length",function(){return Object.keys(this.b).length})}function y(a,b,c,d){this.v!==this.g&&(this.o=this.o.concat(c),this.v++,d&&this.o.length>=d&&(this.v=this.g),this.v===this.g&& +(this.cache&&this.l.set(b,this.o),this.G&&this.G(this.o)));return this}function I(a,b){const c=a.length,d=D(b),e=[];for(let f=0,k=0;f=k&&(a=a[p-(e+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=d);return e}function P(a,b){if(a){const c=Object.keys(a);for(let d=0,e=c.length;da?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;db?1:0}function R(a,b,c,d){c=[];let e;const f= +a.length;if(1b&&(c=c.slice(0, +b)));return c}function C(a){return"string"===typeof a}function w(a){return a.constructor===Array}function D(a){return"function"===typeof a}function B(a){return"object"===typeof a}function v(a){return"undefined"===typeof a}function S(a){const b=Array(a);for(let c=0;c=this.m.length&&(this.D=0),this.m[this.D].postMessage({add:!0,id:a,content:b}),this.b[f]=""+this.D,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=D(c)?c(b):b.split(U);this.filter&&(e=I(e,this.filter));const h=u();h._ctx=u();const q=e.length,n=this.threshold,z=this.depth,F=this.c,M=this.i,O=this.F;for(let b=0;bl;c--)m=k.substring(l,c),L(M,h,m,a,b,g,n,F-1)}break;default:if(p=L(M,h,k,a,1,g,n,F-1),z&&1=n)for(p=h._ctx[k]||(h._ctx[k]=u()),k=this.j[k]||(this.j[k]=S(F-(n||0))),g=b-z,m=b+z+1,0>g&&(g=0),m>q&&(m=q);gc;d--)e=f[d-1],f[d]=e,b[e]=d;f[c]=a;b[a]=c}}}return b};return a}();return h}(function(){const x={},G="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(h,y,I,K,H){I=G?URL.createObjectURL(new Blob(["("+I.toString()+")()"],{type:"text/javascript"})):h+".min.js";h+="-"+y;x[h]||(x[h]=[]);x[h][H]=new Worker(I);x[h][H].onmessage=K;return x[h][H]}}()), +this); diff --git a/dist/flexsearch.node.js b/dist/flexsearch.node.js index 9ea08db..7b08a95 100644 --- a/dist/flexsearch.node.js +++ b/dist/flexsearch.node.js @@ -1,34 +1,35 @@ /* - FlexSearch v0.5.1 + FlexSearch v0.5.2 Copyright 2019 Nextapps GmbH Author: Thomas Wilkerling Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';(function(h,y,D){let e;(e=D.define)&&e.amd?e([],function(){return y}):(e=D.modules)?e[h.toLowerCase()]=y:"object"===typeof exports?module.exports=y:D[h]=y})("FlexSearch",function(){function h(a,b){const c=b?b.id:a&&a.id;this.id=c||0===c?c:S++;this.init(a,b);D(this,"index",function(){return this.c});D(this,"length",function(){return Object.keys(this.c).length})}function y(a,b){a=a.concat.apply([],a);b&&(E(b)||(z=b.split(":"),1=g&&(a=a[k-(f+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=d);return f}function L(a,b){if(a){const c=Object.keys(a);for(let d=0,f=c.length;da?1:a?-1:0}function W(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function U(a,b){a=a[z];b=b[z];return ab?1:0}function T(a,b){const c=z.length;for(let d= -0;db?1:0}function X(a,b,c,d,f){c=[];let l;const g=a.length;if(1b&&(c=c.slice(0,b));return c}function F(a){return"string"===typeof a}function x(a){return a.constructor===Array}function E(a){return"function"===typeof a}function A(a){return"object"===typeof a}function v(a){return"undefined"===typeof a}function N(a){const b=Array(a);for(let c=0;cm;c--)n=g.substring(m,c),H(I,p,n,a,b,e,q,u-1)}break;default:if(k=H(I,p,g,a,1,e,q,u-1),h&&1=q)for(k=p._ctx[g]||(p._ctx[g]=t()),g=this.i[g]||(this.i[g]=N(u-(q||0))),e=b-h,n=b+h+1,0>e&&(e=0),n>B&&(n=B);ec;d--)f=e[d-1],e[d]=f,b[f]=d;e[c]=a;b[a]=c}}}return b};return a}();return h}(!1),this); +'use strict';(function(h,C,D){let z;(z=D.define)&&z.amd?z([],function(){return C}):(z=D.modules)?z[h.toLowerCase()]=C:"object"===typeof exports?module.exports=C:D[h]=C})("FlexSearch",function(){function h(a,b){const c=b?b.id:a&&a.id;this.id=c||0===c?c:T++;this.init(a,b);z(this,"index",function(){return this.c});z(this,"length",function(){return Object.keys(this.c).length})}function C(a,b){const c=a.length,d=E(b),e=[];for(let f=0,k=0;f=k&&(a=a[p-(e+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=d);return e}function L(a,b){if(a){const c=Object.keys(a);for(let d=0,e=c.length;da?1:a?-1:0}function V(a,b){a=a[y];b=b[y];return ab?1:0}function U(a,b){const c=y.length;for(let d=0;db?1:0}function N(a,b,c,d){c=[];let e;const f=a.length;if(1b&&(c=c.slice(0,b)));return c}function B(a){return"string"===typeof a}function v(a){return a.constructor===Array}function E(a){return"function"===typeof a}function A(a){return"object"===typeof a}function w(a){return"undefined"=== +typeof a}function O(a){const b=Array(a);for(let c=0;cl;c--)m=k.substring(l,c),H(I,r,m,a,b,g,n,h-1)}break;default:if(p=H(I,r,k,a,1,g,n,h-1),x&&1=n)for(p=r._ctx[k]||(r._ctx[k]=t()),k=this.i[k]||(this.i[k]=O(h-(n||0))),g=b-x,m=b+x+1,0>g&&(g=0),m>q&&(m=q);gc;d--)e=f[d-1],f[d]=e,b[e]=d;f[c]=a;b[a]=c}}}return b};return a}();return h}(!1),this); diff --git a/flexsearch.js b/flexsearch.js index b9b9d4a..11059e7 100644 --- a/flexsearch.js +++ b/flexsearch.js @@ -1,5 +1,5 @@ /**! - * @preserve FlexSearch v0.5.1 + * @preserve FlexSearch v0.5.2 * Copyright 2019 Nextapps GmbH * Author: Thomas Wilkerling * Released under the Apache 2.0 Licence @@ -129,7 +129,7 @@ * @const {RegExp} */ - const regex_split = regex("\\W+"); // regex("[\\s/-_]"); + const regex_split = /\W+/; //regex("\\W+"); // regex("[\\s/-_]"); const filter = {}; const stemmer = {}; @@ -262,7 +262,7 @@ return global_encoder[name](value); }; - function worker_handler(id, query, result, limit){ + function worker_handler(id, query, result, limit, where, cursor, suggest){ if(this._task_completed !== this.worker){ @@ -276,15 +276,22 @@ this._task_completed = this.worker; } - if(this._current_callback && (this._task_completed === this.worker)){ + if(this._task_completed === this.worker){ + + // this._task_result = intersect(this._task_result, where ? 0 : limit, cursor, suggest); if(this.cache){ this._cache.set(query, this._task_result); } - this._current_callback(this._task_result); - this._task_result = []; + if(this._current_callback){ + + this._current_callback(this._task_result); + } + + //this._task_completed = 0; + //this._task_result = []; } } @@ -525,14 +532,28 @@ if((custom = options["filter"])) { + if(is_string(custom)){ + + custom = filter[custom]; + } + + if(is_array(custom)){ + + custom = init_filter(custom, this.encoder); + } + /** @private */ - this.filter = init_filter(filter[custom] || custom, this.encoder); + this.filter = custom; } if((custom = options["stemmer"])) { /** @private */ - this.stemmer = init_stemmer(stemmer[custom] || custom, this.encoder); + this.stemmer = init_stemmer( + + is_string(custom) ? stemmer[custom] : custom, + this.encoder + ); } let doc; @@ -565,8 +586,8 @@ options["doc"] = null; - const index = doc["index"] = []; - const ref = doc["ref"] = {}; + const index = doc["index"] = {}; + const keys = doc["keys"] = []; let field = doc["field"]; let tag = doc["tag"]; @@ -638,21 +659,23 @@ for(let i = 0; i < field.length; i++){ - if(!is_array(field[i])){ + const ref = field[i]; + + if(!is_array(ref)){ if(has_custom){ - options = has_custom[field[i]]; + options = has_custom[ref]; } - ref[field[i]] = i; - field[i] = field[i].split(":"); + keys[i] = ref; + field[i] = ref.split(":"); } // TODO: move fields to main index to provide pagination - index[i] = new FlexSearch(options); - index[i]._doc = this._doc; + index[ref] = new FlexSearch(options); + index[ref]._doc = this._doc; // if(SUPPORT_WHERE && tag){ // @@ -725,35 +748,6 @@ value = this.encoder(value); } - // TODO completely filter out words actually can break the context chain - /* - if(value && this.filter){ - - const words = value.split(" "); - //const final = ""; - - for(const i = 0; i < words.length; i++){ - - const word = words[i]; - const filter = this.filter[word]; - - if(filter){ - - //const length = word.length - 1; - - words[i] = filter; - //words[i] = word[0] + (length ? word[1] : ""); - //words[i] = "~" + word[0]; - //words.splice(i, 1); - //i--; - //final += (final ? " " : "") + word; - } - } - - value = words.join(" "); // final; - } - */ - if(value && this.stemmer){ value = replace(value, this.stemmer); @@ -787,6 +781,26 @@ return this; }; + function filter_words(words, filter){ + + const length = words.length; + const has_function = is_function(filter); + const filtered = []; + + for(let i = 0, count = 0; i < length; i++){ + + const word = words[i]; + + if((has_function && filter(word)) || + (!has_function && !filter[word])){ + + filtered[count++] = word; + } + } + + return filtered; + } + /** * @param {number|string} id * @param {string|Function} content @@ -898,7 +912,7 @@ const tokenizer = this.tokenize; - const words = ( + let words = ( is_function(tokenizer) ? @@ -914,14 +928,19 @@ ) ); + if(this.filter){ + + words = filter_words(words, this.filter); + } + const dupes = create_object(); dupes["_ctx"] = create_object(); + const word_length = words.length; const threshold = this.threshold; const depth = this.depth; const resolution = this.resolution; const map = this._map; - const word_length = words.length; const rtl = this.rtl; // tokenize @@ -1109,6 +1128,7 @@ else{ const index = this.doc["index"]; + const keys = this.doc["keys"]; const tags = this.doc["tag"]; let tree = this.doc["id"]; let id; @@ -1145,15 +1165,15 @@ delete this._doc[id]; - for(let z = 0, length = index.length; z < length; z++){ + for(let z = 0, length = keys.length; z < length; z++){ if(z === length - 1){ - return index[z].remove(id, callback); + return index[keys[z]].remove(id, callback); } else{ - index[z].remove(id); + index[keys[z]].remove(id); } } } @@ -1177,7 +1197,7 @@ this._doc[id] = doc; - const self = index[i]; + const self = index[keys[i]]; let fn; @@ -1348,11 +1368,31 @@ let field_to_sort; - // TODO: apply intersect here + function enrich_documents(arr, docs){ + + const length = arr.length; + const result = new Array(length); + + for(let i = 0; i < length; i++){ + + result[i] = docs[arr[i]]; + } + + return result; + } + + function merge_and_sort(query, result, sort, limit, where, cursor){ - function merge_and_sort(arrays, sort){ + const doc = this._doc; + const suggest = SUPPORT_SUGGESTIONS && this.suggest; - arrays = arrays.concat.apply([], arrays); + result = intersect(result, where ? 0 : limit, cursor, suggest); + result = enrich_documents(result, doc); + + if(where){ + + result = this.where(where, null, limit, result); + } if(sort){ @@ -1371,10 +1411,15 @@ } } - arrays.sort(sort); + result.sort(sort); } - return arrays; + if(SUPPORT_CACHE && this.cache){ + + this._cache.set(query, result); + } + + return result; } /** @@ -1433,8 +1478,12 @@ if(SUPPORT_DOCUMENTS){ //boost = query["boost"]; - where = query["where"]; sort = query["sort"]; + + if(SUPPORT_WHERE){ + + where = query["where"]; + } } //cursor = this.paging && query["cursor"]; @@ -1445,7 +1494,6 @@ if(SUPPORT_DOCUMENTS && this.doc){ - const doc_ref = this.doc["ref"]; const doc_idx = this.doc["index"]; let queries; @@ -1454,6 +1502,11 @@ if(field){ _query["field"] = null; + + if(!is_array(field)){ + + field = [field]; + } } else if(is_array(_query)){ @@ -1467,60 +1520,45 @@ } else{ - field = get_keys(doc_ref); + field = this.doc["keys"]; } - if(is_object(field)){ - - if(sort){ - - _query["sort"] = null; - } - - if(!is_array(field)){ + if(sort){ - field = [field]; - } + _query["sort"] = null; + } - const len = field.length; + const len = field.length; - for(let i = 0; i < len; i++){ + for(let i = 0; i < len; i++){ - if(queries){ + if(queries){ - _query = queries[i]; - } + _query = queries[i]; + } - const ref = doc_ref[field[i]]; + result[i] = doc_idx[field[i]].search(_query); + } - // TODO: Support Field-Merging (return array before intersection and apply here) - result[i] = doc_idx[ref].search(_query); - } + if(callback){ - if(SUPPORT_ASYNC && callback){ + return callback(merge_and_sort.call(this, query, result, sort, limit, where, cursor)); + } + else if(SUPPORT_ASYNC && this.async){ - return callback(merge_and_sort(result, sort)); - } - else if(SUPPORT_ASYNC && this.async){ + const self = this; - return new Promise(function(resolve){ + return new Promise(function(resolve){ - Promise.all(/** @type {!Iterable} */ (result)).then(function(values){ + Promise.all(/** @type {!Iterable} */ (result)).then(function(values){ - resolve(merge_and_sort(values, sort)); - }); + resolve(merge_and_sort.call(self, query, values, sort, limit, where, cursor)); }); - } - else{ - - return merge_and_sort(result, sort); - } + }); } else{ - const ref = doc_ref[field]; - - return doc_idx[ref].search(_query, callback); + return merge_and_sort.call(this, query, result, sort, limit, where, cursor); } } @@ -1548,8 +1586,9 @@ "search": true, "limit": limit, - //"cursor": cursor, + "cursor": cursor, "threshold": threshold, + "where": where, "content": query }); } @@ -1641,7 +1680,7 @@ const tokenizer = this.tokenize; - const words = ( + let words = ( is_function(tokenizer) ? @@ -1658,6 +1697,11 @@ ) ); + if(this.filter){ + + words = filter_words(words, this.filter); + } + const length = words.length; let found = true; const check = []; @@ -1793,26 +1837,16 @@ // Not handled by intersection: - result = intersect(check, limit, cursor, SUPPORT_DOCUMENTS && this._doc, SUPPORT_SUGGESTIONS && this.suggest); + result = intersect(check, limit, cursor, /*SUPPORT_DOCUMENTS && this._doc,*/ SUPPORT_SUGGESTIONS && this.suggest); // Handled by intersection: //result = intersect_3d(check, limit, this.suggest); } - if(SUPPORT_WHERE && where){ - - result = this.where(where, null, limit, result); - } - - if(SUPPORT_DOCUMENTS && sort){ - - result = merge_and_sort([result], sort); - } - // store result to cache - if(SUPPORT_CACHE && this.cache){ + if(SUPPORT_CACHE && this.cache && (!SUPPORT_DOCUMENTS || !this.doc)){ this._cache.set(query, result); } @@ -2092,13 +2126,14 @@ if(SUPPORT_DOCUMENTS && this.doc){ - const index = this._doc["index"]; + const keys = this.doc["keys"]; - for(let i = 0; i < index.length; i++){ + for(let i = 0; i < keys.length; i++){ - index.destroy(); + this.doc.index[keys[i]].destroy(); } + this.doc = this._doc = null; } @@ -2116,19 +2151,19 @@ if(SUPPORT_DOCUMENTS && this.doc){ - const index = this.doc["index"]; - const length = index.length; + const keys = this.doc["keys"]; + const length = keys.length; const payload = new Array(length + 1); let i = 0; - for(; i < index.length; i++){ + for(; i < keys.length; i++){ + + const idx = this.doc.index[keys[i]]; payload[i] = [ - index[i]._map, - index[i]._ctx, - index[i]._ids + idx._map, idx._ctx, idx._ids ]; } @@ -2155,12 +2190,12 @@ if(SUPPORT_DOCUMENTS && this.doc){ - const index = this.doc["index"]; - const length = index.length; + const keys = this.doc["keys"]; + const length = keys.length; for(let i = 0; i < length; i++){ - const idx = index[i]; + const idx = this.doc.index[keys[i]]; idx._map = payload[i][0]; idx._ctx = payload[i][1]; @@ -2175,7 +2210,7 @@ this._map = payload[0]; this._ctx = payload[1]; this._ids = payload[2]; - this._doc = payload[3]; + //this._doc = payload[3]; } }; } @@ -2872,14 +2907,11 @@ const final = create_object(); - if(words){ + for(let i = 0; i < words.length; i++){ - for(let i = 0; i < words.length; i++){ + const word = encoder ? encoder(words[i]) : words[i]; - const word = encoder ? encoder(words[i]) : words[i]; - - final[word] = String.fromCharCode((65000 - words.length) + i); - } + final[word] = 1; // String.fromCharCode((65000 - words.length) + i); // mask filtered words? } return final; @@ -2895,25 +2927,23 @@ const final = []; - if(stem){ - - for(const key in stem){ + for(const key in stem){ - if(stem.hasOwnProperty(key)){ + if(stem.hasOwnProperty(key)){ - const tmp = encoder ? encoder(key) : key; + const tmp = encoder ? encoder(key) : key; - final.push( + final.push( - regex("(?=.{" + (tmp.length + 3) + ",})" + tmp + "$"), + //regex("(?=.{" + tmp.length + ",})" + tmp + "$"), + regex(tmp + "($|\\W)"), - encoder ? + encoder ? - encoder(stem[key]) - : - stem[key] - ); - } + encoder(stem[key]) + : + stem[key] + ); } } @@ -2921,8 +2951,8 @@ } /** - * @param {string} a - * @param {string} b + * @param {Array} a + * @param {Array} b * @returns {number} */ @@ -3019,12 +3049,11 @@ * @param {!Array>} arrays * @param {number=} limit * @param {number=} cursor - * @param {Object=} docs * @param {boolean=} suggest * @returns {Array} */ - function intersect(arrays, limit, cursor, docs, suggest) { + function intersect(arrays, limit, cursor, /*docs,*/ suggest) { let result = []; let suggestions; @@ -3032,9 +3061,10 @@ if(length_z > 1){ - // pre-sort arrays by length up + // pre-sort arrays - arrays.sort(sort_by_length_up); + //TODO: test strategy + //arrays.sort(sort_by_length_down); // fill initial map @@ -3079,7 +3109,8 @@ if(is_final_loop){ - result[count++] = docs ? docs[tmp] : tmp; + //result[count++] = docs ? docs[tmp] : tmp; + result[count++] = tmp; if(limit && (count === limit)){ @@ -3142,7 +3173,8 @@ for(i = 0, length = tmp.length; i < length; i++){ - result[count++] = docs ? docs[tmp[i]] : tmp[i]; + //result[count++] = docs ? docs[tmp[i]] : tmp[i]; + result[count++] = tmp[i]; if(limit && (count === limit)){ @@ -3156,24 +3188,24 @@ } else if(length_z){ - if(docs){ - - const arr = arrays[0]; - let length = arr.length; - - if(limit && (limit < length)){ - - length = limit; - } - - result = new Array(length); - - for(let i = 0; i < length; i++){ - - result[i] = docs[arr[i]]; - } - } - else{ + // if(docs){ + // + // const arr = arrays[0]; + // let length = arr.length; + // + // if(limit && (limit < length)){ + // + // length = limit; + // } + // + // result = new Array(length); + // + // for(let i = 0; i < length; i++){ + // + // result[i] = docs[arr[i]]; + // } + // } + // else{ result = arrays[0]; @@ -3183,7 +3215,7 @@ result = result.slice(0, limit); } - } + //} // Note: handle references to the original index array //return result.slice(0); @@ -3410,101 +3442,6 @@ return Object.keys(obj); } - /** - * @param {FlexSearch} ref - */ - - /* - function runner(ref){ - - const async = ref.async; - let current; - - if(async){ - - ref.async = false; - } - - if(ref._stack_keys.length){ - - const start = time(); - let key; - - // TODO: optimize shift() using a loop and splice() - while((key = ref._stack_keys.shift()) || (key === 0)){ - - current = ref._stack[key]; - - switch(current[0]){ - - case enum_task.add: - - ref.add(current[1], current[2]); - break; - - // Note: Update is handled by .remove() + .add() - // - // case enum_task.update: - // - // ref.update(current[1], current[2]); - // break; - - case enum_task.remove: - - ref.remove(current[1]); - break; - } - - delete ref._stack[key]; - - if((time() - start) > 100){ - - break; - } - } - - if(ref._stack_keys.length){ - - register_task(ref); - } - } - - if(async){ - - ref.async = async; - } - } - */ - - /** - * @param {FlexSearch} ref - */ - - /* - function register_task(ref){ - - ref._timer || ( - - ref._timer = queue(function(){ - - ref._timer = 0; - - runner(ref); - - }, 1, "@" + ref.id) - ); - } - */ - - /** - * @returns {number} - */ - - function time(){ - - return Date.now(); - } - /** * https://jsperf.com/comparison-object-index-type * @param {number} count @@ -3550,7 +3487,8 @@ { "limit": data["limit"], - "threshold": data["threshold"] + "threshold": data["threshold"], + "where": data["where"] } : data["limit"] @@ -3635,7 +3573,16 @@ if(data && data["result"]){ - callback(data["id"], data["content"], data["result"], data["limit"]); + callback( + + data["id"], + data["content"], + data["result"], + data["limit"], + data["where"], + data["cursor"], + data["suggest"] + ); } }, diff --git a/package.json b/package.json index d5c5f65..35b93ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flexsearch", - "version": "0.5.1", + "version": "0.5.2", "description": "Next-Generation full text search library with zero dependencies.", "homepage": "https://github.com/nextapps-de/flexsearch/", "author": "Thomas Wilkerling", diff --git a/test/test.es6.js b/test/test.es6.js index 072f531..fb73c3d 100644 --- a/test/test.es6.js +++ b/test/test.es6.js @@ -71,8 +71,8 @@ describe("Index Multi-Field Documents (ES6)", function(){ await index.add(data); - expect(index.doc.index[0].length).to.equal(3); - expect(index.doc.index[1].length).to.equal(3); + expect(index.doc.index["data:title"].length).to.equal(3); + expect(index.doc.index["data:body"].length).to.equal(3); expect(await index.search({field: "data:body", query: "body"})).to.have.members(data); expect(await index.search({field: "data:title", query: "title"})).to.have.members(data); @@ -80,23 +80,34 @@ describe("Index Multi-Field Documents (ES6)", function(){ expect(await index.search({field: "data:body", query: "title"})).to.have.lengthOf(0); expect(await index.search({field: "data:title", query: "body"})).to.have.lengthOf(0); - expect(await index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data); - expect(await index.search({field: ["data:body", "data:title"], query: "title"})).to.have.members(data); + //TODO: provide logical operator "OR" + // expect(await index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data); + // expect(await index.search({field: ["data:body", "data:title"], query: "title"})).to.have.members(data); + expect(await index.search({field: ["data:body"], query: "body"})).to.have.members(data); + expect(await index.search({field: "data:title", query: "title"})).to.have.members(data); - expect(await index.search({query: "body"})).to.have.members(data); - expect(await index.search("title")).to.have.members(data); + //TODO: provide logical operator "OR" + // expect(await index.search({query: "body"})).to.have.members(data); + // expect(await index.search("title")).to.have.members(data); + expect(await index.search({field: ["data:body"], query: "body"})).to.have.members(data); + expect(await index.search({field: "data:title", query: "title"})).to.have.members(data); await index.update(update); - expect(await index.search("foo")).not.to.have.members(data); - expect(await index.search("bar")).not.to.have.members(data); - expect(await index.search("foo")).to.have.members(update); - expect(await index.search("bar")).to.have.members(update); + //TODO: provide logical operator "OR" + // expect(await index.search("foo")).not.to.have.members(data); + // expect(await index.search("bar")).not.to.have.members(data); + // expect(await index.search("foo")).to.have.members(update); + // expect(await index.search("bar")).to.have.members(update); + expect(await index.search("foo", {field: "data:title"})).not.to.have.members(data); + expect(await index.search("bar", {field: "data:body"})).not.to.have.members(data); + expect(await index.search("foo", {field: "data:title"})).to.have.members(update); + expect(await index.search("bar", {field: "data:body"})).to.have.members(update); await index.remove(update); - expect(await index.doc.index[0].length).to.equal(0); - expect(await index.doc.index[1].length).to.equal(0); + expect(await index.doc.index["data:title"].length).to.equal(0); + expect(await index.doc.index["data:body"].length).to.equal(0); }); it("Should have been indexed properly (Worker)", async function(){ @@ -117,8 +128,8 @@ describe("Index Multi-Field Documents (ES6)", function(){ await index.add(data); - expect(index.doc.index[0].length).to.equal(3); - expect(index.doc.index[1].length).to.equal(3); + expect(index.doc.index["data:title"].length).to.equal(3); + expect(index.doc.index["data:body"].length).to.equal(3); expect(await index.search({field: "data:body", query: "body"})).to.have.members(data); expect(await index.search({field: "data:title", query: "title"})).to.have.members(data); @@ -126,22 +137,33 @@ describe("Index Multi-Field Documents (ES6)", function(){ expect(await index.search({field: "data:body", query: "title"})).to.have.lengthOf(0); expect(await index.search({field: "data:title", query: "body"})).to.have.lengthOf(0); - expect(await index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data); - expect(await index.search({field: ["data:body", "data:title"], query: "title"})).to.have.members(data); + //TODO: provide logical operator "OR" + // expect(await index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data); + // expect(await index.search({field: ["data:body", "data:title"], query: "title"})).to.have.members(data); + expect(await index.search({field: ["data:body"], query: "body"})).to.have.members(data); + expect(await index.search({field: "data:title", query: "title"})).to.have.members(data); - expect(await index.search({query: "body"})).to.have.members(data); - expect(await index.search("title")).to.have.members(data); + //TODO: provide logical operator "OR" + // expect(await index.search({query: "body"})).to.have.members(data); + // expect(await index.search("title")).to.have.members(data); + expect(await index.search({query: "body", field: "data:body"})).to.have.members(data); + expect(await index.search("title", {field: "data:title"})).to.have.members(data); await index.update(update); - expect(await index.search("foo")).not.to.have.members(data); - expect(await index.search("bar")).not.to.have.members(data); - expect(await index.search("foo")).to.have.members(update); - expect(await index.search("bar")).to.have.members(update); + //TODO: provide logical operator "OR" + // expect(await index.search("foo")).not.to.have.members(data); + // expect(await index.search("bar")).not.to.have.members(data); + // expect(await index.search("foo")).to.have.members(update); + // expect(await index.search("bar")).to.have.members(update); + expect(await index.search("foo", {field: "data:title"})).not.to.have.members(data); + expect(await index.search("bar", {field: "data:body"})).not.to.have.members(data); + expect(await index.search("foo", {field: "data:title"})).to.have.members(update); + expect(await index.search("bar", {field: "data:body"})).to.have.members(update); await index.remove(update); - expect(await index.doc.index[0].length).to.equal(0); - expect(await index.doc.index[1].length).to.equal(0); + expect(await index.doc.index["data:title"].length).to.equal(0); + expect(await index.doc.index["data:body"].length).to.equal(0); }); }); diff --git a/test/test.js b/test/test.js index cd1d0c2..3c3026a 100644 --- a/test/test.js +++ b/test/test.js @@ -1009,6 +1009,92 @@ describe("Options", function(){ } }); +// ------------------------------------------------------------------------ +// Filter Tests +// ------------------------------------------------------------------------ + +describe("Filter", function(){ + + it("Should have been filtered properly", function(){ + + var index = new FlexSearch({ + encode: "icase", + tokenize: "strict", + filter: ["in", "the"] + }); + + index.add(0, "Today in the morning."); + + expect(index.length).to.equal(1); + expect(index.search("today in the morning.")).to.include(0); + expect(index.search("today morning")).to.include(0); + expect(index.search("in the")).to.have.length(0); + }); + + it("Should have been filtered properly (custom function)", function(){ + + var index = new FlexSearch({ + encode: "icase", + tokenize: "strict", + filter: function(word){ + return word.length > 3; + } + }); + + index.add(0, "Today in the morning."); + + expect(index.length).to.equal(1); + expect(index.search("today in the morning.")).to.include(0); + expect(index.search("today morning")).to.include(0); + expect(index.search("in the")).to.have.length(0); + }); +}); + +describe("Stemmer", function(){ + + it("Should have been stemmed properly", function(){ + + var index = new FlexSearch({ + encode: "icase", + tokenize: "reverse", + stemmer: { + "ization": "ize", + "tional": "tion" + } + }); + + index.add(0, "Just a multinational colonization."); + + expect(index.length).to.equal(1); + expect(index.search("Just a multinational colonization.")).to.include(0); + expect(index.search("multinational colonization")).to.include(0); + expect(index.search("tional tion")).to.have.length(0); + }); + + it("Should have been stemmed properly (custom function)", function(){ + + var stems = { + "ization": "ize", + "tional": "tion" + }; + + var index = new FlexSearch({ + encode: "icase", + tokenize: "strict", + stemmer: function(word){ + return stems[word] || word; + } + }); + + index.add(0, "Just a multinational colonization."); + + expect(index.length).to.equal(1); + expect(index.search("Just a multinational colonization.")).to.include(0); + expect(index.search("multinational colonization")).to.include(0); + expect(index.search("tional tion")).to.have.length(0); + }); +}); + // ------------------------------------------------------------------------ // Relevance Tests // ------------------------------------------------------------------------ @@ -1031,7 +1117,7 @@ describe("Relevance", function(){ expect(index.search("one two")).to.have.members([1, 2]); expect(index.search("four one")).to.have.members([1, 2]); - var index = new FlexSearch({ + index = new FlexSearch({ encode: "advanced", tokenize: "strict", threshold: 5, @@ -1047,7 +1133,7 @@ describe("Relevance", function(){ expect(index.search("one two")).to.have.members([1, 2]); expect(index.search("four one")).to.have.members([1, 2]); - var index = new FlexSearch({ + index = new FlexSearch({ encode: "extra", tokenize: "ngram", threshold: 5, @@ -1231,8 +1317,8 @@ if(env !== "light") describe("Index Multi-Field Documents", function(){ if(env === ""){ - expect(index.doc.index[0].length).to.equal(3); - expect(index.doc.index[1].length).to.equal(3); + expect(index.doc.index["data:title"].length).to.equal(3); + expect(index.doc.index["data:body"].length).to.equal(3); } expect(index.search({field: "data:body", query: "body"})).to.have.members(data); @@ -1241,11 +1327,17 @@ if(env !== "light") describe("Index Multi-Field Documents", function(){ expect(index.search({field: "data:body", query: "title"})).to.have.lengthOf(0); expect(index.search({field: "data:title", query: "body"})).to.have.lengthOf(0); - expect(index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data); - expect(index.search({field: ["data:body", "data:title"], query: "title"})).to.have.members(data); + //TODO: provide logical operator "OR" + //expect(index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data); + //expect(index.search({field: ["data:body", "data:title"], query: "title"})).to.have.members(data); + expect(index.search({field: "data:body", query: "body"})).to.have.members(data); + expect(index.search({field: ["data:title"], query: "title"})).to.have.members(data); - expect(index.search({query: "body"})).to.have.members(data); - expect(index.search("title")).to.have.members(data); + //TODO: provide logical operator "OR" + //expect(index.search({query: "body"})).to.have.members(data); + //expect(index.search("title")).to.have.members(data); + expect(index.search("body", {field: "data:body"})).to.have.members(data); + expect(index.search("title", {field: ["data:title"]})).to.have.members(data); expect(index.search({ @@ -1255,17 +1347,18 @@ if(env !== "light") describe("Index Multi-Field Documents", function(){ })).to.have.members(data); - expect(index.search([{ - - field: "data:title", - query: "body", - boost: 2 - },{ - field: "data:body", - query: "body", - boost: 2 - - }])).to.have.members(data); + //TODO: provide logical operator "OR" + // expect(index.search([{ + // + // field: "data:title", + // query: "body", + // boost: 2 + // },{ + // field: "data:body", + // query: "body", + // boost: 2 + // + // }])).to.have.members(data); expect(index.search("title", { @@ -1281,29 +1374,35 @@ if(env !== "light") describe("Index Multi-Field Documents", function(){ })).to.have.lengthOf(0); - expect(index.search("body", [{ - - field: "data:title", - boost: 2 - },{ - field: "data:body", - boost: 2 - - }])).to.have.members(data); + //TODO: provide logical operator "OR" + // expect(index.search("body", [{ + // + // field: "data:title", + // boost: 2 + // },{ + // field: "data:body", + // boost: 2 + // + // }])).to.have.members(data); index.update(update); - expect(index.search("foo")).not.to.have.members(data); - expect(index.search("bar")).not.to.have.members(data); - expect(index.search("foo")).to.have.members(update); - expect(index.search("bar")).to.have.members(update); + //TODO: provide logical operator "OR" + // expect(index.search("foo")).not.to.have.members(data); + // expect(index.search("bar")).not.to.have.members(data); + // expect(index.search("foo")).to.have.members(update); + // expect(index.search("bar")).to.have.members(update); + expect(index.search("foo", {field: "data:title"})).not.to.have.members(data); + expect(index.search("bar", {field: "data:body"})).not.to.have.members(data); + expect(index.search("foo", {field: "data:title"})).to.have.members(update); + expect(index.search("bar", {field: "data:body"})).to.have.members(update); index.remove(update); if(env === ""){ - expect(index.doc.index[0].length).to.equal(0); - expect(index.doc.index[1].length).to.equal(0); + expect(index.doc.index["data:title"].length).to.equal(0); + expect(index.doc.index["data:body"].length).to.equal(0); } }); @@ -1331,8 +1430,8 @@ if(env !== "light") describe("Index Multi-Field Documents", function(){ if(env === ""){ - expect(index.doc.index[0].length).to.equal(3); - expect(index.doc.index[1].length).to.equal(3); + expect(index.doc.index["data:title"].length).to.equal(3); + expect(index.doc.index["data:body"].length).to.equal(3); } expect(index.search({field: "data:body", query: "body"})).to.have.members(data); @@ -1341,11 +1440,17 @@ if(env !== "light") describe("Index Multi-Field Documents", function(){ expect(index.search({field: "data:body", query: "title"})).to.have.lengthOf(0); expect(index.search({field: "data:title", query: "body"})).to.have.lengthOf(0); - expect(index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data); - expect(index.search({field: ["data:body", "data:title"], query: "tle"})).to.have.members(data); + //TODO: provide logical operator "OR" + //expect(index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data); + //expect(index.search({field: ["data:body", "data:title"], query: "tle"})).to.have.members(data); + expect(index.search({field: ["data:body"], query: "body"})).to.have.members(data); + expect(index.search({field: "data:title", query: "tle"})).to.have.members(data); - expect(index.search({query: "body"})).to.have.members(data); - expect(index.search("tle")).to.have.members(data); + //TODO: provide logical operator "OR" + //expect(index.search({query: "body"})).to.have.members(data); + //expect(index.search("tle")).to.have.members(data); + expect(index.search({query: "body", field: "data:body"})).to.have.members(data); + expect(index.search("tle", {field: "data:title"})).to.have.members(data); expect(index.search({ @@ -1354,15 +1459,16 @@ if(env !== "light") describe("Index Multi-Field Documents", function(){ })).to.have.members(data); - expect(index.search([{ - - field: "data:title", - query: "body" - },{ - field: "data:body", - query: "body" - - }])).to.have.members(data); + //TODO: provide logical operator "OR" + // expect(index.search([{ + // + // field: "data:title", + // query: "body" + // },{ + // field: "data:body", + // query: "body" + // + // }])).to.have.members(data); expect(index.search("tle", { @@ -1376,30 +1482,57 @@ if(env !== "light") describe("Index Multi-Field Documents", function(){ })).to.have.lengthOf(0); - expect(index.search("body", [{ - - field: "data:title" - },{ - field: "data:body" - - }])).to.have.members(data); + //TODO: provide logical operator "OR" + // expect(index.search("body", [{ + // + // field: "data:title" + // },{ + // field: "data:body" + // + // }])).to.have.members(data); index.update(update); - expect(index.search("foo")).not.to.have.members(data); - expect(index.search("bar")).not.to.have.members(data); - expect(index.search("foo")).to.have.members(update); - expect(index.search("bar")).to.have.members(update); + //TODO: provide logical operator "OR" + // expect(index.search("foo")).not.to.have.members(data); + // expect(index.search("bar")).not.to.have.members(data); + // expect(index.search("foo")).to.have.members(update); + // expect(index.search("bar")).to.have.members(update); + expect(index.search("foo", {field: "data:title"})).not.to.have.members(data); + expect(index.search("bar", {field: "data:body"})).not.to.have.members(data); + expect(index.search("foo", {field: "data:title"})).to.have.members(update); + expect(index.search("bar", {field: "data:body"})).to.have.members(update); index.remove(update); if(env === ""){ - expect(index.doc.index[0].length).to.equal(0); - expect(index.doc.index[1].length).to.equal(0); + expect(index.doc.index["data:title"].length).to.equal(0); + expect(index.doc.index["data:body"].length).to.equal(0); } }); + it("Should have been unique results", function(){ + + var index = new FlexSearch({ + doc: { + id: "id", + field: ["field1", "field2"] + } + }); + + var docs = [{ + id: 1, + field1: "phrase", + field2: "phrase" + }]; + + index.add(docs); + + expect(index.search("phrase")).to.have.lengthOf(1); + expect(index.search("phrase")).to.have.members(docs); + }); + /* it("Should have been indexed properly (tag)", function(){ @@ -1635,12 +1768,12 @@ if(env !== "light") describe("Export / Import", function(){ if(env === ""){ - expect(index.doc.index[0].length).to.equal(3); + expect(index.doc.index["title"].length).to.equal(3); expect(data).to.equal(JSON.stringify([ [ - index.doc.index[0]._map, - index.doc.index[0]._ctx, - index.doc.index[0]._ids + index.doc.index["title"]._map, + index.doc.index["title"]._ctx, + index.doc.index["title"]._ids ], index._doc ])); @@ -1660,7 +1793,7 @@ if(env !== "light") describe("Export / Import", function(){ if(env === ""){ - expect(index.doc.index[0].length).to.equal(3); + expect(index.doc.index["title"].length).to.equal(3); } expect(index.search("foo")).to.have.lengthOf(2);