From e5f79b984c647c00b2196ed37482e589fed9c098 Mon Sep 17 00:00:00 2001 From: Thomas Wilkerling Date: Thu, 31 Jan 2019 11:46:45 +0100 Subject: [PATCH] v0.3.4 --- .gitignore | 1 + README.md | 46 ++++++++++-- flexsearch.compact.js | 34 ++++----- flexsearch.js | 138 +++++++++++++++++++++++------------- flexsearch.light.js | 21 +++--- flexsearch.min.js | 45 ++++++------ test/benchmark-presets.html | 2 +- test/benchmark.html | 4 +- test/flexsearch.es5.js | 58 +++++++-------- test/matching-presets.html | 2 +- test/matching.html | 2 +- test/test.js | 10 +-- 12 files changed, 218 insertions(+), 145 deletions(-) diff --git a/.gitignore b/.gitignore index 88e71fd..1b8cba3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ coverage perf node_modules +server !*.keep src tmp diff --git a/README.md b/README.md index efc8805..3095e38 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ - + - +

@@ -19,12 +19,14 @@ When it comes to raw search speed most memory-efficient index. Keep in mind that updating and/or removing existing items from the index has a significant cost. When your index needs to be updated very often then BulkSearch may be a better choice. FlexSearch also provides you a non-blocking asynchronous processing model as well as web workers to perform any updates or queries on the index in parallel through dedicated balanced threads. -Installation Guide  •  API Reference  •  Example Options  •  Custom Builds +Installation Guide  •  API Reference  •  Example Options  •  Custom Builds  •  Flexsearch Server Supported Platforms: - Browser - Node.js +> FlexSearch Server is also available here: https://github.com/nextapps-de/flexsearch-server + Library Comparison: - Benchmark "Gulliver's Travels" - Relevance Scoring @@ -201,10 +203,10 @@ __Query Test: "Gulliver's Travels"__ 1 FlexSearch *** - 0.3.2 - 342040 - 178456 - 1527778 + 0.3.3 + 363757 + 182603 + 1627219 @@ -543,6 +545,8 @@ Index methods: - Index.__info__() - Index.__addMatcher__({_KEY: VALUE_}) - Index.__encode__(string) +- Index.__export__() +- Index.__import__(string) ## Usage @@ -1589,6 +1593,34 @@ index.add(index_table["fdf12cad-8779-47ab-b614-4dbbd649178b"], "content"); It is planned to provide a built-in feature which should replace this workaround. + +## Export/Import Index + +> index.export() returns a serialized dump as a string. + +> index.import(string) takes a serialized dump as a string and load it to the index. + +Assuming you have one or several indexes: +```js +var feeds_2017 = new FlexSearch(); +var feeds_2018 = new FlexSearch(); +var feeds_2019 = new FlexSearch(); +``` + +Export indexes, e.g. to the local storage: +```js +localStorage.setItem("feeds_2017", feeds_2017.export()); +localStorage.setItem("feeds_2018", feeds_2018.export()); +localStorage.setItem("feeds_2019", feeds_2019.export()); +``` + +Import indexes, e.g. from the local storage: +```js +feeds_2017.import(localStorage.getItem("feeds_2017")); +feeds_2018.import(localStorage.getItem("feeds_2018")); +feeds_2019.import(localStorage.getItem("feeds_2019")); +``` + ## Debug diff --git a/flexsearch.compact.js b/flexsearch.compact.js index 3dd1c6c..d6c50c8 100644 --- a/flexsearch.compact.js +++ b/flexsearch.compact.js @@ -5,20 +5,20 @@ Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';(function(g,r,c){let h;(h=c.define)&&h.amd?h([],function(){return r}):(h=c.modules)?h[g.toLowerCase()]=r:"object"===typeof exports?module.exports=r:c[g]=r})("FlexSearch",function(){function g(a){y(a)&&(a=G[a]);a||(a=t);this.id=a.id||M++;this.init(a);r(this,"index",function(){return this.b});r(this,"length",function(){return Object.keys(this.b).length})}function r(a,b,d){Object.defineProperty(a,b,{get:d})}function c(a){return new RegExp(a,"g")}function h(a,b){for(let d=0;d=k&&(a=a[e+.5>>0],a=a[d]||(a[d]=[]),a[a.length]=f);return e}function C(a,b){if(a){const d=Object.keys(a);for(let f=0,e=d.length;fa?1:a?-1:0}function O(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function P(a,b,d){let c=[],e=[];const u=a.length;if(1b&&(c=c.slice(0,b)));return c}function y(a){return"string"===typeof a}function z(a){return"function"===typeof a}function A(a){return"undefined"===typeof a}function E(a){a.l||(a.l=H(function(){a.l= -0;{const b=a.async;let d;b&&(a.async=!1);if(a.c.length){const b=Date.now();let c;for(;(c=a.c.shift())||0===c;){d=a.f[c];switch(d[0]){case B.add:a.add(d[1],d[2]);break;case B.remove:a.remove(d[1])}delete a.f[c];if(100n;d--)k=c.substring(n,d), -x(l,f,k,a,b,g,h)}break;default:if(e=x(l,f,c,a,1,g,h),u&&1=h)for(e=f._ctx[c]||(f._ctx[c]=q()),c=this.g[c]||(this.g[c]=I(10)),g=m-u,k=m+u+1,0>g&&(g=0),k>p&&(k=p);gb;b++)C(this.i[b], -a);this.depth&&C(this.g,a);delete this.b[a]}return this};g.prototype.search=function(a,b,c,f){let d=a,g,k=[];"object"===typeof a&&((c=a.callback||b)&&(d.callback=null),b=a.limit,g=a.threshold,a=a.query);g||(g=this.threshold||0);z(b)?(c=b,b=1E3):b||0===b||(b=1E3);if(c){{let a=this;H(function(){c(a.search(d,b,null,!0));a=null},1,"search-"+this.id)}}else{if(!f&&this.async&&"function"!==typeof importScripts){let a=this;return new Promise(function(c){c(a.search(d,b,null,!0));a=null})}if(!a||!y(a))return k; -d=a;d=this.encode(d);if(!d.length)return k;a=this.a;a=z(a)?a(d):d.split(J);f=a.length;var h=!0,r=[],v=q();if(1=g;e--)if(f=l[e][c])a[d++]=f,b=!0}if(b)r[r.length]=1=h&&(a=a[9-(f+.5>>0)],a=a[d]||(a[d]=[]),a[a.length]=e);return f}function D(a,b){if(a){const d=Object.keys(a);for(let e=0,f=d.length;ea?1:a?-1:0}function Q(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function R(a,b,d){let c=[],f;const z=a.length;if(1b&&(c=c.slice(0,b)));return c}function y(a){return"string"===typeof a}function A(a){return"function"===typeof a}function B(a){return"undefined"===typeof a}function F(a){a.l|| +(a.l=J(function(){a.l=0;{const b=a.async;let d;b&&(a.async=!1);if(a.c.length){const b=Date.now();let c;for(;(c=a.c.shift())||0===c;){d=a.g[c];switch(d[0]){case C.add:a.add(d[1],d[2]);break;case C.remove:a.remove(d[1])}delete a.g[c];if(100k;d--)h= +c.substring(k,d),x(r,p,h,a,b,g,n)}break;default:if(f=x(r,p,c,a,1,g,n),l&&1=n)for(f=p._ctx[c]||(p._ctx[c]=t()),c=this.f[c]||(this.f[c]=K(10-(n||0))),g=e-l,h=e+l+1,0>g&&(g=0),h>q&&(h=q);g 1) && (score >= threshold)){ const ctxDupes = dupes["_ctx"][value] || (dupes["_ctx"][value] = create_object()); - const ctxTmp = this._ctx[value] || (this._ctx[value] = create_object_array(10)); + const ctxTmp = this._ctx[value] || (this._ctx[value] = create_object_array(10 - (threshold || 0))); let x = i - depth; let y = i + depth + 1; @@ -838,7 +840,7 @@ // update status - this._ids[id] = 1; + this._ids[index] = 1; if(SUPPORT_CACHE){ @@ -863,7 +865,9 @@ FlexSearch.prototype.update = function(id, content){ - if(this._ids[id] && is_string(content)){ + const index = "@" + id; + + if(this._ids[index] && is_string(content)){ if(PROFILER){ @@ -889,11 +893,13 @@ FlexSearch.prototype.remove = function(id){ - if(this._ids[id]){ + const index = "@" + id; + + if(this._ids[index]){ if(SUPPORT_WORKER && this.worker){ - const current_task = this._ids[id]; + const current_task = this._ids[index]; this._worker[current_task].postMessage(current_task, { @@ -903,19 +909,19 @@ //this._ids_count[current_task]--; - delete this._ids[id]; + delete this._ids[index]; return this; } if(SUPPORT_ASYNC && this.async){ - this._stack[id] || ( + this._stack[index] || ( - this._stack_keys[this._stack_keys.length] = id + this._stack_keys[this._stack_keys.length] = index ); - this._stack[id] = [ + this._stack[index] = [ enum_task.remove, id @@ -931,7 +937,7 @@ profile_start("remove"); } - for(let z = 0; z < 10; z++){ + for(let z = 0; z < (10 - (this.threshold || 0)); z++){ remove_index(this._map[z], id); } @@ -941,7 +947,7 @@ remove_index(this._ctx, id); } - delete this._ids[id]; + delete this._ids[index]; if(SUPPORT_CACHE){ @@ -1177,7 +1183,7 @@ let map_value; - for(let z = 9; z >= threshold; z--){ + for(let z = 0; z < (10 - threshold); z++){ if((map_value = map[z][value])){ @@ -1278,7 +1284,7 @@ words = 0, chars = 0; - for(let z = 0; z < 10; z++){ + for(let z = 0; z < (10 - (this.threshold || 0)); z++){ keys = get_keys(this._map[z]); @@ -1314,7 +1320,7 @@ "worker": this.worker, "threshold": this.threshold, "depth": this.depth, - "contextual": !!this.depth + "contextual": this.depth && (this.tokenize === "strict") }; }; } @@ -1362,6 +1368,33 @@ return this; }; + /** + * @export + */ + + FlexSearch.prototype.export = function(){ + + return JSON.stringify([ + + this._map, + this._ctx, + this._ids + ]); + }; + + /** + * @export + */ + + FlexSearch.prototype.import = function(payload){ + + payload = JSON.parse(payload); + + this._map = payload[0]; + this._ctx = payload[1]; + this._ids = payload[2]; + }; + /** @const */ const global_encoder_balance = (function(){ @@ -1612,9 +1645,9 @@ const stack = create_object(); - return function(fn, delay, id){ + return function(fn, delay, key){ - const timer = stack[id]; + const timer = stack[key]; if(timer){ @@ -1623,7 +1656,7 @@ return ( - stack[id] = setTimeout(fn, delay) + stack[key] = setTimeout(fn, delay) ); }; @@ -1653,9 +1686,9 @@ this.ids = []; }; - Cache.prototype.set = function(id, value){ + Cache.prototype.set = function(key, value){ - if(this.limit && is_undefined(this.cache[id])){ + if(this.limit && is_undefined(this.cache[key])){ let length = this.ids.length; @@ -1670,18 +1703,18 @@ delete this.index[last_id]; } - this.index[id] = length; - this.ids[length] = id; - this.count[id] = -1; - this.cache[id] = value; + this.index[key] = length; + this.ids[length] = key; + this.count[key] = -1; + this.cache[key] = value; // shift up counter +1 - this.get(id); + this.get(key); } else{ - this.cache[id] = value; + this.cache[key] = value; } }; @@ -1689,15 +1722,15 @@ * Note: It is better to have the complexity when fetching the cache: */ - Cache.prototype.get = function(id){ + Cache.prototype.get = function(key){ - const cache = this.cache[id]; + const cache = this.cache[key]; if(this.limit && cache){ - const count = ++this.count[id]; + const count = ++this.count[key]; const index = this.index; - let current_index = index[id]; + let current_index = index[key]; if(current_index > 0){ @@ -1728,8 +1761,8 @@ } // push new value on top - ids[current_index] = id; - index[id] = current_index; + ids[current_index] = key; + index[key] = current_index; } } } @@ -1858,7 +1891,7 @@ if(score >= threshold){ - let arr = map[((score + 0.5) >> 0)]; + let arr = map[9 - ((score + 0.5) >> 0)]; arr = arr[value] || (arr[value] = []); arr[arr.length] = id; @@ -2187,7 +2220,7 @@ function intersect(arrays, limit, suggest) { let result = []; - let suggestions = []; + let suggestions; const length_z = arrays.length; if(length_z > 1){ @@ -2205,7 +2238,7 @@ while(i < length) { - check[arr[i++]] = 1; + check["@" + arr[i++]] = 1; } // loop through arrays @@ -2229,9 +2262,11 @@ tmp = arr[i++]; - if(check[tmp]){ + const index = "@" + tmp; - const check_val = check[tmp]; + if(check[index]){ + + const check_val = check[index]; if(check_val === z){ @@ -2248,7 +2283,7 @@ } else{ - check[tmp] = z + 1; + check[index] = z + 1; } // apply count status @@ -2617,7 +2652,7 @@ runner(ref); - }, 1, "search-async-" + ref.id) + }, 1, "@" + ref.id) ); } @@ -2814,12 +2849,15 @@ "" : - "const SUPPORT_WORKER = true;" + - "const DEBUG = " + (DEBUG ? "true" : "false") + ";" + - "const PROFILER = " + (PROFILER ? "true" : "false") + ";" + - "const SUPPORT_ENCODER = " + (SUPPORT_ENCODER ? "true" : "false") + ";" + - "const SUPPORT_CACHE = " + (SUPPORT_CACHE ? "true" : "false") + ";" + - "const SUPPORT_ASYNC = " + (SUPPORT_ASYNC ? "true" : "false") + ";" + "var RELEASE = '" + RELEASE + "';" + + "var DEBUG = " + (DEBUG ? "true" : "false") + ";" + + "var PROFILER = " + (PROFILER ? "true" : "false") + ";" + + "var SUPPORT_PRESETS = " + (SUPPORT_PRESETS ? "true" : "false") + ";" + + "var SUPPORT_SUGGESTIONS = " + (SUPPORT_SUGGESTIONS ? "true" : "false") + ";" + + "var SUPPORT_ENCODER = " + (SUPPORT_ENCODER ? "true" : "false") + ";" + + "var SUPPORT_CACHE = " + (SUPPORT_CACHE ? "true" : "false") + ";" + + "var SUPPORT_ASYNC = " + (SUPPORT_ASYNC ? "true" : "false") + ";" + + "var SUPPORT_WORKER = true;" ) + "(" + _worker.toString() + ")()" ],{ diff --git a/flexsearch.light.js b/flexsearch.light.js index 2c75bbb..387a9ff 100644 --- a/flexsearch.light.js +++ b/flexsearch.light.js @@ -5,13 +5,14 @@ Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';(function(f,u,v){let k;(k=v.define)&&k.amd?k([],function(){return u}):(k=v.modules)?k[f.toLowerCase()]=u:"object"===typeof exports?module.exports=u:v[f]=u})("FlexSearch",function(){function f(a){a||(a=x);this.id=a.id||G++;this.init(a);u(this,"index",function(){return this.a});u(this,"length",function(){return Object.keys(this.a).length})}function u(a,b,c){Object.defineProperty(a,b,{get:c})}function v(a,b){for(let c=0;c=g&&(a=a[d+.5>>0],a=a[c]||(a[c]=[]),a[a.length]=e);return d}function z(a,b){if(a){const c=Object.keys(a);for(let e=0,d=c.length;ea?1:a?-1:0}function I(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function y(a){return"function"===typeof a} -function A(a){return"undefined"===typeof a}function C(a){const b=Array(a);for(let c=0;cm;c--)g=e.substring(m,c),k(r,f,g,a,b,h,l)}break;default:if(d=k(r,f,e,a,1,h,l),p&&1=l)for(d=f._ctx[e]||(f._ctx[e]=q()),e=this.c[e]||(this.c[e]=C(10)),h=t-p,g=t+p+1,0>h&&(h=0),g>n&&(g=n);hb;b++)z(this.g[b],a);this.depth&&z(this.c,a);delete this.a[a]}return this};f.prototype.search=function(a,b,c){var e=a,d=[];if("object"===typeof a){b=a.limit;var h=a.threshold;a=a.query}h||(h=this.threshold||0);y(b)?(c=b,b=1E3):b||0===b||(b=1E3);if(c)c(this.search(e,b,null,!0));else{if(!a||"string"!==typeof a)return d; -e=this.encode(a);if(!e.length)return d;a=this.b;a=y(a)?a(e):e.split(D);c=a.length;var g=!0;e=[];var f=q();if(1=h;e--)if(d=l[e][n])a[c++]=d,b=!0}if(b)e[e.length]=1b&&(h=h.slice(0,b)));d=h}return d}};f.prototype.clear=function(){this.destroy();return this.init()};f.prototype.destroy=function(){this.filter=this.stemmer=this.g=this.c=this.a=null;return this};const w={icase:function(a){return a.toLowerCase()}};return f}(!1),this); +'use strict';(function(e,u,v){let k;(k=v.define)&&k.amd?k([],function(){return u}):(k=v.modules)?k[e.toLowerCase()]=u:"object"===typeof exports?module.exports=u:v[e]=u})("FlexSearch",function(){function e(a){a||(a=x);this.id=a.id||G++;this.init(a);u(this,"index",function(){return this.a});u(this,"length",function(){return Object.keys(this.a).length})}function u(a,b,c){Object.defineProperty(a,b,{get:c})}function v(a,b){for(let c=0;c=g&&(a=a[9-(d+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=f);return d}function z(a,b){if(a){const c=Object.keys(a);for(let f=0,d=c.length;fa?1:a?-1:0}function I(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function y(a){return"function"===typeof a} +function A(a){return"undefined"===typeof a}function C(a){const b=Array(a);for(let c=0;ch;c--)g=f.substring(h,c),k(q,l,g,a,b,m,n)}break;default:if(d=k(q,l,f,a,1,m,n),t&&1=n)for(d=l._ctx[f]||(l._ctx[f]=r()),f=this.b[f]||(this.b[f]=C(10-(n||0))),m=e-t,g=e+t+1,0>m&&(m=0),g>p&&(g= +p);mb&&(e=e.slice(0,b)));d=e}return d}};e.prototype.clear=function(){this.destroy();return this.init()};e.prototype.destroy=function(){this.filter=this.stemmer=this.c=this.b= +this.a=null;return this};e.prototype.export=function(){return JSON.stringify([this.c,this.b,this.a])};e.prototype.import=function(a){a=JSON.parse(a);this.c=a[0];this.b=a[1];this.a=a[2]};const w={icase:function(a){return a.toLowerCase()}};return e}(!1),this); diff --git a/flexsearch.min.js b/flexsearch.min.js index 75057df..d881c1f 100644 --- a/flexsearch.min.js +++ b/flexsearch.min.js @@ -5,25 +5,26 @@ Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';(function(r,A,g){let v;(v=g.define)&&v.amd?v([],function(){return A}):(v=g.modules)?v[r.toLowerCase()]=A:"object"===typeof exports?module.exports=A:g[r]=A})("FlexSearch",function P(r){function g(a){C(a)&&(a=I[a]);a||(a=w);this.id=a.id||Q++;this.init(a);v(this,"index",function(){return this.a});v(this,"length",function(){return Object.keys(this.a).length})}function v(a,b,d){Object.defineProperty(a,b,{get:d})}function e(a){return new RegExp(a,"g")}function x(a,b){for(let d=0;d=h&&(a=a[f+.5>>0],a=a[d]||(a[d]=[]),a[a.length]=c);return f}function p(a,b){if(a){const d=Object.keys(a);for(let c=0,f=d.length;ca?1:a?-1:0}function V(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function W(a,b,d){let c=[],f=[];const l=a.length;if(1b&&(c=c.slice(0,b)));return c}function C(a){return"string"===typeof a}function D(a){return"function"===typeof a}function z(a){return"undefined"===typeof a}function G(a){a.D||(a.D=K(function(){a.D=0;{const b=a.async;let d;b&&(a.async=!1);if(a.f.length){const b=Date.now();let f;for(;(f=a.f.shift())||0===f;){d=a.g[f];switch(d[0]){case E.add:a.add(d[1],d[2]);break;case E.remove:a.remove(d[1])}delete a.g[f]; -if(100=f&&(c.o=c.c),c.B&&c.o===c.c&&(c.cache&&c.i.set(b,c.h),c.B(c.h),c.h=[]),c})}else a.worker=!1,this.j=null;this.b=a.tokenize||d.b||this.b||w.b;this.async=z(b=a.async)?this.async||w.async:b;this.c=z(b=a.worker)?this.c||w.c:b;this.threshold=z(b=a.threshold)?d.threshold||this.threshold||w.threshold:b;this.depth=z(b=a.depth)?d.depth||this.depth||w.depth:b;this.u=z(b=a.suggest)?this.u||w.u:b;this.s=(b=z(b=a.encode)?d.encode:b)&&B[b]&&B[b].bind(B)|| -(D(b)?b:this.s||!1);(b=a.matcher)&&this.addMatcher(b);if(b=a.filter)this.filter=S(N[b]||b,this.s);if(b=a.stemmer)this.stemmer=T(O[b]||b,this.s);this.w=L(10);this.l=q();this.a=q();this.g=q();this.f=[];this.D=0;this.v=!0;this.i=(this.cache=b=z(b=a.cache)?this.cache||w.cache:b)?new Y(b):!1;return this};g.prototype.encode=function(a){a&&H.length&&(a=x(a,H));a&&this.C.length&&(a=x(a,this.C));a&&this.s&&(a=this.s(a));a&&this.stemmer&&(a=x(a,this.stemmer));return a};g.prototype.addMatcher=function(a){const b= -this.C;for(const d in a)a.hasOwnProperty(d)&&b.push(e(d),a[d]);return this};g.prototype.add=function(a,b,d){if(b&&C(b)&&(a||0===a))if(this.a[a]&&!d)this.update(a,b);else{if(this.c)return++this.m>=this.j.length&&(this.m=0),this.j[this.m].postMessage(this.m,{add:!0,id:a,content:b}),this.a[a]=""+this.m,this;if(this.async)return this.g[a]||(this.f[this.f.length]=a),this.g[a]=[E.add,a,b],G(this),this;b=this.encode(b);if(!b.length)return this;d=this.b;b=D(d)?d(b):b.split(M);const l=q();l._ctx=q();const u= -this.threshold,t=this.depth,n=this.w,m=b.length;for(let k=0;kg;d--)h=c.substring(g,d),y(n,l,h,a,b,e,u)}break;default:if(f=y(n,l,c,a,1,e,u),t&&1=u)for(f=l._ctx[c]||(l._ctx[c]=q()),c=this.l[c]||(this.l[c]=L(10)),e=k-t,h=k+t+ -1,0>e&&(e=0),h>m&&(h=m);eb;b++)p(this.w[b],a);this.depth&&p(this.l,a); -delete this.a[a];this.v=!1}return this};g.prototype.search=function(a,b,d,c){let f=a,e;var h=[];"object"===typeof a&&((d=a.callback||b)&&(f.callback=null),b=a.limit,e=a.threshold,a=a.query);e||(e=this.threshold||0);D(b)?(d=b,b=1E3):b||0===b||(b=1E3);if(this.c)for(this.B=d,this.o=0,this.h=[],h=0;h=e;h--)if(f=m[h][b])a[d++]=f,c=!0}if(c)r[r.length]=1d;c--)f=e[c-1],e[c]=f,b[f]=c;e[d]=a;b[a]=d}}}return b};return a}();return g}(function(){const r={}, -A="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(g,v,e,x,y){let p=g;g=A?URL.createObjectURL(new Blob(["("+e.toString()+")()"],{type:"text/javascript"})):p+".min.js";p+="-"+v;r[p]||(r[p]=[]);r[p][y]=new Worker(g);r[p][y].onmessage=x;return{postMessage:function(e,g){r[p][e].postMessage(g)}}}}()),this); +'use strict';(function(t,A,g){let v;(v=g.define)&&v.amd?v([],function(){return A}):(v=g.modules)?v[t.toLowerCase()]=A:"object"===typeof exports?module.exports=A:g[t]=A})("FlexSearch",function P(t){function g(a){C(a)&&(a=I[a]);a||(a=w);this.id=a.id||Q++;this.init(a);v(this,"index",function(){return this.a});v(this,"length",function(){return Object.keys(this.a).length})}function v(a,b,d){Object.defineProperty(a,b,{get:d})}function e(a){return new RegExp(a,"g")}function x(a,b){for(let d=0;d=h&&(a=a[9-(f+.5>>0)],a=a[d]||(a[d]=[]),a[a.length]=c);return f}function q(a,b){if(a){const d=Object.keys(a);for(let c=0,f=d.length;ca?1:a?-1:0}function U(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function V(a,b,d){let c=[],f;const k=a.length;if(1b&&(c=c.slice(0,b)));return c}function C(a){return"string"===typeof a}function D(a){return"function"===typeof a}function z(a){return"undefined"===typeof a}function G(a){a.D||(a.D=K(function(){a.D=0;{const b=a.async;let d;b&&(a.async=!1);if(a.f.length){const b=Date.now();let f;for(;(f=a.f.shift())||0===f;){d=a.h[f];switch(d[0]){case E.add:a.add(d[1],d[2]);break;case E.remove:a.remove(d[1])}delete a.h[f]; +if(100=f&&(c.s=c.c),c.B&&c.s===c.c&&(c.cache&&c.j.set(b,c.i),c.B(c.i),c.i=[]),c})}else a.worker=!1,this.m=null;this.b=a.tokenize||d.b||this.b||w.b;this.async=z(b=a.async)?this.async||w.async:b;this.c=z(b=a.worker)?this.c||w.c:b;this.threshold=z(b=a.threshold)?d.threshold||this.threshold||w.threshold:b;this.depth=z(b=a.depth)?d.depth||this.depth||w.depth:b;this.v=z(b=a.suggest)?this.v||w.v:b;this.u=(b=z(b=a.encode)?d.encode:b)&&B[b]&&B[b].bind(B)|| +(D(b)?b:this.u||!1);(b=a.matcher)&&this.addMatcher(b);if(b=a.filter)this.filter=R(N[b]||b,this.u);if(b=a.stemmer)this.stemmer=S(O[b]||b,this.u);this.l=L(10-(this.threshold||0));this.g=n();this.a=n();this.h=n();this.f=[];this.D=0;this.w=!0;this.j=(this.cache=b=z(b=a.cache)?this.cache||w.cache:b)?new X(b):!1;return this};g.prototype.encode=function(a){a&&H.length&&(a=x(a,H));a&&this.C.length&&(a=x(a,this.C));a&&this.u&&(a=this.u(a));a&&this.stemmer&&(a=x(a,this.stemmer));return a};g.prototype.addMatcher= +function(a){const b=this.C;for(const d in a)a.hasOwnProperty(d)&&b.push(e(d),a[d]);return this};g.prototype.add=function(a,b,d){if(b&&C(b)&&(a||0===a)){const k="@"+a;if(this.a[k]&&!d)this.update(a,b);else{if(this.c)return++this.o>=this.m.length&&(this.o=0),this.m[this.o].postMessage(this.o,{add:!0,id:a,content:b}),this.a[k]=""+this.o,this;if(this.async)return this.h[k]||(this.f[this.f.length]=k),this.h[k]=[E.add,a,b],G(this),this;b=this.encode(b);if(!b.length)return this;d=this.b;b=D(d)?d(b):b.split(M); +const u=n();u._ctx=n();const p=this.threshold,r=this.depth,l=this.l,m=b.length;for(let k=0;kg;d--)h=c.substring(g,d),y(l,u,h,a,b,e,p)}break;default:if(f=y(l,u,c,a,1,e,p),r&&1=p)for(f=u._ctx[c]||(u._ctx[c]=n()),c=this.g[c]|| +(this.g[c]=L(10-(p||0))),e=k-r,h=k+r+1,0>e&&(e=0),h>m&&(h=m);ed;c--)f=e[c-1],e[c]=f,b[f]=c;e[d]=a;b[a]=d}}}return b};return a}();return g}(function(){const t={},A="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(g,v,e,x,y){let q=g;g=A?URL.createObjectURL(new Blob(["("+e.toString()+")()"],{type:"text/javascript"})):q+".min.js";q+="-"+v;t[q]||(t[q]=[]);t[q][y]=new Worker(g);t[q][y].onmessage= +x;return{postMessage:function(e,g){t[q][e].postMessage(g)}}}}()),this); diff --git a/test/benchmark-presets.html b/test/benchmark-presets.html index 2789045..e26d0c3 100644 --- a/test/benchmark-presets.html +++ b/test/benchmark-presets.html @@ -22,7 +22,7 @@

- + + @@ -346,7 +346,7 @@ Test rules: 1. no cache allowed, 2. no async allowed, 3. should return at least "Library " + "Benchmark (Single Phrase) " + "Benchmark (Multi Phrase) " + - "Benchmark (Mixed Not Found) " + + "Benchmark (Not Found) " + ""; for(var test in tests){ diff --git a/test/flexsearch.es5.js b/test/flexsearch.es5.js index c4a7222..33058b1 100644 --- a/test/flexsearch.es5.js +++ b/test/flexsearch.es5.js @@ -5,32 +5,32 @@ Released under the Apache 2.0 Licence https://github.com/nextapps-de/flexsearch */ -'use strict';function H(g){var h=0;return function(){return h=e&&(b=b[d+.5>>0],b=b[a]||(b[a]=[]),b[b.length]=f);return d}function m(b,c){if(b)for(var a=Object.keys(b),f=0,d=a.length;fb?1:b?-1:0}function U(b,c){b=b.length- -c.length;return 0>b?-1:b?1:0}function V(b,c,a){var f=[],d=[],e=b.length;if(1c&&(f=f.slice(0,c)));return f}function F(b){return"string"===typeof b}function C(b){return"function"===typeof b}function y(b){return"undefined"===typeof b}function D(b){b.F||(b.F=L(function(){b.F=0;var c=b.async;c&&(b.async=!1);if(b.b.length){for(var a=Date.now(),f;(f=b.b.shift())||0===f;){var d=b.c[f];switch(d[0]){case B.add:b.add(d[1],d[2]);break;case B.remove:b.remove(d[1])}delete b.c[f];if(100=d&&(f.o=f.i),f.C&&f.o===f.i&&(f.cache&&f.g.set(c,f.f),f.C(f.f), -f.f=[]),f})}else b.worker=!1,this.j=null;this.h=b.tokenize||a.h||this.h||x.h;this.async=y(c=b.async)?this.async||x.async:c;this.i=y(c=b.worker)?this.i||x.i:c;this.threshold=y(c=b.threshold)?a.threshold||this.threshold||x.threshold:c;this.depth=y(c=b.depth)?a.depth||this.depth||x.depth:c;this.w=y(c=b.suggest)?this.w||x.w:c;this.s=(c=y(c=b.encode)?a.encode:c)&&A[c]&&A[c].bind(A)||(C(c)?c:this.s||!1);(c=b.matcher)&&this.addMatcher(c);if(c=b.filter)this.filter=z(O[c]||c,this.s);if(c=b.stemmer)this.stemmer= -T(P[c]||c,this.s);this.v=M(10);this.l=w();this.a=w();this.c=w();this.b=[];this.F=0;this.u=!0;this.g=(this.cache=c=y(c=b.cache)?this.cache||x.cache:c)?new aa(c):!1;return this};e.prototype.encode=function(b){b&&E.length&&(b=l(b,E));b&&this.D.length&&(b=l(b,this.D));b&&this.s&&(b=this.s(b));b&&this.stemmer&&(b=l(b,this.stemmer));return b};e.prototype.addMatcher=function(b){var c=this.D,d;for(d in b)b.hasOwnProperty(d)&&c.push(a(d),b[d]);return this};e.prototype.add=function(b,c,a){if(c&&F(c)&&(b||0=== -b))if(this.a[b]&&!a)this.update(b,c);else{if(this.i)return++this.m>=this.j.length&&(this.m=0),this.j[this.m].postMessage(this.m,{add:!0,id:b,content:c}),this.a[b]=""+this.m,this;if(this.async)return this.c[b]||(this.b[this.b.length]=b),this.c[b]=[B.add,b,c],D(this),this;c=this.encode(c);if(!c.length)return this;a=this.h;c=C(a)?a(c):c.split(N);var f=w();f._ctx=w();for(var e=this.threshold,g=this.depth,k=this.v,r=c.length,u=0;uv;t--)q=l.substring(v,t),d(k,f,q,b,m,p,e);break;default:if(n=d(k,f,l,b,1,p,e),g&&1=e)for(n=f._ctx[l]||(f._ctx[l]=w()),l=this.l[l]||(this.l[l]=M(10)),p=u-g,q=u+g+1,0>p&&(p=0),q>r&&(q=r);pc;c++)m(this.v[c],b);this.depth&&m(this.l,b);delete this.a[b];this.u=!1}return this};e.prototype.search=function(b,c,a,d){var f=b,e=[];if("object"===typeof b){(a=b.callback||c)&&(f.callback=null);c=b.limit;var g=b.threshold; -b=b.query}g||(g=this.threshold||0);C(c)?(a=c,c=1E3):c||0===c||(c=1E3);if(this.i)for(this.C=a,this.o=0,this.f=[],e=0;e=g;G--)if(E=t[G][z])A[D++]=E,B=!0;if(B)p[p.length]=1e;c--)k=g[c-1],g[c]=k,d[k]=c;g[e]=a;d[a]=e}}}return b};return a}();return e}(function(){var g={},h="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(e,k,a,l,d){var m=e;e=h?URL.createObjectURL(new Blob(["("+a.toString()+")()"],{type:"text/javascript"})):m+".es5.js";m+="-"+k;g[m]||(g[m]=[]);g[m][d]=new Worker(e); -g[m][d].onmessage=l;return{postMessage:function(a,d){g[m][a].postMessage(d)}}}}()),this); +'use strict';function I(g){var h=0;return function(){return h=e&&(b=b[9-(d+.5>>0)],b=b[a]||(b[a]=[]),b[b.length]=f);return d}function l(b,c){if(b)for(var a=Object.keys(b),f=0,d=a.length;fb?1:b?-1:0}function V(b,c){b= +b.length-c.length;return 0>b?-1:b?1:0}function W(b,c,a){var f=[],d=b.length;if(1c&&(f=f.slice(0,c)));return f}function G(b){return"string"===typeof b}function F(b){return"function"===typeof b}function x(b){return"undefined"===typeof b}function D(b){b.F||(b.F=M(function(){b.F=0;var c=b.async;c&&(b.async=!1);if(b.b.length){for(var a=Date.now(),f;(f=b.b.shift())||0===f;){var d=b.f[f];switch(d[0]){case E.add:b.add(d[1],d[2]);break;case E.remove:b.remove(d[1])}delete b.f[f];if(100=d&&(f.s=f.i),f.C&& +f.s===f.i&&(f.cache&&f.j.set(c,f.g),f.C(f.g),f.g=[]),f})}else b.worker=!1,this.m=null;this.h=b.tokenize||a.h||this.h||u.h;this.async=x(c=b.async)?this.async||u.async:c;this.i=x(c=b.worker)?this.i||u.i:c;this.threshold=x(c=b.threshold)?a.threshold||this.threshold||u.threshold:c;this.depth=x(c=b.depth)?a.depth||this.depth||u.depth:c;this.w=x(c=b.suggest)?this.w||u.w:c;this.u=(c=x(c=b.encode)?a.encode:c)&&B[c]&&B[c].bind(B)||(F(c)?c:this.u||!1);(c=b.matcher)&&this.addMatcher(c);if(c=b.filter)this.filter= +C(P[c]||c,this.u);if(c=b.stemmer)this.stemmer=U(Q[c]||c,this.u);this.l=N(10-(this.threshold||0));this.c=v();this.a=v();this.f=v();this.b=[];this.F=0;this.v=!0;this.j=(this.cache=c=x(c=b.cache)?this.cache||u.cache:c)?new ba(c):!1;return this};e.prototype.encode=function(b){b&&H.length&&(b=m(b,H));b&&this.D.length&&(b=m(b,this.D));b&&this.u&&(b=this.u(b));b&&this.stemmer&&(b=m(b,this.stemmer));return b};e.prototype.addMatcher=function(b){var c=this.D,d;for(d in b)b.hasOwnProperty(d)&&c.push(a(d),b[d]); +return this};e.prototype.add=function(b,c,a){if(c&&G(c)&&(b||0===b)){var f="@"+b;if(this.a[f]&&!a)this.update(b,c);else{if(this.i)return++this.o>=this.m.length&&(this.o=0),this.m[this.o].postMessage(this.o,{add:!0,id:b,content:c}),this.a[f]=""+this.o,this;if(this.async)return this.f[f]||(this.b[this.b.length]=f),this.f[f]=[E.add,b,c],D(this),this;c=this.encode(c);if(!c.length)return this;a=this.h;c=F(a)?a(c):c.split(O);var e=v();e._ctx=v();for(var g=this.threshold,k=this.depth,w=this.l,m=c.length, +l=0;ln;z--)t=r.substring(n,z),d(w,e,t,b,y,q,g);break;default:if(p=d(w,e,r,b,1,q,g),k&&1=g)for(p=e._ctx[r]||(e._ctx[r]=v()),r=this.c[r]||(this.c[r]=N(10-(g||0))),q=l-k,t=l+k+1,0>q&&(q=0),t>m&&(t=m);qe;c--)k=g[c-1],g[c]=k,d[k]=c;g[e]=a;d[a]=e}}}return b};return a}();return e}(function(){var g={},h="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(e,k,a,m,d){var l=e;e=h?URL.createObjectURL(new Blob(["("+a.toString()+")()"],{type:"text/javascript"})):l+".es5.js";l+="-"+k;g[l]||(g[l]=[]);g[l][d]=new Worker(e);g[l][d].onmessage=m;return{postMessage:function(a,d){g[l][a].postMessage(d)}}}}()),this); diff --git a/test/matching-presets.html b/test/matching-presets.html index 570ace2..724ce42 100644 --- a/test/matching-presets.html +++ b/test/matching-presets.html @@ -16,7 +16,7 @@

Presets Relevance Scoring Comparison

Indexed Text: "Gulliver's Travels" (Swift Jonathan 1726)


- +
diff --git a/test/matching.html b/test/matching.html index 344c36c..d50dccd 100644 --- a/test/matching.html +++ b/test/matching.html @@ -201,7 +201,7 @@
Most relevant results was successfully found in the first place.
Note: Open console and type e.g. data[493] - + diff --git a/test/test.js b/test/test.js index 27deb9b..1047181 100644 --- a/test/test.js +++ b/test/test.js @@ -203,7 +203,7 @@ describe("Add (Sync)", function(){ flexsearch_sync.add(2, "bar"); flexsearch_sync.add(1, "foobar"); - expect(flexsearch_sync.index).to.have.keys([0, 1, 2]); + expect(flexsearch_sync.index).to.have.keys(["@0", "@1", "@2"]); expect(flexsearch_sync.length).to.equal(3); }); @@ -405,7 +405,7 @@ if(env !== "light"){ setTimeout(function(){ expect(flexsearch_async.length).to.equal(3); - expect(flexsearch_async.index).to.have.keys([0, 1, 2]); + expect(flexsearch_async.index).to.have.keys(["@0", "@1", "@2"]); done(); @@ -428,7 +428,7 @@ if(env !== "light"){ setTimeout(function(){ expect(flexsearch_async.length).to.equal(3); - expect(flexsearch_async.index).to.have.keys([0, 1, 2]); + expect(flexsearch_async.index).to.have.keys(["@0", "@1", "@2"]); done(); @@ -657,7 +657,7 @@ if(env !== "light"){ flexsearch_worker.add(1, "foobar"); expect(flexsearch_worker.length).to.equal(3); - expect(flexsearch_worker.index).to.have.keys([0, 1, 2]); + expect(flexsearch_worker.index).to.have.keys(["@0", "@1", "@2"]); flexsearch_worker.search("foo", function(result){ @@ -682,7 +682,7 @@ if(env !== "light"){ setTimeout(function(){ expect(flexsearch_worker.length).to.equal(3); - expect(flexsearch_worker.index).to.have.keys([0, 1, 2]); + expect(flexsearch_worker.index).to.have.keys(["@0", "@1", "@2"]); done();