mirror of
https://github.com/nextapps-de/flexsearch.git
synced 2025-08-19 12:21:57 +02:00
support for inline worker
This commit is contained in:
49
dist/flexsearch.min.js
vendored
49
dist/flexsearch.min.js
vendored
@@ -5,26 +5,29 @@
|
|||||||
* Licence: Apache-2.0
|
* Licence: Apache-2.0
|
||||||
* https://github.com/nextapps-de/flexsearch
|
* https://github.com/nextapps-de/flexsearch
|
||||||
*/
|
*/
|
||||||
(function(self){'use strict';var u;const v=/[\W_]+/;function aa(a){if(a=a.toLowerCase())if(a&&this.B&&(a=y(a,this.B)),this.F&&1<a.length&&(a=y(a,this.F)),a&&(v||""===v)&&(a=a.split(v),this.filter)){var b=this.filter;const c=a.length,d=[];for(let e=0,f=0;e<c;e++){const g=a[e];g&&!b[g]&&(d[f++]=g)}a=d}return a};function A(a,b){return"undefined"!==typeof a?a:b}function B(a){const b=Array(a);for(let c=0;c<a;c++)b[c]=C();return b}function C(){return Object.create(null)}function ba(a,b){return b.length-a.length}function D(a){return"string"===typeof a}function E(a){return"object"===typeof a}function F(a){return"function"===typeof a};function G(a,b){const c=Object.keys(a),d=c.length,e=[];let f="",g=0;for(let h=0,k,l;h<d;h++)k=c[h],(l=a[k])?(e[g++]=new RegExp(b?"(?!\\b)"+k+"(\\b|_)":k,"g"),e[g++]=l):f+=(f?"|":"")+k;f&&(e[g++]=new RegExp(b?"(?!\\b)("+f+")(\\b|_)":"("+f+")","g"),e[g]="");return e}function y(a,b){for(let c=0,d=b.length;c<d&&(a=a.replace(b[c],b[c+1]),a);c+=2);return a};const H={},ca={};let I=Promise;Object.assign||(Object.assign=function(){const a=arguments,b=a.length,c=a[0];for(let d=1,e,f,g;d<b;d++){e=a[d];f=Object.keys(e);g=f.length;for(let h=0,k;h<g;h++)k=f[h],c[k]=e[k]}return c});if(!I){function a(b){this.g=null;const c=this;b(function(d){c.g&&c.g(d)})}a.prototype.then=function(b){this.g=b};I=a};function da(a){J(a,"add");J(a,"append");J(a,"search");J(a,"update");J(a,"remove")}function J(a,b){a[b+"Async"]=function(){const c=this,d=arguments;var e=d[d.length-1];let f;F(e)&&(f=e,delete d[d.length-1]);e=new I(function(g){setTimeout(function(){const h=c[b];h.async=!0;g(h.apply(c,d));h.async=!1})});return f?(e.then(f),this):e}};function ea(a,b,c,d){const e=a.length;let f=[],g=C(),h=0;d&&(d=[]);for(let k=0;k<e;k++){const l=a[k],p=l.length,r=C();let w=!k;for(let q=0;q<p;q++){const t=l[q],m=t.length;if(m){d&&(d[q]=[]);for(let n=0,x=0,z;n<m;n++)if(z=t[n],!k)r[z]=1;else if(g[z]){if(k===e-1)if(c)c--;else{if(f[h++]=z,h===b)return f}else d&&x<b&&(d[q][x++]=z),r[z]=1;w=!0}}}if(!w&&!d)return[];g=r}if(d)for(let k=d.length-1,l,p;0<=k;k--)if(p=(l=d[k])&&l.length){if(h+p>=b)return f.concat(l.slice(0,b-h));f=f.concat(l);h+=p}return f}
|
(function _f(self){'use strict';try{if(module)self=module}catch(e){}self._factory=_f;var u;const w=/[\W_]+/;function aa(a){if(a=a.toLowerCase())if(a&&this.C&&(a=y(a,this.C)),this.G&&1<a.length&&(a=y(a,this.G)),a&&(w||""===w)&&(a=a.split(w),this.filter)){var b=this.filter;const c=a.length,d=[];for(let e=0,f=0;e<c;e++){const g=a[e];g&&!b[g]&&(d[f++]=g)}a=d}return a};function z(a,b){return"undefined"!==typeof a?a:b}function A(a){const b=Array(a);for(let c=0;c<a;c++)b[c]=B();return b}function B(){return Object.create(null)}function ba(a,b){return b.length-a.length}function C(a){return"string"===typeof a}function D(a){return"object"===typeof a}function E(a){return"function"===typeof a};function H(a,b){const c=Object.keys(a),d=c.length,e=[];let f="",g=0;for(let h=0,k,l;h<d;h++)k=c[h],(l=a[k])?(e[g++]=new RegExp(b?"(?!\\b)"+k+"(\\b|_)":k,"g"),e[g++]=l):f+=(f?"|":"")+k;f&&(e[g++]=new RegExp(b?"(?!\\b)("+f+")(\\b|_)":"("+f+")","g"),e[g]="");return e}function y(a,b){for(let c=0,d=b.length;c<d&&(a=a.replace(b[c],b[c+1]),a);c+=2);return a};const ca={},da={};let I=Promise;Object.assign||(Object.assign=function(){const a=arguments,b=a.length,c=a[0];for(let d=1,e,f,g;d<b;d++){e=a[d];f=Object.keys(e);g=f.length;for(let h=0,k;h<g;h++)k=f[h],c[k]=e[k]}return c});if(!I){function a(b){this.g=null;const c=this;b(function(d){c.g&&c.g(d)})}a.prototype.then=function(b){this.g=b};I=a};function ea(a){J(a,"add");J(a,"append");J(a,"search");J(a,"update");J(a,"remove")}function J(a,b){a[b+"Async"]=function(){const c=this,d=arguments;var e=d[d.length-1];let f;E(e)&&(f=e,delete d[d.length-1]);e=new I(function(g){setTimeout(function(){const h=c[b];h.async=!0;g(h.apply(c,d));h.async=!1})});return f?(e.then(f),this):e}};function fa(a,b,c,d){var e=a.length;let f=[],g,h=0;d&&(d=[]);for(--e;0<=e;e--){const k=a[e],l=k.length,n=B();let q=!g;for(let r=0;r<l;r++){const v=k[r],p=v.length;if(p)for(let m=0,t=0,x;m<p;m++)if(x=v[m],!g)n[x]=1;else if(g[x]){if(e)d&&t<b&&((d[r]||(d[r]=[]))[t++]=x),n[x]=1;else if(c)c--;else if(f[h++]=x,h===b)return f;q=!0}}if(!q&&!d)return[];g=n}if(d)for(let k=d.length-1,l,n;0<=k;k--)if((n=(l=d[k])&&l.length)&&c&&(n<=c?(c-=n,n=0):n-=c),n){if(h+n>=b)return f.concat(l.slice(c,b-h+c));f=f.concat(c?
|
||||||
function fa(a,b){const c=C(),d=C(),e=[];for(let f=0;f<a.length;f++)c[a[f]]=1;for(let f=0,g;f<b.length;f++){g=b[f];for(let h=0,k;h<g.length;h++)k=g[h],c[k]&&!d[k]&&(d[k]=1,e[e.length]=k)}return e};function K(a){this.h=!0!==a&&a;this.cache=C();this.g=[]}function ha(a,b,c){E(a)&&(a=a.query);let d=this.cache.get(a);d||(d=this.search(a,b,c),this.cache.set(a,d));return d}K.prototype.set=function(a,b){if(!this.cache[a]){var c=this.g.length;c===this.h?delete this.cache[this.g[c-1]]:c++;for(--c;0<c;c--)this.g[c]=this.g[c-1];this.g[0]=a}this.cache[a]=b};K.prototype.get=function(a){const b=this.cache[a];if(this.h&&b&&(a=this.g.indexOf(a))){const c=this.g[a-1];this.g[a-1]=this.g[a];this.g[a]=c}return b};const ia={memory:{charset:"latin:extra",o:3,m:3,i:!1,l:"memory"},performance:{threshold:8,m:3,context:{depth:1,u:!0}},match:{charset:"latin:extra",I:"full",o:3},score:{charset:"latin:advanced",threshold:1,context:{depth:3,u:!0}},"default":{o:3,threshold:0,depth:3}};function la(a,b,c,d,e,f){setTimeout(function(){const g=a(c,JSON.stringify(f));g&&g.then?g.then(function(){b.export(a,b,c,d,e+1)}):b.export(a,b,c,d,e+1)})};function L(a,b){if(!(this instanceof L))return new L(a);var c;if(a){D(a)?a=ia[a]:(c=a.preset)&&(a=Object.assign({},c[c],a));c=a.charset;var d=a.lang;D(c)&&(-1===c.indexOf(":")&&(c+=":default"),c=ca[c]);D(d)&&(d=H[d])}else a={};let e,f,g,h=a.context||{};this.encode=a.encode||c&&c.encode||aa;this.register=b||C();e=a.resolution||9;f=a.threshold||0;f>=e&&(f=e-1);this.o=e;this.threshold=f;this.s=b=c&&c.I||a.tokenize||"strict";this.depth="strict"===b&&h.depth;this.u=A(h.bidirectional,!0);this.l=g="memory"===
|
l.slice(c):l);h+=n;c=0}return f}function ha(a,b){const c=B(),d=B(),e=[];for(let f=0;f<a.length;f++)c[a[f]]=1;for(let f=0,g;f<b.length;f++){g=b[f];for(let h=0,k;h<g.length;h++)k=g[h],c[k]&&!d[k]&&(d[k]=1,e[e.length]=k)}return e};function K(a){this.h=!0!==a&&a;this.cache=B();this.g=[]}function ia(a,b,c){D(a)&&(a=a.query);let d=this.cache.get(a);d||(d=this.search(a,b,c),this.cache.set(a,d));return d}K.prototype.set=function(a,b){if(!this.cache[a]){var c=this.g.length;c===this.h?delete this.cache[this.g[c-1]]:c++;for(--c;0<c;c--)this.g[c]=this.g[c-1];this.g[0]=a}this.cache[a]=b};K.prototype.get=function(a){const b=this.cache[a];if(this.h&&b&&(a=this.g.indexOf(a))){const c=this.g[a-1];this.g[a-1]=this.g[a];this.g[a]=c}return b};const ja={memory:{charset:"latin:extra",s:3,o:3,i:!1,m:"memory"},performance:{threshold:8,o:3,context:{depth:1,v:!0}},match:{charset:"latin:extra",I:"full",s:3},score:{charset:"latin:advanced",threshold:1,context:{depth:3,v:!0}},"default":{s:3,threshold:0,depth:3}};function ka(a,b,c,d,e,f){setTimeout(function(){const g=a(c,JSON.stringify(f));g&&g.then?g.then(function(){b.export(a,b,c,d,e+1)}):b.export(a,b,c,d,e+1)})};function L(a,b){if(!(this instanceof L))return new L(a);var c;if(a){C(a)?a=ja[a]:(c=a.preset)&&(a=Object.assign({},c[c],a));c=a.charset;var d=a.lang;C(c)&&(-1===c.indexOf(":")&&(c+=":default"),c=da[c]);C(d)&&(d=ca[d])}else a={};let e,f,g,h=a.context||{};this.encode=a.encode||c&&c.encode||aa;this.register=b||B();e=a.resolution||9;f=a.threshold||0;f>=e&&(f=e-1);this.s=e;this.threshold=f;this.u=b=c&&c.I||a.tokenize||"strict";this.depth="strict"===b&&h.depth;this.v=z(h.bidirectional,!0);this.m=g="memory"===
|
||||||
a.optimize;this.i=A(a.fastupdate,!0);this.m=a.minlength||1;this.map=g?B(e-f):C();e=h.resolution||e;f=h.threshold||f;f>=e&&(f=e-1);this.h=e;this.j=f;this.g=g?B(e-f):C();this.D=c&&c.D||a.rtl;this.B=(b=a.matcher||d&&d.B)&&G(b,!1);this.F=(b=a.stemmer||d&&d.F)&&G(b,!0);if(c=b=a.filter||d&&d.filter){c=b;d=C();for(let k=0,l=c.length;k<l;k++)d[c[k]]=1;c=d}this.filter=c;this.cache=(b=a.cache)&&new K(b)}u=L.prototype;u.append=function(a,b){return this.add(a,b,!0)};
|
a.optimize;this.i=z(a.fastupdate,!0);this.o=a.minlength||1;this.map=g?A(e-f):B();e=h.resolution||e;f=h.threshold||f;f>=e&&(f=e-1);this.h=e;this.l=f;this.g=g?A(e-f):B();this.F=c&&c.F||a.rtl;this.C=(b=a.matcher||d&&d.C)&&H(b,!1);this.G=(b=a.stemmer||d&&d.G)&&H(b,!0);if(c=b=a.filter||d&&d.filter){c=b;d=B();for(let k=0,l=c.length;k<l;k++)d[c[k]]=1;c=d}this.filter=c;this.cache=(b=a.cache)&&new K(b)}u=L.prototype;u.append=function(a,b){return this.add(a,b,!0)};
|
||||||
u.add=function(a,b,c){if(this.register[a]&&!c)return this.update(a,b);if(b&&(a||0===a)){b=this.encode(b);const l=b.length;if(l){const p=this.depth,r=this.o-this.threshold,w=C(),q=C();for(let t=0;t<l;t++){let m=b[this.D?l-1-t:t];var d=m.length;if(m&&d>=this.m&&(p||!w[m])){var e=Math.min(this.o/l*t|0,t);if(e<r){var f="";switch(this.s){case "full":if(3<d){for(var g=0;g<d;g++){var h=g?Math.min(e/2+this.o/d*g/2|0,e+g):e;if(h<r)for(var k=d;k>g;k--)f=m.substring(g,k),f.length>=this.m&&N(this,w,f,h,a,c)}break}case "reverse":if(2<
|
u.add=function(a,b,c){if(this.register[a]&&!c)return this.update(a,b);if(b&&(a||0===a)){b=this.encode(b);const l=b.length;if(l){const n=this.depth,q=this.s-this.threshold,r=B(),v=B();for(let p=0;p<l;p++){let m=b[this.F?l-1-p:p];var d=m.length;if(m&&d>=this.o&&(n||!r[m])){var e=Math.min(this.s/l*p|0,p);if(e<q){var f="";switch(this.u){case "full":if(3<d){for(var g=0;g<d;g++){var h=g?Math.min(e/2+this.s/d*g/2|0,e+g):e;if(h<q)for(var k=d;k>g;k--)f=m.substring(g,k),f.length>=this.o&&M(this,r,f,h,a,c)}break}case "reverse":if(2<
|
||||||
d){for(g=d-1;0<g;g--)f=m[g]+f,f.length>=this.m&&N(this,w,f,e,a,c);f=""}case "forward":if(1<d)for(g=0;g<d;g++)f+=m[g],f.length>=this.m&&N(this,w,f,e,a,c);break;default:if(N(this,w,m,e,a,c),p&&1<l&&t<l-1)for(d=this.h-this.j,e=C(),f=m,g=Math.min(p+1,l-t),e[f]=1,h=1;h<g;h++)if((m=b[this.D?l-1-t-h:t+h])&&m.length>=this.m&&!e[m]){if(e[m]=1,k=Math.min((this.h-g)/l*t+h|0,t+(h-1)),k<d){const n=this.u&&m>f;N(this,q,n?f:m,k,a,c,n?m:f)}}else g=Math.min(g+1,l-t)}}}}this.i||(this.register[a]=1)}}return this};
|
d){for(g=d-1;0<g;g--)f=m[g]+f,f.length>=this.o&&M(this,r,f,e,a,c);f=""}case "forward":if(1<d)for(g=0;g<d;g++)f+=m[g],f.length>=this.o&&M(this,r,f,e,a,c);break;default:if(M(this,r,m,e,a,c),n&&1<l&&p<l-1)for(d=this.h-this.l,e=B(),f=m,g=Math.min(n+1,l-p),e[f]=1,h=1;h<g;h++)if((m=b[this.F?l-1-p-h:p+h])&&m.length>=this.o&&!e[m]){if(e[m]=1,k=Math.min((this.h-g)/l*p+h|0,p+(h-1)),k<d){const t=this.v&&m>f;M(this,v,t?f:m,k,a,c,t?m:f)}}else g=Math.min(g+1,l-p)}}}}this.i||(this.register[a]=1)}}return this};
|
||||||
function N(a,b,c,d,e,f,g){let h=g?a.g:a.map;if(!b[c]||g&&!b[c][g])a.l&&(h=h[d]),g?(b[c]||(b[c]=C()),b[c][g]=1,h=h[g]||(h[g]=C())):b[c]=1,h=h[c]||(h[c]=[]),a.l||(h=h[d]||(h[d]=[])),f&&-1!==h.indexOf(e)||(h[h.length]=e,a.i&&(a=a.register[e]||(a.register[e]=[]),a[a.length]=h))}
|
function M(a,b,c,d,e,f,g){let h=g?a.g:a.map;if(!b[c]||g&&!b[c][g])a.m&&(h=h[d]),g?(b=b[c]||(b[c]=B()),b[g]=1,h=h[g]||(h[g]=B())):b[c]=1,h=h[c]||(h[c]=[]),a.m||(h=h[d]||(h[d]=[])),f&&-1!==h.indexOf(e)||(h[h.length]=e,a.i&&(a=a.register[e]||(a.register[e]=[]),a[a.length]=h))}
|
||||||
u.search=function(a,b,c){E(a)?(c=a,a=c.query):E(b)&&(c=b);let d=[],e;var f=this.threshold;let g,h=0;if(c){b=c.limit;h=c.offset||0;f=A(c.threshold,f);var k=c.context;g=c.suggest}if(a&&(a=this.encode(a),e=a.length,1<e)){c=C();var l=[];for(let r=0,w=0,q;r<e;r++)if((q=a[r])&&q.length>=this.m&&!c[q])if(this.l||g||this.map[q])l[w++]=q,c[q]=1;else return d;a=l;e=a.length}if(!e)return d;b||(b=100);c=this.o-f;f=this.h-f;k=this.depth&&1<e&&!1!==k;l=0;let p;k?(p=a[0],l=1):1<e&&a.sort(ba);for(let r,w;l<e;l++){w=
|
u.search=function(a,b,c){D(a)?(c=a,a=c.query):D(b)&&(c=b);let d=[],e;var f=this.threshold;let g,h=0;if(c){b=c.limit;h=c.offset||0;f=z(c.threshold,f);var k=c.context;g=c.suggest}if(a&&(a=this.encode(a),e=a.length,1<e)){c=B();var l=[];for(let q=0,r=0,v;q<e;q++)if((v=a[q])&&v.length>=this.o&&!c[v])if(this.m||g||this.map[v])l[r++]=v,c[v]=1;else return d;a=l;e=a.length}if(!e)return d;b||(b=100);c=this.s-f;f=this.h-f;k=this.depth&&1<e&&!1!==k;l=0;let n;k?(n=a[0],l=1):1<e&&a.sort(ba);for(let q,r;l<e;l++){r=
|
||||||
a[l];k?(r=ma(this,d,g,f,b,2===e,w,p),g&&!1===r&&d.length||(p=w)):r=ma(this,d,g,c,b,1===e,w);if(r)return r;if(g&&l===e-1){let q=d.length;if(!q){if(k){k=0;l=-1;continue}return d}if(1===q)return d=d[0],d=1===d.length?d[0]:[].concat.apply([],d),d.length>b?d.slice(0,b):d}}return ea(d,b,h,g)};function na(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}
|
a[l];k?(q=na(this,d,g,f,b,h,2===e,r,n),g&&!1===q&&d.length||(n=r)):q=na(this,d,g,c,b,h,1===e,r);if(q)return q;if(g&&l===e-1){let v=d.length;if(!v){if(k){k=0;l=-1;continue}return d}if(1===v)return oa(d[0],b,h)}}return fa(d,b,h,g)};
|
||||||
function ma(a,b,c,d,e,f,g,h){let k=[],l=h?a.g:a.map;a.l||(l=na(l,g,h,a.u));if(l){let p=0;d=Math.min(l.length,d);for(let r=0,w=0,q;r<d&&!(q=l[r],a.l&&(q=na(q,g,h,a.u)),q&&(k[p++]=q,f&&(w+=q.length,w>=e)));r++);if(p){if(f)return k=1===p?k[0]:[].concat.apply([],k),k.length>e?k.slice(0,e):k;b[b.length]=k;return}}return!c&&k}u.contain=function(a){return!!this.register[a]};u.update=function(a,b){return this.remove(a).add(a,b)};
|
function na(a,b,c,d,e,f,g,h,k){let l=[],n=k?a.g:a.map;a.m||(n=pa(n,h,k,a.v));if(n){let q=0;d=Math.min(n.length,d);for(let r=0,v=0,p,m;r<d&&!(p=n[r],a.m&&(p=pa(p,h,k,a.v)),p&&g&&(m=p.length,m<=f?(f-=m,p=null):f&&(p=p.slice(f),f=0)),p&&(l[q++]=p,g&&(v+=p.length,v>=e)));r++);if(q){if(g)return oa(l,e,0);b[b.length]=l;return}}return!c&&l}function oa(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a}
|
||||||
u.remove=function(a,b){const c=this.register[a];if(c){if(this.i)for(let d=0,e;d<c.length;d++)e=c[d],e.splice(e.indexOf(a),1);else O(this.map,a,this.o-this.threshold,this.l),this.depth&&O(this.g,a,this.h-this.j,this.l);b||delete this.register[a];if(this.cache){b=this.cache;for(let d=0,e,f;d<b.g.length;d++)f=b.g[d],e=b.cache[f],-1!==e.indexOf(a)&&(b.g.splice(d--,1),delete b.cache[f])}}return this};
|
function pa(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}u.contain=function(a){return!!this.register[a]};u.update=function(a,b){return this.remove(a).add(a,b)};
|
||||||
function O(a,b,c,d,e){let f=0;if(a.constructor===Array)if(e)b=a.indexOf(b),-1!==b?1<a.length&&(a.splice(b,1),f++):f++;else{e=Math.min(a.length,c);for(let g=0,h;g<e;g++)if(h=a[g])f=O(h,b,c,d,e),d||f||delete a[g]}else for(let g in a)(f=O(a[g],b,c,d,e))||delete a[g];return f}u.searchCache=ha;
|
u.remove=function(a,b){const c=this.register[a];if(c){if(this.i)for(let d=0,e;d<c.length;d++)e=c[d],e.splice(e.indexOf(a),1);else P(this.map,a,this.s-this.threshold,this.m),this.depth&&P(this.g,a,this.h-this.l,this.m);b||delete this.register[a];if(this.cache){b=this.cache;for(let d=0,e,f;d<b.g.length;d++)f=b.g[d],e=b.cache[f],-1!==e.indexOf(a)&&(b.g.splice(d--,1),delete b.cache[f])}}return this};
|
||||||
u.export=function(a,b,c,d,e){let f,g;switch(e||(e=0)){case 0:f="reg";if(this.i){g=C();for(let h in this.register)g[h]=1}else g=this.register;break;case 1:f="cfg";g={doc:0,opt:this.l?1:0};break;case 2:f="map";g=this.map;break;case 3:f="ctx";g=this.g;break;default:return}la(a,b||this,c?c+"."+f:f,d,e,g);return!0};u.import=function(a,b){if(b)switch(D(b)&&(b=JSON.parse(b)),a){case "cfg":this.l=!!b.opt;break;case "reg":this.i=!1;this.register=b;break;case "map":this.map=b;break;case "ctx":this.g=b}};da(L.prototype);let oa=0;function P(a,b){E(a)&&(b=a,a=0);b&&F(b.encode)&&(b.encode=b.encode.toString());const c=this;this.id=a||oa++;this.h=null;this.g=new Worker("worker.js",{type:"module"});this.g.onmessage=function(d){c.h(d.data)};this.g.postMessage({H:"create",options:b})}Q("add");Q("append");Q("search");Q("update");Q("remove");
|
function P(a,b,c,d,e){let f=0;if(a.constructor===Array)if(e)b=a.indexOf(b),-1!==b?1<a.length&&(a.splice(b,1),f++):f++;else{e=Math.min(a.length,c);for(let g=0,h;g<e;g++)if(h=a[g])f=P(h,b,c,d,e),d||f||delete a[g]}else for(let g in a)(f=P(a[g],b,c,d,e))||delete a[g];return f}u.searchCache=ia;
|
||||||
function Q(a){P.prototype[a]=P.prototype[a+"Async"]=function(){const b=this,c=[].slice.call(arguments);var d=c[c.length-1];let e;F(d)&&(e=d,c.splice(c.length-1,1));d=new I(function(f){b.g.postMessage({H:a,J:c});"search"===a?b.h=f:f()});return e?(d.then(e),this):d}};function R(a){if(!(this instanceof R))return new R(a);var b;a||(a={});this.G=[];this.g=[];this.s=[];this.register=C();this.key=(b=a.key)&&U(b,this.s)||"id";this.i=A(a.fastupdate,!0);this.store=(b=a.store)&&C();this.v=b&&!0!==b&&[];this.C=(b=a.tag)&&U(b,this.s);this.h=b&&C();this.cache=(b=a.cache)&&new K(b);a.cache=!1;this.A=a.worker;this.async=!1;b=a;a=C();let c=b.doc;if(D(c))c=[c];else if(c.constructor!==Array){var d=c;c=Object.keys(c)}for(let e=0,f,g;e<c.length;e++)f=c[e],D(f)?d&&(g=d[f]):(g=f,
|
u.export=function(a,b,c,d,e){let f,g;switch(e||(e=0)){case 0:f="reg";if(this.i){g=B();for(let h in this.register)g[h]=1}else g=this.register;break;case 1:f="cfg";g={doc:0,opt:this.m?1:0};break;case 2:f="map";g=this.map;break;case 3:f="ctx";g=this.g;break;default:return}ka(a,b||this,c?c+"."+f:f,d,e,g);return!0};u.import=function(a,b){if(b)switch(C(b)&&(b=JSON.parse(b)),a){case "cfg":this.m=!!b.opt;break;case "reg":this.i=!1;this.register=b;break;case "map":this.map=b;break;case "ctx":this.g=b}};ea(L.prototype);function qa(a){var b=self._index;a=a.data;var c=a.args;switch(a.task){case "init":b=a.options||{};a=a.factory;c=b.encode;b.cache=!1;"string"===typeof c&&(b.encode=(new Function("return "+c))());a?((new Function("return "+a))()(self),self._index=self.FlexSearch.Index(b),delete self.FlexSearch):self._index=new L(b);break;case "add":b.add.apply(b,c);break;case "append":b.append.apply(b,c);break;case "search":b=b.search.apply(b,c);postMessage(b);break;case "update":b.update.apply(b,c);break;case "remove":b.remove.apply(b,
|
||||||
f=f.field),g=E(g)?Object.assign({},b,g):b,a[f]=this.A?new P(g):new L(g,this.register),this.G[e]=U(f,this.s),this.g[e]=f;if(this.v)for(d=b.store,D(d)&&(d=[d]),b=0;b<d.length;b++)this.v[b]=U(d[b],this.s);this.j=a}function U(a,b){const c=a.split(":");let d=0;for(let e=0;e<c.length;e++)a=c[e],0<=a.indexOf("[]")&&(a=a.substring(0,a.length-2))&&(b[d]=!0),a&&(c[d++]=a);d<c.length&&(c.length=d);return 1<d?c:c[0]}function pa(a,b){if(D(b))a=a[b];else for(let c=0;a&&c<b.length;c++)a=a[b[c]];return a}
|
c)}};let ra=0;function Q(a,b){var c;D(a)?(b=a,a=0):b?E(c=b.encode)&&(b.encode=c.toString()):b={};(c=(self||window)._factory)&&(c=c.toString());const d=this;this.id=a||ra++;this.g=null;if(this.j=sa(c))this.j.onmessage=function(e){d.g(e.data)},this.j.postMessage({task:"init",factory:c,options:b})}R("add");R("append");R("search");R("update");R("remove");
|
||||||
function V(a,b,c,d,e){a=a[e];if(d===c.length-1)b[e]=a;else if(a)if(a.constructor===Array)for(b=b[e]=Array(a.length),e=0;e<a.length;e++)V(a,b,c,d,e);else b=b[e]||(b[e]=C()),e=c[++d],V(a,b,c,d,e)}function W(a,b,c,d,e,f,g,h){a=a[g];if(d===b.length-1){if(a.constructor===Array){if(c[d]){for(b=0;b<a.length;b++)e.add(f,a[b],!0);return}a=a.join(" ")}e.add(f,a,h)}else if(a)if(a.constructor===Array)for(g=0;g<a.length;g++)W(a,b,c,d,e,f,g,h);else g=b[++d],W(a,b,c,d,e,f,g,h)}u=R.prototype;
|
function R(a){Q.prototype[a]=Q.prototype[a+"Async"]=function(){const b=this,c=[].slice.call(arguments);var d=c[c.length-1];let e;E(d)&&(e=d,c.splice(c.length-1,1));d=new I(function(f){b.j.postMessage({task:a,args:c});"search"===a?b.g=f:f()});return e?(d.then(e),this):d}}function sa(a){let b;try{b=a?new Worker(URL.createObjectURL(new Blob(["onmessage="+qa.toString()],{type:"text/javascript"}))):new Worker("worker.js",{type:"module"})}catch(c){}return b};function S(a){if(!(this instanceof S))return new S(a);var b;a||(a={});this.H=[];this.g=[];this.u=[];this.register=B();this.key=(b=a.key)&&T(b,this.u)||"id";this.i=z(a.fastupdate,!0);this.B=!!(b=a.extern);this.A=!this.B&&(b=a.store)&&!0!==b&&[];this.store=b&&(this.B?b:B());this.D=(b=a.tag)&&T(b,this.u);this.h=b&&B();this.cache=(b=a.cache)&&new K(b);a.cache=!1;this.j=a.worker;this.async=!1;b=a;a=B();let c=b.doc;if(C(c))c=[c];else if(c.constructor!==Array){var d=c;c=Object.keys(c)}for(let e=0,f,g;e<
|
||||||
u.add=function(a,b,c){E(a)&&(b=a,a=pa(b,this.key));if(b&&(a||0===a)){if(this.register[a])return this.update(a,b);for(let d=0,e,f;d<this.g.length;d++)f=this.g[d],e=this.G[d],D(e)&&(e=[e]),W(b,e,this.s,0,this.j[f],a,e[0],c);if(this.C){let d=pa(b,this.C),e=C();D(d)&&(d=[d]);for(let f=0,g,h;f<d.length;f++)if(g=d[f],!e[g]&&(e[g]=1,h=this.h[g]||(this.h[g]=[]),!c||-1===h.indexOf(a)))if(h[h.length]=a,this.i){const k=this.register[a]||(this.register[a]=[]);k[k.length]=h}}if(this.store){let d;if(this.v){d=
|
c.length;e++)f=c[e],C(f)?d&&(g=d[f]):(g=f,f=f.field),g=D(g)?Object.assign({},b,g):b,this.j&&(a[f]=new Q(g),a[f].j||(this.j=!1)),this.j||(a[f]=new L(g,this.register)),this.H[e]=T(f,this.u),this.g[e]=f;if(this.A)for(d=b.store,C(d)&&(d=[d]),b=0;b<d.length;b++)this.A[b]=T(d[b],this.u);this.l=a}function T(a,b){const c=a.split(":");let d=0;for(let e=0;e<c.length;e++)a=c[e],0<=a.indexOf("[]")&&(a=a.substring(0,a.length-2))&&(b[d]=!0),a&&(c[d++]=a);d<c.length&&(c.length=d);return 1<d?c:c[0]}
|
||||||
C();for(let e=0,f;e<this.v.length;e++)f=this.v[e],D(f)?d[f]=b[f]:V(b,d,f,0,f[0])}this.store[a]=d||b}}return this};u.append=function(a,b){return this.add(a,b,!0)};u.update=function(a,b){return this.remove(a).add(a,b)};
|
function ta(a,b){if(C(b))a=a[b];else for(let c=0;a&&c<b.length;c++)a=a[b[c]];return a}function V(a,b,c,d,e){a=a[e];if(d===c.length-1)b[e]=a;else if(a)if(a.constructor===Array)for(b=b[e]=Array(a.length),e=0;e<a.length;e++)V(a,b,c,d,e);else b=b[e]||(b[e]=B()),e=c[++d],V(a,b,c,d,e)}
|
||||||
u.remove=function(a){E(a)&&(a=a[this.key]);if(this.register[a]){for(var b=0;b<this.g.length&&(this.j[this.g[b]].remove(a,!0),!this.i||this.A);b++);if(this.C&&(!this.i||this.A))for(let c in this.h){b=this.h[c];const d=b.indexOf(a);-1!==d&&(1<b.length?b.splice(d,1):delete this.h[c])}this.store&&delete this.store[a];delete this.register[a]}return this};
|
function W(a,b,c,d,e,f,g,h){a=a[g];if(d===b.length-1){if(a.constructor===Array){if(c[d]){for(b=0;b<a.length;b++)e.add(f,a[b],!0);return}a=a.join(" ")}e.add(f,a,h)}else if(a)if(a.constructor===Array)for(g=0;g<a.length;g++)W(a,b,c,d,e,f,g,h);else g=b[++d],W(a,b,c,d,e,f,g,h)}u=S.prototype;
|
||||||
u.search=function(a,b,c,d){E(a)?(c=a,a=c.query):E(b)&&(c=b,b=0);let e=[],f=[],g,h,k,l,p,r,w,q=0;if(c)if(c.constructor===Array)k=c,c=null;else if(k=(g=c.pluck)||c.field||c.doc,p=c.tag,h=this.store&&c.enrich,r="and"===c.bool,b=c.limit||100,w=c.offset||0,k&&(D(k)?k=[k]:k.constructor!==Array&&(l=k,k=Object.keys(k))),p&&(D(p)&&(p=[p]),!a)){for(let m=0,n;m<p.length;m++)if(n=qa.call(this,p[m],b,w,h))e[e.length]=n,q++;return q?e:[]}k||(k=this.g);r=r&&(1<k.length||p&&1<p.length);if(!d&&(this.A||this.async)){d=
|
u.add=function(a,b,c){D(a)&&(b=a,a=ta(b,this.key));if(b&&(a||0===a)){if(this.register[a])return this.update(a,b);for(let d=0,e,f;d<this.g.length;d++)f=this.g[d],e=this.H[d],C(e)&&(e=[e]),W(b,e,this.u,0,this.l[f],a,e[0],c);if(this.D){let d=ta(b,this.D),e=B();C(d)&&(d=[d]);for(let f=0,g,h;f<d.length;f++)if(g=d[f],!e[g]&&(e[g]=1,h=this.h[g]||(this.h[g]=[]),!c||-1===h.indexOf(a)))if(h[h.length]=a,this.i){const k=this.register[a]||(this.register[a]=[]);k[k.length]=h}}if(this.store&&!this.B){let d;if(this.A){d=
|
||||||
[];for(let n=0,x;n<k.length;n++){var t=void 0;x=k[n];D(x)?l&&(t=l[x]):(t=x,x=x.field);d[n]=this.j[x].searchAsync(a,b,t||c)}const m=this;return Promise.all(d).then(function(n){m.search(a,b,c,n)})}for(let m=0,n,x,z;m<k.length;m++){let S;x=k[m];D(x)?l&&(S=l[x]):(S=x,x=x.field);n=d?d[m]:this.j[x].search(a,b,S||c);z=n.length;if(p&&z){t=[];let ja=0;r&&(t[0]=[n]);for(let T=0,ka,M;T<p.length;T++)if(ka=p[T],z=(M=this.h[ka])&&M.length)ja++,t[t.length]=r?[M]:M;ja&&(n=r?ea(t,b||100,w||0):fa(n,t),z=n.length)}if(z)f[q]=
|
B();for(let e=0,f;e<this.A.length;e++)f=this.A[e],C(f)?d[f]=b[f]:V(b,d,f,0,f[0])}this.store[a]=d||b}}return this};u.append=function(a,b){return this.add(a,b,!0)};u.update=function(a,b){return this.remove(a).add(a,b)};
|
||||||
x,e[q++]=n;else if(r)return[]}if(!q)return[];if(g&&(!h||!this.store))return e[0];for(let m=0,n;m<f.length;m++){n=e[m];n.length&&h&&(n=ra.call(this,n));if(g)return n;e[m]={field:f[m],result:n}}return e};function qa(a,b,c,d){let e=this.h[a],f=e&&e.length-c;if(f&&0<f){if(f>b||c)e=e.slice(c,c+b);d&&(e=ra.call(this,e));return{tag:a,result:e}}}function ra(a){const b=Array(a.length);for(let c=0,d;c<a.length;c++)d=a[c],b[c]={key:d,doc:this.store[d]};return b}u.contain=function(a){return!!this.register[a]};
|
u.remove=function(a){D(a)&&(a=a[this.key]);if(this.register[a]){for(var b=0;b<this.g.length&&(this.l[this.g[b]].remove(a,!0),!this.i||this.j);b++);if(this.D&&(!this.i||this.j))for(let c in this.h){b=this.h[c];const d=b.indexOf(a);-1!==d&&(1<b.length?b.splice(d,1):delete this.h[c])}this.store&&!this.B&&delete this.store[a];delete this.register[a]}return this};
|
||||||
u.get=function(a){return this.store[a]};u.set=function(a,b){this.store[a]=b;return this};u.searchCache=ha;u.export=function(a,b,c,d,e){e||(e=0);d||(d=0);if(d<this.g.length){const f=this.g[d],g=this.j[f];b=this;setTimeout(function(){g.export(a,b,e?f.replace(":","-"):"",d,e++)||(d++,e=1,b.export(a,b,f,d,e))})}else{let f;switch(e){case 1:c="tag";f=this.h;break;case 2:c="store";f=this.store;break;default:return}la(a,this,c,d,e,f)}};
|
u.search=function(a,b,c,d){D(a)?(c=a,a=c.query):D(b)&&(c=b,b=0);let e=[],f=[],g,h,k,l,n,q,r,v=0;if(c)if(c.constructor===Array)k=c,c=null;else if(k=(g=c.pluck)||c.field||c.doc,n=c.tag,h=this.store&&c.enrich,q="and"===c.bool,b=c.limit||100,r=c.offset||0,k&&(C(k)?k=[k]:k.constructor!==Array&&(l=k,k=Object.keys(k))),n&&(C(n)&&(n=[n]),!a)){for(let m=0,t;m<n.length;m++)if(t=ua.call(this,n[m],b,r,h))e[e.length]=t,v++;return v?e:[]}k||(k=this.g);q=q&&(1<k.length||n&&1<n.length);const p=!d&&(this.j||this.async)&&
|
||||||
u.import=function(a,b){if(b)switch(D(b)&&(b=JSON.parse(b)),a){case "tag":this.h=b;break;case "reg":this.i=!1;this.register=b;for(let d=0,e;d<this.g.length;d++)e=this.j[this.g[d]],e.register=b,e.i=!1;break;case "store":this.store=b;break;default:a=a.split(".");const c=a[0];a=a[1];c&&a&&this.j[c].import(a,b)}};da(R.prototype);const X=self||window,Y={Index:L,Document:R,WorkerAdapter:P,registerCharset:function(a,b){ca[a]=b},registerLanguage:function(a,b){H[a]=b}};let Z;(Z=X.define)&&Z.amd?Z([],function(){return Y}):X.exports?X.exports=Y:X.FlexSearch=Y;}(module));
|
[];for(let m=0,t,x,F;m<k.length;m++){let N;x=k[m];C(x)?l&&(N=l[x]):(N=x,x=x.field);if(p)p[m]=this.l[x].searchAsync(a,b,N||c);else{d?t=d[m]:t=this.l[x].search(a,b,N||c);F=t.length;if(n&&F){const G=[];let la=0;q&&(G[0]=[t]);for(let U=0,ma,O;U<n.length;U++)if(ma=n[U],F=(O=this.h[ma])&&O.length)la++,G[G.length]=q?[O]:O;la&&(t=q?fa(G,b||100,r||0):ha(t,G),F=t.length)}if(F)f[v]=x,e[v++]=t;else if(q)return[]}}if(p){const m=this;return new Promise(function(t){Promise.all(p).then(function(x){t(m.search(a,b,
|
||||||
|
c,x))})})}if(!v)return[];if(g&&(!h||!this.store))return e[0];for(let m=0,t;m<f.length;m++){t=e[m];t.length&&h&&(t=va.call(this,t));if(g)return t;e[m]={field:f[m],result:t}}return e};function ua(a,b,c,d){let e=this.h[a],f=e&&e.length-c;if(f&&0<f){if(f>b||c)e=e.slice(c,c+b);d&&(e=va.call(this,e));return{tag:a,result:e}}}function va(a){const b=Array(a.length);for(let c=0,d;c<a.length;c++)d=a[c],b[c]={key:d,doc:this.store[d]};return b}u.contain=function(a){return!!this.register[a]};u.get=function(a){return this.store[a]};
|
||||||
|
u.set=function(a,b){this.store[a]=b;return this};u.searchCache=ia;u.export=function(a,b,c,d,e){e||(e=0);d||(d=0);if(d<this.g.length){const f=this.g[d],g=this.l[f];b=this;setTimeout(function(){g.export(a,b,e?f.replace(":","-"):"",d,e++)||(d++,e=1,b.export(a,b,f,d,e))})}else{let f;switch(e){case 1:c="tag";f=this.h;break;case 2:c="store";f=this.store;break;default:return}ka(a,this,c,d,e,f)}};
|
||||||
|
u.import=function(a,b){if(b)switch(C(b)&&(b=JSON.parse(b)),a){case "tag":this.h=b;break;case "reg":this.i=!1;this.register=b;for(let d=0,e;d<this.g.length;d++)e=this.l[this.g[d]],e.register=b,e.i=!1;break;case "store":this.store=b;break;default:a=a.split(".");const c=a[0];a=a[1];c&&a&&this.l[c].import(a,b)}};ea(S.prototype);const X=self;let Y;const Z={Index:L,Document:S,Worker:Q,registerCharset:function(a,b){da[a]=b},registerLanguage:function(a,b){ca[a]=b}};(Y=X.define)&&Y.amd?Y([],function(){return Z}):X.exports?X.exports=Z:X.FlexSearch=Z;}(this));
|
||||||
|
73
doc/0.7.0.md
73
doc/0.7.0.md
@@ -24,7 +24,7 @@ In a document every index can have its own configuration, except the `encoder`.
|
|||||||
|
|
||||||
You can use an instance of Index directly (very much like the old FlexSearch when not indexing documents, instead just ID and text contents).
|
You can use an instance of Index directly (very much like the old FlexSearch when not indexing documents, instead just ID and text contents).
|
||||||
|
|
||||||
### Basic Usage
|
### Load Library
|
||||||
|
|
||||||
#### ES6 Modules:
|
#### ES6 Modules:
|
||||||
|
|
||||||
@@ -53,12 +53,14 @@ Install the non-published beta version:
|
|||||||
npm install https://github.com/nextapps-de/flexsearch/tarball/0.7.0
|
npm install https://github.com/nextapps-de/flexsearch/tarball/0.7.0
|
||||||
```
|
```
|
||||||
|
|
||||||
Use as a npm module:
|
Use as a npm package:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const { Index, Document } = require("flexsearch");
|
const { Index, Document } = require("flexsearch");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
The method signature stays almost unchanged:
|
The method signature stays almost unchanged:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -87,19 +89,19 @@ Source Code v0.7.0-pre-alpha available here:<br>
|
|||||||
|
|
||||||
What is not included yet but comes soon?
|
What is not included yet but comes soon?
|
||||||
|
|
||||||
- ~~WebWorker (almost done)~~
|
- ~~WebWorker~~
|
||||||
- Worker for Node.js (almost done)
|
- Worker for Node.js (almost done)
|
||||||
- Inline Worker (optionally)
|
- ~~Inline Worker (optionally)~~
|
||||||
- Offset-Pagination (almost done)
|
- ~~Offset-Pagination~~
|
||||||
- ~~Export/Import (not implemented yet)~~
|
- ~~Export/Import (not implemented yet)~~
|
||||||
- ~~Tags (almost done)~~
|
- ~~Tags (almost done)~~
|
||||||
- ~~Bundles: Light, Compact, Full (almost done)~~
|
- ~~Bundles: Light, Compact, Full~~
|
||||||
- Test Automation (needs to be migrated)
|
- Test Automation (needs to be migrated)
|
||||||
- Benchmark Suite (almost done)
|
- Benchmark Suite (almost done)
|
||||||
|
|
||||||
What is not included yet and comes later?
|
What is not included yet and comes later?
|
||||||
|
|
||||||
- Engines (almost done)
|
- Engines
|
||||||
|
|
||||||
What will be dropped?
|
What will be dropped?
|
||||||
|
|
||||||
@@ -442,7 +444,7 @@ const index = new Document({
|
|||||||
|
|
||||||
Note: The context options from the field "content" also gets inherited by the corresponding field options, whereas this field options was inherited by the global option (so threshold would be "3" if not set in context options).
|
Note: The context options from the field "content" also gets inherited by the corresponding field options, whereas this field options was inherited by the global option (so threshold would be "3" if not set in context options).
|
||||||
|
|
||||||
#### Nested Data Fields
|
### Nested Data Fields
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -548,7 +550,7 @@ One advantage here is you can perform a search through the same field with diffe
|
|||||||
|
|
||||||
> When passing field-specific options you need to provide the full configuration for each field. They get not inherited like the document descriptor.
|
> When passing field-specific options you need to provide the full configuration for each field. They get not inherited like the document descriptor.
|
||||||
|
|
||||||
#### Complex Documents
|
### Complex Documents
|
||||||
|
|
||||||
You need to follow 2 rules for your documents:
|
You need to follow 2 rules for your documents:
|
||||||
|
|
||||||
@@ -625,7 +627,7 @@ index.search(query, {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Not Supported Documents (Sequential Data)
|
### Not Supported Documents (Sequential Data)
|
||||||
|
|
||||||
This example breaks both rules from above:
|
This example breaks both rules from above:
|
||||||
|
|
||||||
@@ -699,7 +701,7 @@ add([{
|
|||||||
|
|
||||||
You can skip the first loop when your document data has just one index as the outer array.
|
You can skip the first loop when your document data has just one index as the outer array.
|
||||||
|
|
||||||
#### Join / Append Arrays
|
### Join / Append Arrays
|
||||||
|
|
||||||
On the complex example above, the field `keywords` is an array but here the markup did not have brackets like `keywords[]`. That will also detect the array but instead of appending each entry to a new context, the array will be joined into on large string and added to the index.
|
On the complex example above, the field `keywords` is an array but here the markup did not have brackets like `keywords[]`. That will also detect the array but instead of appending each entry to a new context, the array will be joined into on large string and added to the index.
|
||||||
|
|
||||||
@@ -968,15 +970,25 @@ In this case the result-set looks like:
|
|||||||
}]
|
}]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Limit & Offset
|
||||||
|
|
||||||
> By default, every query is limited to 100 entries. Unbounded queries leads into issues. You need to set the limit as an option to adjust the size.
|
> By default, every query is limited to 100 entries. Unbounded queries leads into issues. You need to set the limit as an option to adjust the size.
|
||||||
|
|
||||||
|
You can set the limit and the offset for each query:
|
||||||
|
|
||||||
|
```js
|
||||||
|
index.search(query, { limit: 20, offset: 100 });
|
||||||
|
```
|
||||||
|
|
||||||
|
> You cannot pre-count the size of the result-set. That's a limit by the design of FlexSearch. When you really need a count of all results you are able to page through, then just assign a high enough limit and get back all results and apply your paging offset manually (this works also on server-side). FlexSearch is fast enough that this isn't an issue.
|
||||||
|
|
||||||
## Document Stores
|
## Document Stores
|
||||||
|
|
||||||
> Never use a store when: 1. you did not need the original data to process your query results, or 2. you already have the contents/documents stored elsewhere (outside the index).
|
> Do not use a store when: 1. an array of IDs as the result is good enough, or 2. you already have the contents/documents stored elsewhere (outside the index).
|
||||||
|
|
||||||
Only a document index have a store. You can use a document index instead of a flat index to get this functionality when only storing ID-content-pairs.
|
Only a document index can have a store. You can use a document index instead of a flat index to get this functionality also when only storing ID-content-pairs.
|
||||||
|
|
||||||
This will add the whole original content to the store (text as string or documents as objects):
|
This will add the whole original content to the store:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const index = new Document({ doc: "content", store: true });
|
const index = new Document({ doc: "content", store: true });
|
||||||
@@ -1073,6 +1085,25 @@ Your results are now looking like:
|
|||||||
|
|
||||||
Both field "author" and "email" are not indexed.
|
Both field "author" and "email" are not indexed.
|
||||||
|
|
||||||
|
### Extern Stores
|
||||||
|
|
||||||
|
When the data already exist in your application runtime, then you did not need to add those to the store again. You can assign your data as "extern store":
|
||||||
|
|
||||||
|
```js
|
||||||
|
const data = [{ ... }, { ... }, { ... }];
|
||||||
|
|
||||||
|
const index = new Document({
|
||||||
|
doc: "content",
|
||||||
|
extern: data // <--- extern store
|
||||||
|
});
|
||||||
|
|
||||||
|
index.add(data[0]);
|
||||||
|
```
|
||||||
|
|
||||||
|
> Entries from an extern store are not being managed/changed automatically by FlexSearch. When removing items from the index, the corresponding data item from the extern dataset stays untouched. Please consider, using the method `index.set(id, data)` will change extern stores also.
|
||||||
|
|
||||||
|
When you didn't use the data anywhere in your application (just for searching) then it is better to use an internal store and just select fields you need in the results, which costs you less memory.
|
||||||
|
|
||||||
## WebWorker
|
## WebWorker
|
||||||
|
|
||||||
The whole worker implementation has changed by also keeping Node.js support in mind. The good news is worker will also get supported by Node.js by the library.
|
The whole worker implementation has changed by also keeping Node.js support in mind. The good news is worker will also get supported by Node.js by the library.
|
||||||
@@ -1132,8 +1163,10 @@ When you perform a field search through all fields then this task is perfectly b
|
|||||||
|
|
||||||
Above we have seen that documents will create worker automatically for each field. You can also create a WorkerIndex directly (same like using `Index` instead of `Document`).
|
Above we have seen that documents will create worker automatically for each field. You can also create a WorkerIndex directly (same like using `Index` instead of `Document`).
|
||||||
|
|
||||||
|
Use as ES6 module:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import WorkerIndex from "./adapter.js";
|
import WorkerIndex from "./worker/index.js";
|
||||||
const index = new WorkerIndex(options);
|
const index = new WorkerIndex(options);
|
||||||
index.add(1, "some")
|
index.add(1, "some")
|
||||||
.add(2, "content")
|
.add(2, "content")
|
||||||
@@ -1141,6 +1174,16 @@ index.add(1, "some")
|
|||||||
.add(4, "index");
|
.add(4, "index");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Or when bundled version was used instead:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var index = new FlexSearch.Worker(options);
|
||||||
|
index.add(1, "some")
|
||||||
|
.add(2, "content")
|
||||||
|
.add(3, "to")
|
||||||
|
.add(4, "index");
|
||||||
|
```
|
||||||
|
|
||||||
Such a WorkerIndex works pretty much the same as a created instance of `Index`.
|
Such a WorkerIndex works pretty much the same as a created instance of `Index`.
|
||||||
|
|
||||||
> A WorkerIndex only support the `async` variant of all methods. That means when you call `index.search()` on a WorkerIndex this will perform also in async the same way as `index.searchAsync()` will do.
|
> A WorkerIndex only support the `async` variant of all methods. That means when you call `index.search()` on a WorkerIndex this will perform also in async the same way as `index.searchAsync()` will do.
|
||||||
|
@@ -1,82 +0,0 @@
|
|||||||
import { promise as Promise } from "./polyfill.js";
|
|
||||||
import { is_function, is_object } from "./common.js";
|
|
||||||
|
|
||||||
let counter = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number|string|Object} id
|
|
||||||
* @param {Object=} options
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
|
|
||||||
function WorkerAdapter(id, options){
|
|
||||||
|
|
||||||
if(is_object(id)){
|
|
||||||
|
|
||||||
options = /** @type {Object} */ (id);
|
|
||||||
id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(options && is_function(options["encode"])){
|
|
||||||
|
|
||||||
options["encode"] = options["encode"].toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
this.id = id || counter++;
|
|
||||||
this.resolver = null;
|
|
||||||
this.worker = new Worker("worker.js", { type: "module" });
|
|
||||||
this.worker.onmessage = function(e){ self.resolver(e["data"]/*["results"]*/) };
|
|
||||||
this.worker.postMessage({ task: "create", /*id: this.id,*/ options: options });
|
|
||||||
}
|
|
||||||
|
|
||||||
export default WorkerAdapter;
|
|
||||||
|
|
||||||
register("add");
|
|
||||||
register("append");
|
|
||||||
register("search");
|
|
||||||
register("update");
|
|
||||||
register("remove");
|
|
||||||
|
|
||||||
function register(key){
|
|
||||||
|
|
||||||
WorkerAdapter.prototype[key] =
|
|
||||||
WorkerAdapter.prototype[key + "Async"] = function(){
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
const args = [].slice.call(arguments);
|
|
||||||
const arg = args[args.length - 1];
|
|
||||||
let callback;
|
|
||||||
|
|
||||||
if(is_function(arg)){
|
|
||||||
|
|
||||||
callback = arg;
|
|
||||||
args.splice(args.length - 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const promise = new Promise(function(resolve){
|
|
||||||
|
|
||||||
self.worker.postMessage({ task: key, /*id: this.id,*/ args: args });
|
|
||||||
|
|
||||||
if(key === "search"){
|
|
||||||
|
|
||||||
self.resolver = resolve;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if(callback){
|
|
||||||
|
|
||||||
promise.then(callback);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@@ -3,16 +3,6 @@ export function parse_option(value, default_value){
|
|||||||
return typeof value !== "undefined" ? value : default_value;
|
return typeof value !== "undefined" ? value : default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {!Object} obj
|
|
||||||
* @returns {Array<string>}
|
|
||||||
*/
|
|
||||||
|
|
||||||
export function get_keys(obj){
|
|
||||||
|
|
||||||
return Object.keys(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!number} count
|
* @param {!number} count
|
||||||
* @returns {Array<Object>}
|
* @returns {Array<Object>}
|
||||||
@@ -42,6 +32,16 @@ export function create_arrays(count){
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} obj
|
||||||
|
* @returns {Array<string>}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function get_keys(obj){
|
||||||
|
|
||||||
|
return Object.keys(obj);
|
||||||
|
}
|
||||||
|
|
||||||
export function create_object(){
|
export function create_object(){
|
||||||
|
|
||||||
return Object.create(null);
|
return Object.create(null);
|
||||||
|
118
src/document.js
118
src/document.js
@@ -20,11 +20,11 @@ import {
|
|||||||
import Index from "./index.js";
|
import Index from "./index.js";
|
||||||
import { DocumentInterface } from "./type.js";
|
import { DocumentInterface } from "./type.js";
|
||||||
import Cache, { searchCache } from "./cache.js";
|
import Cache, { searchCache } from "./cache.js";
|
||||||
import { create_object, is_array, is_string, is_object, parse_option } from "./common.js";
|
import { create_object, is_array, is_string, is_object, parse_option, get_keys } from "./common.js";
|
||||||
import apply_async from "./async.js";
|
import apply_async from "./async.js";
|
||||||
import { intersect, intersect_union } from "./intersect.js";
|
import { intersect, intersect_union } from "./intersect.js";
|
||||||
import { exportDocument, importDocument } from "./serialize.js";
|
import { exportDocument, importDocument } from "./serialize.js";
|
||||||
import WorkerAdapter from "./adapter.js";
|
import WorkerIndex from "./worker/index.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
@@ -53,8 +53,9 @@ function Document(options){
|
|||||||
|
|
||||||
if(SUPPORT_STORE){
|
if(SUPPORT_STORE){
|
||||||
|
|
||||||
this.store = (opt = options["store"]) && create_object();
|
this.extern = !!(opt = options["extern"]);
|
||||||
this.storetree = opt && (opt !== true) && [];
|
this.storetree = !this.extern && (opt = options["store"]) && (opt !== true) && [];
|
||||||
|
this.store = opt && (this.extern ? opt : create_object());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SUPPORT_TAGS){
|
if(SUPPORT_TAGS){
|
||||||
@@ -66,6 +67,9 @@ function Document(options){
|
|||||||
if(SUPPORT_CACHE){
|
if(SUPPORT_CACHE){
|
||||||
|
|
||||||
this.cache = (opt = options["cache"]) && new Cache(opt);
|
this.cache = (opt = options["cache"]) && new Cache(opt);
|
||||||
|
|
||||||
|
// do not apply cache again for the indexes
|
||||||
|
|
||||||
options["cache"] = false;
|
options["cache"] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +80,8 @@ function Document(options){
|
|||||||
|
|
||||||
if(SUPPORT_ASYNC){
|
if(SUPPORT_ASYNC){
|
||||||
|
|
||||||
|
// this switch is used by recall of promise callbacks
|
||||||
|
|
||||||
this.async = false;
|
this.async = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +107,7 @@ function parse_descriptor(options){
|
|||||||
else if(!is_array(field)){
|
else if(!is_array(field)){
|
||||||
|
|
||||||
field_options = field;
|
field_options = field;
|
||||||
field = Object.keys(field);
|
field = get_keys(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let i = 0, key, opt; i < field.length; i++){
|
for(let i = 0, key, opt; i < field.length; i++){
|
||||||
@@ -120,11 +126,20 @@ function parse_descriptor(options){
|
|||||||
|
|
||||||
opt = is_object(opt) ? Object.assign({}, options, opt) : options;
|
opt = is_object(opt) ? Object.assign({}, options, opt) : options;
|
||||||
|
|
||||||
index[key] = this.worker ?
|
if(this.worker){
|
||||||
|
|
||||||
new WorkerAdapter(opt)
|
index[key] = new WorkerIndex(opt);
|
||||||
:
|
|
||||||
new Index(opt, this.register);
|
if(!index[key].worker){
|
||||||
|
|
||||||
|
this.worker = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.worker){
|
||||||
|
|
||||||
|
index[key] = new Index(opt, this.register);
|
||||||
|
}
|
||||||
|
|
||||||
this.tree[i] = parse_tree(key, this.marker);
|
this.tree[i] = parse_tree(key, this.marker);
|
||||||
this.field[i] = key;
|
this.field[i] = key;
|
||||||
@@ -349,7 +364,7 @@ Document.prototype.add = function(id, content, _append){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SUPPORT_STORE && this.store){
|
if(SUPPORT_STORE && this.store && !this.extern){
|
||||||
|
|
||||||
let store;
|
let store;
|
||||||
|
|
||||||
@@ -374,7 +389,6 @@ Document.prototype.add = function(id, content, _append){
|
|||||||
|
|
||||||
this.store[id] = store || content;
|
this.store[id] = store || content;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -441,7 +455,7 @@ Document.prototype.remove = function(id){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SUPPORT_STORE && this.store){
|
if(SUPPORT_STORE && this.store && !this.extern){
|
||||||
|
|
||||||
delete this.store[id];
|
delete this.store[id];
|
||||||
}
|
}
|
||||||
@@ -452,16 +466,24 @@ Document.prototype.remove = function(id){
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Document.prototype.search = function(query, limit, options, resolve){
|
/**
|
||||||
|
* @param {!string|Object} query
|
||||||
|
* @param {number|Object=} limit
|
||||||
|
* @param {Object=} options
|
||||||
|
* @param {Array<Array>=} _resolve For internal use only.
|
||||||
|
* @returns {Promise|Array}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Document.prototype.search = function(query, limit, options, _resolve){
|
||||||
|
|
||||||
if(is_object(query)){
|
if(is_object(query)){
|
||||||
|
|
||||||
options = query;
|
options = /** @type {Object} */ (query);
|
||||||
query = options["query"];
|
query = options["query"];
|
||||||
}
|
}
|
||||||
else if(is_object(limit)){
|
else if(is_object(limit)){
|
||||||
|
|
||||||
options = limit;
|
options = /** @type {Object} */ (limit);
|
||||||
limit = 0;
|
limit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,7 +522,7 @@ Document.prototype.search = function(query, limit, options, resolve){
|
|||||||
else if(!is_array(field)){
|
else if(!is_array(field)){
|
||||||
|
|
||||||
field_options = field;
|
field_options = field;
|
||||||
field = Object.keys(field);
|
field = get_keys(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,40 +558,7 @@ Document.prototype.search = function(query, limit, options, resolve){
|
|||||||
field || (field = this.field);
|
field || (field = this.field);
|
||||||
bool = bool && ((field.length > 1) || (tag && (tag.length > 1)));
|
bool = bool && ((field.length > 1) || (tag && (tag.length > 1)));
|
||||||
|
|
||||||
// use Promise.all to get a change of processing requests in parallel
|
const promises = !_resolve && (this.worker || this.async) && [];
|
||||||
|
|
||||||
if(!resolve && (this.worker || this.async)){
|
|
||||||
|
|
||||||
resolve = [];
|
|
||||||
|
|
||||||
for(let i = 0, key; i < field.length; i++){
|
|
||||||
|
|
||||||
let opt;
|
|
||||||
|
|
||||||
key = field[i];
|
|
||||||
|
|
||||||
if(!is_string(key)){
|
|
||||||
|
|
||||||
opt = key;
|
|
||||||
key = key["field"];
|
|
||||||
}
|
|
||||||
else if(field_options){
|
|
||||||
|
|
||||||
opt = field_options[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve[i] = this.index[key].searchAsync(query, limit, opt || options);
|
|
||||||
}
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
// anyone knows a better workaround of optionally having async promises?
|
|
||||||
|
|
||||||
return Promise.all(resolve).then(function(resolve){
|
|
||||||
|
|
||||||
self.search(query, limit, options, resolve);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO solve this in one loop below
|
// TODO solve this in one loop below
|
||||||
|
|
||||||
@@ -589,9 +578,17 @@ Document.prototype.search = function(query, limit, options, resolve){
|
|||||||
opt = field_options[key];
|
opt = field_options[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(resolve){
|
if(promises){
|
||||||
|
|
||||||
res = resolve[i];
|
promises[i] = this.index[key].searchAsync(query, limit, opt || options);
|
||||||
|
|
||||||
|
// just collect and continue
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(_resolve){
|
||||||
|
|
||||||
|
res = _resolve[i];
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
||||||
@@ -653,6 +650,23 @@ Document.prototype.search = function(query, limit, options, resolve){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(promises){
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
// anyone knows a better workaround of optionally having async promises?
|
||||||
|
// the promise.all() needs to be wrapped into additional promise,
|
||||||
|
// otherwise the recursive callback wouldn't run before return
|
||||||
|
|
||||||
|
return new Promise(function(resolve){
|
||||||
|
|
||||||
|
Promise.all(promises).then(function(result){
|
||||||
|
|
||||||
|
resolve(self.search(query, limit, options, result));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if(!count){
|
if(!count){
|
||||||
|
|
||||||
// fast path "not found"
|
// fast path "not found"
|
||||||
|
239
src/index.js
239
src/index.js
@@ -319,8 +319,8 @@ Index.prototype.push_index = function(dupes, value, score, id, append, keyword){
|
|||||||
|
|
||||||
if(keyword){
|
if(keyword){
|
||||||
|
|
||||||
dupes[value] || (dupes[value] = create_object());
|
dupes = dupes[value] || (dupes[value] = create_object());
|
||||||
dupes[value][keyword] = 1;
|
dupes[keyword] = 1;
|
||||||
|
|
||||||
arr = arr[keyword] || (arr[keyword] = create_object());
|
arr = arr[keyword] || (arr[keyword] = create_object());
|
||||||
}
|
}
|
||||||
@@ -453,7 +453,7 @@ Index.prototype.search = function(query, limit, options){
|
|||||||
|
|
||||||
if(depth){
|
if(depth){
|
||||||
|
|
||||||
arr = this.add_result(result, suggest, resolution_ctx, limit, length === 2, term, keyword);
|
arr = this.add_result(result, suggest, resolution_ctx, limit, offset, length === 2, term, keyword);
|
||||||
|
|
||||||
// when suggestion enabled just forward keyword if term was found
|
// when suggestion enabled just forward keyword if term was found
|
||||||
// as long as the result is empty forward the pointer also
|
// as long as the result is empty forward the pointer also
|
||||||
@@ -465,7 +465,7 @@ Index.prototype.search = function(query, limit, options){
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
||||||
arr = this.add_result(result, suggest, resolution, limit, length === 1, term);
|
arr = this.add_result(result, suggest, resolution, limit, offset, length === 1, term);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(arr){
|
if(arr){
|
||||||
@@ -497,20 +497,7 @@ Index.prototype.search = function(query, limit, options){
|
|||||||
|
|
||||||
// fast path optimization
|
// fast path optimization
|
||||||
|
|
||||||
result = result[0];
|
return single_result(result[0], limit, offset);
|
||||||
|
|
||||||
if(result.length === 1){
|
|
||||||
|
|
||||||
result = result[0];
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
|
|
||||||
result = concat(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO apply offset
|
|
||||||
|
|
||||||
return result.length > limit ? result.slice(0, limit) : result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,6 +505,127 @@ Index.prototype.search = function(query, limit, options){
|
|||||||
return intersect(result, limit, offset, suggest);
|
return intersect(result, limit, offset, suggest);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array when the result is done (to stop the process immediately),
|
||||||
|
* returns false when suggestions is enabled and no result was found,
|
||||||
|
* or returns nothing when a set was pushed successfully to the results
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} result
|
||||||
|
* @param {Array} suggest
|
||||||
|
* @param {number} resolution
|
||||||
|
* @param {number} limit
|
||||||
|
* @param {number} offset
|
||||||
|
* @param {boolean} single_term
|
||||||
|
* @param {string} term
|
||||||
|
* @param {string=} keyword
|
||||||
|
* @return {Array<Array<string|number>>|boolean|undefined}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Index.prototype.add_result = function(result, suggest, resolution, limit, offset, single_term, term, keyword){
|
||||||
|
|
||||||
|
let word_arr = [];
|
||||||
|
let arr = keyword ? this.ctx : this.map;
|
||||||
|
|
||||||
|
if(!this.optimize){
|
||||||
|
|
||||||
|
arr = get_array(arr, term, keyword, this.bidirectional);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(arr){
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
const arr_len = Math.min(arr.length, resolution);
|
||||||
|
|
||||||
|
for(let x = 0, size = 0, tmp, len; x < arr_len; x++){
|
||||||
|
|
||||||
|
tmp = arr[x];
|
||||||
|
|
||||||
|
if(this.optimize){
|
||||||
|
|
||||||
|
tmp = get_array(tmp, term, keyword, this.bidirectional);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tmp && single_term){
|
||||||
|
|
||||||
|
len = tmp.length;
|
||||||
|
|
||||||
|
if(len <= offset){
|
||||||
|
|
||||||
|
offset -= len;
|
||||||
|
tmp = null;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
if(offset){
|
||||||
|
|
||||||
|
tmp = tmp.slice(offset);
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tmp){
|
||||||
|
|
||||||
|
// keep score (sparse array):
|
||||||
|
//word_arr[x] = tmp;
|
||||||
|
|
||||||
|
// simplified score order:
|
||||||
|
word_arr[count++] = tmp;
|
||||||
|
|
||||||
|
if(single_term){
|
||||||
|
|
||||||
|
size += tmp.length;
|
||||||
|
|
||||||
|
if(size >= limit){
|
||||||
|
|
||||||
|
// fast path optimization
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count){
|
||||||
|
|
||||||
|
if(single_term){
|
||||||
|
|
||||||
|
// fast path optimization
|
||||||
|
// offset was already applied at this point
|
||||||
|
|
||||||
|
return single_result(word_arr, limit, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
result[result.length] = word_arr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return an empty array will stop the loop,
|
||||||
|
// to prevent stop when using suggestions return a false value
|
||||||
|
|
||||||
|
return !suggest && word_arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
function single_result(result, limit, offset){
|
||||||
|
|
||||||
|
if(result.length === 1){
|
||||||
|
|
||||||
|
result = result[0];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
result = concat(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset || (result.length > limit) ?
|
||||||
|
|
||||||
|
result.slice(offset, offset + limit)
|
||||||
|
:
|
||||||
|
result;
|
||||||
|
}
|
||||||
|
|
||||||
function get_array(arr, term, keyword, bidirectional){
|
function get_array(arr, term, keyword, bidirectional){
|
||||||
|
|
||||||
if(keyword){
|
if(keyword){
|
||||||
@@ -535,101 +643,6 @@ function get_array(arr, term, keyword, bidirectional){
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array when the result is done (to stop the process immediately),
|
|
||||||
* returns false when suggestions is enabled and no result was found,
|
|
||||||
* or returns nothing when a set was pushed successfully to the results
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Array} result
|
|
||||||
* @param {Array} suggest
|
|
||||||
* @param {number} resolution
|
|
||||||
* @param {number} limit
|
|
||||||
* @param {boolean} just_one_loop
|
|
||||||
* @param {string} term
|
|
||||||
* @param {string=} keyword
|
|
||||||
* @return {Array<Array<string|number>>|boolean|undefined}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Index.prototype.add_result = function(result, suggest, resolution, limit, just_one_loop, term, keyword){
|
|
||||||
|
|
||||||
let word_arr = [];
|
|
||||||
let arr = keyword ? this.ctx : this.map;
|
|
||||||
|
|
||||||
if(!this.optimize){
|
|
||||||
|
|
||||||
arr = get_array(arr, term, keyword, this.bidirectional);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(arr){
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
const arr_len = Math.min(arr.length, resolution);
|
|
||||||
|
|
||||||
for(let x = 0, size = 0, tmp; x < arr_len; x++){
|
|
||||||
|
|
||||||
tmp = arr[x];
|
|
||||||
|
|
||||||
if(this.optimize){
|
|
||||||
|
|
||||||
tmp = get_array(tmp, term, keyword, this.bidirectional);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tmp){
|
|
||||||
|
|
||||||
// TODO apply offset
|
|
||||||
|
|
||||||
// keep score (sparse array):
|
|
||||||
//word_arr[x] = arr;
|
|
||||||
|
|
||||||
// simplified score order:
|
|
||||||
word_arr[count++] = tmp;
|
|
||||||
|
|
||||||
if(just_one_loop){
|
|
||||||
|
|
||||||
size += tmp.length;
|
|
||||||
|
|
||||||
if(size >= limit){
|
|
||||||
|
|
||||||
// fast path optimization
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count){
|
|
||||||
|
|
||||||
if(just_one_loop){
|
|
||||||
|
|
||||||
// TODO apply offset
|
|
||||||
|
|
||||||
// fast path optimization
|
|
||||||
|
|
||||||
if(count === 1){
|
|
||||||
|
|
||||||
word_arr = word_arr[0];
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
|
|
||||||
word_arr = concat(word_arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return word_arr.length > limit ? word_arr.slice(0, limit) : word_arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
result[result.length] = word_arr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return an empty array will stop the loop,
|
|
||||||
// to prevent stop when using suggestions return a false value
|
|
||||||
|
|
||||||
return !suggest && word_arr;
|
|
||||||
};
|
|
||||||
|
|
||||||
Index.prototype.contain = function(id){
|
Index.prototype.contain = function(id){
|
||||||
|
|
||||||
return !!this.register[id];
|
return !!this.register[id];
|
||||||
|
@@ -18,7 +18,7 @@ export function intersect(arrays, limit, offset, suggest) {
|
|||||||
// return a.length - b.length;
|
// return a.length - b.length;
|
||||||
// });
|
// });
|
||||||
|
|
||||||
let check = create_object();
|
let check;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
if(suggest){
|
if(suggest){
|
||||||
@@ -26,16 +26,16 @@ export function intersect(arrays, limit, offset, suggest) {
|
|||||||
suggest = [];
|
suggest = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// terms
|
// terms in reversed order!
|
||||||
for(let x = 0; x < length; x++){
|
for(let x = length - 1; x >= 0; x--){
|
||||||
|
|
||||||
const word_arr = arrays[x];
|
const word_arr = arrays[x];
|
||||||
const word_arr_len = word_arr.length;
|
const word_arr_len = word_arr.length;
|
||||||
const new_check = create_object();
|
const new_check = create_object();
|
||||||
|
|
||||||
let found = !x;
|
let found = !check;
|
||||||
|
|
||||||
// relevance
|
// but relevance in forward order
|
||||||
for(let y = 0; y < word_arr_len; y++){
|
for(let y = 0; y < word_arr_len; y++){
|
||||||
|
|
||||||
//const arr = [].concat.apply([], word_arr);
|
//const arr = [].concat.apply([], word_arr);
|
||||||
@@ -44,23 +44,18 @@ export function intersect(arrays, limit, offset, suggest) {
|
|||||||
|
|
||||||
if(arr_len){
|
if(arr_len){
|
||||||
|
|
||||||
if(suggest){
|
|
||||||
|
|
||||||
suggest[y] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// ids
|
// ids
|
||||||
for(let z = 0, count_suggest = 0, id; z < arr_len; z++){
|
for(let z = 0, count_suggest = 0, id; z < arr_len; z++){
|
||||||
|
|
||||||
id = arr[z];
|
id = arr[z];
|
||||||
|
|
||||||
if(!x){
|
if(!check){
|
||||||
|
|
||||||
new_check[id] = 1;
|
new_check[id] = 1;
|
||||||
}
|
}
|
||||||
else if(check[id]){
|
else if(check[id]){
|
||||||
|
|
||||||
if(x === (length - 1)){
|
if(!x){
|
||||||
|
|
||||||
if(offset){
|
if(offset){
|
||||||
|
|
||||||
@@ -82,7 +77,9 @@ export function intersect(arrays, limit, offset, suggest) {
|
|||||||
|
|
||||||
if(suggest && (count_suggest < limit)){
|
if(suggest && (count_suggest < limit)){
|
||||||
|
|
||||||
suggest[y][count_suggest++] = id;
|
const tmp = suggest[y] || (suggest[y] = []);
|
||||||
|
|
||||||
|
tmp[count_suggest++] = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_check[id] = 1;
|
new_check[id] = 1;
|
||||||
@@ -109,18 +106,30 @@ export function intersect(arrays, limit, offset, suggest) {
|
|||||||
res = suggest[i];
|
res = suggest[i];
|
||||||
len = res && res.length;
|
len = res && res.length;
|
||||||
|
|
||||||
// TODO apply offset
|
if(len && offset){
|
||||||
|
|
||||||
|
if(len <= offset){
|
||||||
|
|
||||||
|
offset -= len;
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
len -= offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(len){
|
if(len){
|
||||||
|
|
||||||
if(count + len >= limit){
|
if(count + len >= limit){
|
||||||
|
|
||||||
return result.concat(res.slice(0, limit - count));
|
return result.concat(res.slice(offset, limit - count + offset));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
||||||
result = result.concat(res);
|
result = result.concat(offset ? res.slice(offset) : res);
|
||||||
count += len;
|
count += len;
|
||||||
|
offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { IndexInterface, DocumentInterface } from "./type.js";
|
import { IndexInterface, DocumentInterface } from "./type.js";
|
||||||
import { create_object } from "./common.js";
|
import { create_object, get_keys } from "./common.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!string} str
|
* @param {!string} str
|
||||||
@@ -161,7 +161,7 @@ export function init_filter(words){
|
|||||||
|
|
||||||
export function init_stemmer_or_matcher(obj, is_stemmer){
|
export function init_stemmer_or_matcher(obj, is_stemmer){
|
||||||
|
|
||||||
const keys = Object.keys(obj);
|
const keys = get_keys(obj);
|
||||||
const length = keys.length;
|
const length = keys.length;
|
||||||
const final = [];
|
const final = [];
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { SUPPORT_ASYNC, SUPPORT_DOCUMENT, SUPPORT_CACHE, SUPPORT_SERIALIZE } from "./config.js";
|
import { SUPPORT_ASYNC, SUPPORT_DOCUMENT, SUPPORT_CACHE, SUPPORT_SERIALIZE } from "./config.js";
|
||||||
import Document from "./document.js";
|
import Document from "./document.js";
|
||||||
import Index from "./index.js";
|
import Index from "./index.js";
|
||||||
import WorkerAdapter from "./adapter.js";
|
import WorkerIndex from "./worker/index.js";
|
||||||
import { registerCharset, registerLanguage } from "./global.js";
|
import { registerCharset, registerLanguage } from "./global.js";
|
||||||
|
|
||||||
/** @export */ Document.prototype.add;
|
/** @export */ Document.prototype.add;
|
||||||
@@ -49,19 +49,18 @@ if(SUPPORT_SERIALIZE){
|
|||||||
/** @export */ Document.prototype.import;
|
/** @export */ Document.prototype.import;
|
||||||
}
|
}
|
||||||
|
|
||||||
const root = self || window;
|
const root = self;
|
||||||
|
let tmp;
|
||||||
|
|
||||||
const FlexSearch = {
|
const FlexSearch = {
|
||||||
|
|
||||||
"Index": Index,
|
"Index": Index,
|
||||||
"Document": SUPPORT_DOCUMENT ? Document : null,
|
"Document": SUPPORT_DOCUMENT ? Document : null,
|
||||||
"WorkerAdapter": WorkerAdapter,
|
"Worker": WorkerIndex,
|
||||||
"registerCharset": registerCharset,
|
"registerCharset": registerCharset,
|
||||||
"registerLanguage": registerLanguage
|
"registerLanguage": registerLanguage
|
||||||
};
|
};
|
||||||
|
|
||||||
let tmp;
|
|
||||||
|
|
||||||
if((tmp = root["define"]) && tmp["amd"]){
|
if((tmp = root["define"]) && tmp["amd"]){
|
||||||
|
|
||||||
tmp([], function(){
|
tmp([], function(){
|
||||||
|
@@ -1,29 +1,44 @@
|
|||||||
import Index from "./index.js";
|
import Index from "../index.js";
|
||||||
import { is_string, is_object } from "./common.js";
|
|
||||||
|
|
||||||
let index, id;
|
export default function handler(event) {
|
||||||
|
|
||||||
onmessage = function(event) {
|
/** @type Index */
|
||||||
|
const index = self["_index"];
|
||||||
const data = event.data;
|
const data = event["data"];
|
||||||
const args = data["args"];
|
const args = data["args"];
|
||||||
|
|
||||||
switch(data["task"]){
|
switch(data["task"]){
|
||||||
|
|
||||||
case "create":
|
case "init":
|
||||||
|
|
||||||
const options = data["options"] || {};
|
const options = data["options"] || {};
|
||||||
|
const factory = data["factory"];
|
||||||
const encode = options["encode"];
|
const encode = options["encode"];
|
||||||
|
|
||||||
options["cache"] = false;
|
options["cache"] = false;
|
||||||
id = data["id"];
|
//root["_id"] = data["id"];
|
||||||
|
|
||||||
if(is_string(encode)){
|
if(typeof encode === "string"){
|
||||||
|
|
||||||
options["encode"] = new Function("return " + encode)();
|
options["encode"] = new Function("return " + encode)();
|
||||||
}
|
}
|
||||||
|
|
||||||
index = new Index(options);
|
if(factory){
|
||||||
|
|
||||||
|
// export the FlexSearch global payload to "self"
|
||||||
|
new Function("return " + factory)()(self);
|
||||||
|
|
||||||
|
/** @type Index */
|
||||||
|
self["_index"] = self["FlexSearch"]["Index"](options);
|
||||||
|
|
||||||
|
// destroy the exported payload
|
||||||
|
delete self["FlexSearch"];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
self["_index"] = new Index(options);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "add":
|
case "add":
|
134
src/worker/index.js
Normal file
134
src/worker/index.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import { promise as Promise } from "../polyfill.js";
|
||||||
|
import { is_function, is_object } from "../common.js";
|
||||||
|
import handler from "./handler.js";
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number|string|Object} id
|
||||||
|
* @param {Object=} options
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
function WorkerIndex(id, options){
|
||||||
|
|
||||||
|
let opt;
|
||||||
|
|
||||||
|
if(is_object(id)){
|
||||||
|
|
||||||
|
options = /** @type {Object} */ (id);
|
||||||
|
id = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
if(options){
|
||||||
|
|
||||||
|
if(is_function(opt = options["encode"])){
|
||||||
|
|
||||||
|
options["encode"] = opt.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the factory is the outer wrapper from the build
|
||||||
|
// we use "self" as a trap for node.js
|
||||||
|
|
||||||
|
let factory = (self||window)["_factory"];
|
||||||
|
|
||||||
|
if(factory){
|
||||||
|
|
||||||
|
factory = factory.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const _self = this;
|
||||||
|
|
||||||
|
this.id = id || counter++;
|
||||||
|
this.resolver = null;
|
||||||
|
this.worker = create(factory);
|
||||||
|
|
||||||
|
if(!this.worker){
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.worker.onmessage = function(e){ _self.resolver(e["data"]/*["results"]*/) };
|
||||||
|
this.worker.postMessage({ "task": "init", "factory": factory, /*id: this.id,*/ "options": options });
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WorkerIndex;
|
||||||
|
|
||||||
|
register("add");
|
||||||
|
register("append");
|
||||||
|
register("search");
|
||||||
|
register("update");
|
||||||
|
register("remove");
|
||||||
|
|
||||||
|
function register(key){
|
||||||
|
|
||||||
|
WorkerIndex.prototype[key] =
|
||||||
|
WorkerIndex.prototype[key + "Async"] = function(){
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
const args = [].slice.call(arguments);
|
||||||
|
const arg = args[args.length - 1];
|
||||||
|
let callback;
|
||||||
|
|
||||||
|
if(is_function(arg)){
|
||||||
|
|
||||||
|
callback = arg;
|
||||||
|
args.splice(args.length - 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const promise = new Promise(function(resolve){
|
||||||
|
|
||||||
|
self.worker.postMessage({ "task": key, /*id: this.id,*/ "args": args });
|
||||||
|
|
||||||
|
if(key === "search"){
|
||||||
|
|
||||||
|
self.resolver = resolve;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(callback){
|
||||||
|
|
||||||
|
promise.then(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function create(factory){
|
||||||
|
|
||||||
|
let worker
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
worker = factory ?
|
||||||
|
|
||||||
|
new Worker(URL.createObjectURL(
|
||||||
|
|
||||||
|
new Blob([
|
||||||
|
|
||||||
|
"onmessage=" + handler.toString()
|
||||||
|
|
||||||
|
], { "type": "text/javascript" })
|
||||||
|
))
|
||||||
|
:
|
||||||
|
new Worker("worker.js", { type: "module" });
|
||||||
|
}
|
||||||
|
catch(e){}
|
||||||
|
|
||||||
|
return worker;
|
||||||
|
}
|
2
src/worker/worker.js
Normal file
2
src/worker/worker.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import handler from "./handler.js";
|
||||||
|
onmessage = handler;
|
@@ -137,7 +137,7 @@ let parameter = (function(opt){
|
|||||||
rewrite_polyfills: use_polyfill || false,
|
rewrite_polyfills: use_polyfill || false,
|
||||||
|
|
||||||
// isolation_mode: "IIFE",
|
// isolation_mode: "IIFE",
|
||||||
output_wrapper: "(function(self){%output%}(module));"
|
output_wrapper: "(function(self){%output%}(this));"
|
||||||
|
|
||||||
//formatting: "PRETTY_PRINT"
|
//formatting: "PRETTY_PRINT"
|
||||||
});
|
});
|
||||||
@@ -232,6 +232,8 @@ else{
|
|||||||
preserve = preserve.replace("* FlexSearch.js", "* FlexSearch.js v" + package_json.version + (light_version ? " (Light)" : es5_version ? " (ES5)" : ""));
|
preserve = preserve.replace("* FlexSearch.js", "* FlexSearch.js v" + package_json.version + (light_version ? " (Light)" : es5_version ? " (ES5)" : ""));
|
||||||
build = preserve.substring(0, preserve.indexOf('*/') + 2) + "\n" + build;
|
build = preserve.substring(0, preserve.indexOf('*/') + 2) + "\n" + build;
|
||||||
|
|
||||||
|
build = build.replace("(function(self){'use strict';", "(function _f(self){'use strict';try{if(module)self=module}catch(e){}self._factory=_f;");
|
||||||
|
|
||||||
if(release === "pre"){
|
if(release === "pre"){
|
||||||
|
|
||||||
fs.existsSync("test/dist") || fs.mkdirSync("test/dist");
|
fs.existsSync("test/dist") || fs.mkdirSync("test/dist");
|
||||||
|
Reference in New Issue
Block a user