flexsearch
Advanced tools
Comparing version 0.1.24 to 0.1.25
@@ -6,3 +6,3 @@ /**! | ||
* @preserve https://github.com/nextapps-de/flexsearch | ||
* @version: 0.1.24 | ||
* @version: 0.1.25 | ||
* @license: Apache 2.0 Licence | ||
@@ -48,5 +48,2 @@ */ | ||
// use flexible cache (scales automatically) | ||
threads: 4, | ||
// debug flag | ||
@@ -57,7 +54,7 @@ debug: true | ||
/** | ||
* @type {Array<Array>} | ||
* @type {Array} | ||
* @private | ||
*/ | ||
var custom_matchers = []; | ||
var global_matcher = []; | ||
@@ -83,3 +80,3 @@ /** | ||
/** | ||
* @param {Object<string, number|string|boolean>=} options | ||
* @param {Object<string, number|string|boolean|Object|function(string):string>=} options | ||
* @constructor | ||
@@ -93,2 +90,4 @@ * @private | ||
this.name = "FlexSearch"; | ||
// generate UID | ||
@@ -131,19 +130,19 @@ | ||
/** | ||
* @param {Object<string, number|string|boolean>=} options | ||
* @param {Object<string, number|string|boolean|Object|function(string):string>=} options | ||
* @export | ||
*/ | ||
FlexSearch.create = function(options){ | ||
FlexSearch.new = function(options){ | ||
return FlexSearch.new(options); | ||
return new this(options); | ||
}; | ||
/** | ||
* @param {Object<string, number|string|boolean>=} options | ||
* @param {Object<string, number|string|boolean|Object|function(string):string>=} options | ||
* @export | ||
*/ | ||
FlexSearch.new = function(options){ | ||
FlexSearch.create = function(options){ | ||
return new this(options); | ||
return FlexSearch.new(options); | ||
}; | ||
@@ -162,6 +161,4 @@ | ||
custom_matchers[custom_matchers.length] = [ | ||
regex(key), matcher[key] | ||
]; | ||
global_matcher[global_matcher.length] = regex(key); | ||
global_matcher[global_matcher.length] = matcher[key]; | ||
} | ||
@@ -172,8 +169,34 @@ } | ||
/** | ||
* @param {Object<string, number|string|boolean>=} options | ||
* @param {string} name | ||
* @param {function(string):string} encoder | ||
* @export | ||
*/ | ||
FlexSearch.register = function(name, encoder){ | ||
global_encoder[name] = encoder; | ||
}; | ||
/** | ||
* @param {!string} name | ||
* @param {!string} value | ||
* @returns {string} | ||
* @export | ||
*/ | ||
FlexSearch.encode = function(name, value){ | ||
return global_encoder[name](value); | ||
}; | ||
/** | ||
* @param {Object<string, number|string|boolean|Object|function(string):string>=} options | ||
* @export | ||
*/ | ||
FlexSearch.prototype.init = function(options){ | ||
/** @type {Array} */ | ||
this._matcher = []; | ||
if(options){ | ||
@@ -193,3 +216,3 @@ | ||
var self = this; | ||
var threads = options['threads'] || defaults.threads; | ||
var threads = options['worker'] || 4; | ||
@@ -206,3 +229,3 @@ self._current_task = -1; | ||
if(self._task_completed === self.threads){ | ||
if(self._task_completed === self.worker){ | ||
@@ -217,6 +240,6 @@ return; | ||
self._task_completed = self.threads; | ||
self._task_completed = self.worker; | ||
} | ||
if(self._current_callback && (self._task_completed === self.threads)){ | ||
if(self._current_callback && (self._task_completed === self.worker)){ | ||
@@ -290,15 +313,7 @@ if(self._task_result.length){ | ||
/** @export */ | ||
this.threads = ( | ||
options['threads'] || | ||
this.threads || | ||
defaults.threads | ||
); | ||
/** @export */ | ||
this.encoder = ( | ||
(options['encode'] && encoder[options['encode']]) || | ||
(options['encode'] && global_encoder[options['encode']]) || | ||
this.encoder || | ||
(defaults.encode && encoder[defaults.encode]) || | ||
(defaults.encode && global_encoder[defaults.encode]) || | ||
options['encode'] | ||
@@ -314,2 +329,7 @@ ); | ||
); | ||
if(options['matcher']) { | ||
this.addMatcher(/** @type {Object<string, string>} */ (options['matcher'])); | ||
} | ||
} | ||
@@ -319,3 +339,16 @@ | ||
this._map = {}; | ||
this._map = [ | ||
{/* 0 */}, | ||
{/* 1 */}, | ||
{/* 2 */}, | ||
{/* 3 */}, | ||
{/* 4 */}, | ||
{/* 5 */}, | ||
{/* 6 */}, | ||
{/* 7 */}, | ||
{/* 8 */}, | ||
{/* 9 */} | ||
]; | ||
this._ids = {}; | ||
@@ -362,10 +395,10 @@ | ||
if(custom_matchers.length){ | ||
if(global_matcher.length){ | ||
for(var i = 0; i < custom_matchers.length; i++){ | ||
value = replace(value, global_matcher); | ||
} | ||
var matcher = custom_matchers[i]; | ||
if(this._matcher.length){ | ||
value = value.replace(matcher[0], matcher[1]); | ||
} | ||
value = replace(value, this._matcher); | ||
} | ||
@@ -377,2 +410,19 @@ | ||
/** | ||
* @param {Object<string, string>} matcher | ||
* @export | ||
*/ | ||
FlexSearch.prototype.addMatcher = function(matcher){ | ||
for(var key in matcher){ | ||
if(matcher.hasOwnProperty(key)){ | ||
this._matcher[this._matcher.length] = regex(key); | ||
this._matcher[this._matcher.length] = matcher[key]; | ||
} | ||
} | ||
}; | ||
/** | ||
* @param {!number|string} id | ||
@@ -431,4 +481,14 @@ * @param {!string} content | ||
if(content && this.encode){ | ||
content = this.encode(content); | ||
} | ||
if(!content){ | ||
return; | ||
} | ||
var dupes = {}; | ||
var words = content.split(' '); | ||
var words = content.split(regex_split); | ||
@@ -442,61 +502,81 @@ for(var i = 0; i < words.length; i++){ | ||
if(this.encode){ | ||
switch(this.mode){ | ||
value = this.encode(value); | ||
} | ||
case 'inverse': | ||
case 'both': | ||
if(value){ | ||
var tmp = ""; | ||
switch(this.mode){ | ||
for(var a = value.length - 1; a >= 1; a--){ | ||
case 'inverse': | ||
case 'both': | ||
tmp = value[a] + tmp; | ||
var tmp = ""; | ||
addIndex( | ||
for(var a = value.length - 1; a >= 1; a--){ | ||
this._map, | ||
dupes, | ||
tmp, | ||
id, | ||
content | ||
); | ||
} | ||
tmp = value[a] + tmp; | ||
// Note: no break here, fallthrough to next case | ||
addIndex(this._map, dupes, tmp, id); | ||
} | ||
case 'forward': | ||
// Note: no break here, fallthrough to next case | ||
var tmp = ""; | ||
case 'forward': | ||
for(var a = 0; a < value.length; a++){ | ||
var tmp = ""; | ||
tmp += value[a]; | ||
for(var a = 0; a < value.length; a++){ | ||
addIndex( | ||
tmp += value[a]; | ||
this._map, | ||
dupes, | ||
tmp, | ||
id, | ||
content | ||
); | ||
} | ||
addIndex(this._map, dupes, tmp, id); | ||
} | ||
break; | ||
break; | ||
case 'full': | ||
case 'full': | ||
var tmp = ""; | ||
var tmp = ""; | ||
for(var x = 0; x < value.length; x++){ | ||
for(var x = 0; x < value.length; x++){ | ||
for(var y = value.length; y > x; y--){ | ||
for(var y = value.length; y > x; y--){ | ||
tmp = value.substring(x, y); | ||
tmp = value.substring(x, y); | ||
addIndex( | ||
addIndex(this._map, dupes, tmp, id); | ||
} | ||
this._map, | ||
dupes, | ||
tmp, | ||
id, | ||
content | ||
); | ||
} | ||
} | ||
break; | ||
break; | ||
case 'strict': | ||
default: | ||
case 'strict': | ||
default: | ||
addIndex(this._map, dupes, value, id); | ||
addIndex( | ||
break; | ||
} | ||
this._map, | ||
dupes, | ||
value, | ||
id, | ||
content | ||
); | ||
break; | ||
} | ||
@@ -611,12 +691,10 @@ } | ||
var lexical = Object.keys(this._map); | ||
for(var z = 0; z < 10; z++){ | ||
for(var z = 0; z < lexical.length; z++){ | ||
var keys = Object.keys(this._map[z]); | ||
var keys = Object.keys(this._map[lexical[z]]); | ||
for(var i = 0; i < keys.length; i++){ | ||
var key = keys[i]; | ||
var tmp = this._map[lexical[z]]; | ||
var tmp = this._map[z]; | ||
tmp = tmp && tmp[key]; | ||
@@ -639,3 +717,3 @@ | ||
delete this._map[lexical[z]][key]; | ||
delete this._map[z][key]; | ||
} | ||
@@ -663,8 +741,13 @@ } | ||
if((typeof query !== 'string') || !query){ | ||
if(query && (typeof query === 'object')){ | ||
return []; | ||
// re-assign properties | ||
callback = query['callback'] || /** @type {?Function} */ (limit); | ||
limit = query['limit']; | ||
query = query['query']; | ||
} | ||
else if(typeof limit === 'function'){ | ||
if(typeof limit === 'function'){ | ||
callback = limit; | ||
@@ -678,36 +761,2 @@ limit = 1000; | ||
var _query = query; | ||
// invalidate cache | ||
if(!this._status){ | ||
if(this.cache){ | ||
this._last_empty_query = ""; | ||
this._cache.reset(); | ||
} | ||
this._status = true; | ||
} | ||
// validate cache | ||
else if(this.cache){ | ||
var cache = this._cache.get(query); | ||
if(cache){ | ||
return cache; | ||
} | ||
} | ||
// validate last query | ||
else if(this._last_empty_query && (query.indexOf(this._last_empty_query) !== -1)){ | ||
return []; | ||
} | ||
if(this.worker){ | ||
@@ -719,3 +768,3 @@ | ||
for(var i = 0; i < this.threads; i++){ | ||
for(var i = 0; i < this.worker; i++){ | ||
@@ -748,16 +797,48 @@ this._worker[i].postMessage(i, { | ||
// remove trailing spaces | ||
if(!query || (typeof query !== 'string')){ | ||
var spaces = 0; | ||
return []; | ||
} | ||
while(query[spaces] === " "){ | ||
var _query = query; | ||
spaces++; | ||
// invalidate cache | ||
if(!this._status){ | ||
if(this.cache){ | ||
this._last_empty_query = ""; | ||
this._cache.reset(); | ||
} | ||
this._status = true; | ||
} | ||
if(spaces){ | ||
// validate cache | ||
_query = query.substring(spaces); | ||
else if(this.cache){ | ||
var cache = this._cache.get(query); | ||
if(cache){ | ||
return cache; | ||
} | ||
} | ||
// validate last query | ||
else if(this._last_empty_query && (query.indexOf(this._last_empty_query) !== -1)){ | ||
return []; | ||
} | ||
// encode string | ||
if(_query && this.encode){ | ||
_query = this.encode(_query); | ||
} | ||
if(!_query){ | ||
@@ -772,5 +853,7 @@ | ||
var length = words.length; | ||
// sort words by length | ||
if(words.length > 1){ | ||
if(length > 1){ | ||
@@ -787,32 +870,40 @@ words.sort(sort_by_length_down); | ||
for(var a = 0; a < words.length; a++){ | ||
for(var a = 0; a < length; a++){ | ||
var value = words[a]; | ||
if(check_words[value]){ | ||
if(value){ | ||
continue; | ||
} | ||
if(check_words[value]){ | ||
if(value && this.encode){ | ||
continue; | ||
} | ||
value = this.encode(value); | ||
} | ||
var map; | ||
var map_found = false; | ||
var map_check = []; | ||
if(value){ | ||
for(var z = 9; z >= 0; z--){ | ||
var map = this._map[value[0]]; | ||
map = map && map[value]; | ||
if((map = this._map[z][value])){ | ||
if(map && map.length){ | ||
if(map.length){ | ||
check[check.length] = map; | ||
map_check[map_check.length] = map; | ||
map_found = true; | ||
} | ||
} | ||
} | ||
else{ | ||
if(!map_found){ | ||
found = false; | ||
break; | ||
} | ||
else{ | ||
check_words[words[a]] = "1"; | ||
check[check.length] = [].concat.apply([], map_check); | ||
} | ||
check_words[value] = "1"; | ||
} | ||
@@ -835,3 +926,3 @@ } | ||
var length = check.length; | ||
length = check.length; | ||
@@ -881,3 +972,3 @@ while(tmp.length && (count < length)){ | ||
for(var i = 0; i < this.threads; i++) this._worker[i].postMessage(i, { | ||
for(var i = 0; i < this.worker; i++) this._worker[i].postMessage(i, { | ||
@@ -892,2 +983,4 @@ 'info': true, | ||
var keys; | ||
var length; | ||
var bytes = 0, | ||
@@ -897,15 +990,15 @@ words = 0, | ||
keys = Object.keys(this._map); | ||
for(var z = 0; z < 10; z++){ | ||
var length, current; | ||
keys = Object.keys(this._map[z]); | ||
for(var i = 0; i < keys.length; i++){ | ||
for(var i = 0; i < keys.length; i++){ | ||
current = '' + keys[i]; | ||
length = this._map[current].length; | ||
length = this._map[z][keys[i]].length; | ||
// Note: 1 char values allocates 1 byte "Map (OneByteInternalizedString)" | ||
bytes += length * 1 + current.length * 2; | ||
words += length; | ||
chars += length * current.length; | ||
// Note: 1 char values allocates 1 byte "Map (OneByteInternalizedString)" | ||
bytes += length * 1 + keys[i].length * 2 + 4; | ||
words += length; | ||
chars += keys[i].length * 2; | ||
} | ||
} | ||
@@ -931,3 +1024,3 @@ | ||
'cache': this._stack_keys.length, | ||
'matchers': custom_matchers.length | ||
'matchers': global_matcher.length | ||
}; | ||
@@ -979,3 +1072,3 @@ }; | ||
var encoder = { | ||
var global_encoder = { | ||
@@ -994,3 +1087,3 @@ // case insensitive search | ||
var regex_strip = regex('[^a-z0-9 ]'), | ||
regex_split = regex('[-/]'), | ||
regex_split = regex('[-\/]'), | ||
regex_a = regex('[àáâãäå]'), | ||
@@ -1006,2 +1099,3 @@ regex_e = regex('[èéêë]'), | ||
/** @const {Array} */ | ||
var regex_pairs = [ | ||
@@ -1054,2 +1148,3 @@ | ||
/** @const {Array} */ | ||
var regex_pairs = [ | ||
@@ -1084,3 +1179,3 @@ | ||
// perform simple encoding | ||
string = encoder['simple'](string); | ||
string = global_encoder['simple'](string); | ||
@@ -1096,3 +1191,3 @@ // normalize special pairs | ||
// remove white spaces | ||
string = string.replace(regex_space, ''); | ||
//string = string.replace(regex_space, ''); | ||
@@ -1121,4 +1216,6 @@ // delete all repeating chars | ||
/** @const {RegExp} */ | ||
var regex_vowel = regex('[aeiouy]'); | ||
/** @const {Array} */ | ||
var regex_pairs = [ | ||
@@ -1144,3 +1241,3 @@ | ||
// perform advanced encoding | ||
str = encoder['advanced'](str, /* skip post processing? */ true); | ||
str = global_encoder['advanced'](str, /* skip post processing? */ true); | ||
@@ -1273,4 +1370,12 @@ if(str.length > 1){ | ||
function addIndex(map, dupes, tmp, id){ | ||
/** | ||
* @param {Array} map | ||
* @param {Object} dupes | ||
* @param {string} tmp | ||
* @param {string|number} id | ||
* @param {string} content | ||
*/ | ||
function addIndex(map, dupes, tmp, id, content){ | ||
if(!dupes[tmp]){ | ||
@@ -1280,18 +1385,24 @@ | ||
var arr = map[tmp[0]] || ( | ||
var arr = map[calcScore(tmp, content)]; | ||
map[tmp[0]] = {} | ||
); | ||
arr = arr[tmp] || (arr[tmp] = []); | ||
arr[arr.length] = id; | ||
} | ||
} | ||
if(!arr[tmp]){ | ||
/** | ||
* @param {!string} part | ||
* @param {!string} ref | ||
* @returns {number} | ||
*/ | ||
arr[tmp] = arr = []; | ||
} | ||
else{ | ||
function calcScore(part, ref){ | ||
arr = arr[tmp]; | ||
} | ||
var context_index = ref.indexOf(part); | ||
var partial_index = context_index - ref.lastIndexOf(" ", context_index); | ||
arr[arr.length] = id; | ||
} | ||
return ( | ||
((3 / ref.length * (ref.length - context_index)) + (6 / partial_index) + 0.5) | 0 | ||
); | ||
} | ||
@@ -1316,12 +1427,12 @@ | ||
if(i > 0 && char === 'h'){ | ||
if((i > 0) && (char !== ' ') && (char === 'h')){ | ||
var char_prev_is_vowel = ( | ||
char_prev === 'a' || | ||
char_prev === 'e' || | ||
char_prev === 'i' || | ||
char_prev === 'o' || | ||
char_prev === 'u' || | ||
char_prev === 'y' | ||
(char_prev === 'a') || | ||
(char_prev === 'e') || | ||
(char_prev === 'i') || | ||
(char_prev === 'o') || | ||
(char_prev === 'u') || | ||
(char_prev === 'y') | ||
); | ||
@@ -1331,8 +1442,8 @@ | ||
char_next === 'a' || | ||
char_next === 'e' || | ||
char_next === 'i' || | ||
char_next === 'o' || | ||
char_next === 'u' || | ||
char_next === 'y' | ||
(char_next === 'a') || | ||
(char_next === 'e') || | ||
(char_next === 'i') || | ||
(char_next === 'o') || | ||
(char_next === 'u') || | ||
(char_next === 'y') | ||
); | ||
@@ -1353,3 +1464,3 @@ | ||
(i === string.length - 1) ? | ||
(i === (string.length - 1)) ? | ||
@@ -1356,0 +1467,0 @@ '' |
/* | ||
https://github.com/nextapps-de/flexsearch | ||
@version: 0.1.24 | ||
@version: 0.1.25 | ||
@license: Apache 2.0 Licence | ||
*/ | ||
'use strict';(function(n,q,e){var d;(d=e.define)&&d.amd?d([],function(){return q}):(d=e.modules)?d[n.toLowerCase()]=q:"undefined"!==typeof module?module.exports=q:e[n]=q})("FlexSearch",function z(n){function e(a){a||(a=l);this.id=a.id||A++;this.init(a);Object.defineProperty(this,"index",{get:function(){return this.a}});Object.defineProperty(this,"length",{get:function(){return Object.keys(this.a).length}})}function d(a){return new RegExp(a,"g")}function t(a,b,c){if("undefined"===typeof c){for(c=0;c< | ||
b.length;c+=2)a=a.replace(b[c],b[c+1]);return a}return a.replace(b,c)}function m(a,b,c,h){b[c]||(b[c]="1",a=a[c[0]]||(a[c[0]]={}),a[c]?a=a[c]:a[c]=a=[],a[a.length]=h)}function w(a){for(var b="",c="",h="",f=0;f<a.length;f++){var d=a[f];d!==c&&(0<f&&"h"===d?(h="a"===h||"e"===h||"i"===h||"o"===h||"u"===h||"y"===h,"a"!==c&&"e"!==c&&"i"!==c&&"o"!==c&&"u"!==c&&"y"!==c||!h||(b+=d)):b+=d);h=f===a.length-1?"":a[f+1];c=d}return b}function B(a,b){a=a.length-b.length;return 0>a?1:0<a?-1:0}function C(a,b){a=a.length- | ||
b.length;return 0>a?-1:0<a?1:0}function D(a,b,c){var h=a.length,f=b.length,d=[];if(h&&f)for(var g=0,k=0;k<h;k++)for(var e=a[k],l=0;l<f;l++)if(b[l]===e){d[g++]=e;if(c&&g===c)return d;break}return d}function u(a){a.u||(a.u=x(function(){a.u=null;var b=a.async;b&&(a.async=!1);if(a.c.length){for(var c=y(),h;(h=a.c.shift())||0===h;){var f=a.g[h];switch(f[0]){case p.add:a.add(f[1],f[2]);break;case p.update:a.update(f[1],f[2]);break;case p.remove:a.remove(f[1])}a.g[h]=null;delete a.g[h];if(100<y()-c)break}a.c.length&& | ||
u(a)}b&&(a.async=b)},1,"search-async-"+a.id))}function y(){return"undefined"!==typeof performance?performance.now():(new Date).getTime()}function E(a,b,c,h){a=n("flexsearch-"+a,function(){var a,b;self.a=function(c){if(c=c.data)b.debug&&console.log("Worker Job Started: "+c.id),c.search?self.postMessage({result:b.search(c.content,c.limit),id:a,content:c.content,limit:c.limit}):c.add?b.add(c.id,c.content):c.update?b.update(c.id,c.content):c.remove?b.remove(c.id):c.reset?b.reset():c.info?(c=b.info(), | ||
c.worker=a,b.debug&&console.log(c)):c.register&&(a=c.id,c.options.cache=!1,c.options.async=!0,c.options.worker=!1,b=(new Function(c.register.substring(c.register.indexOf("{")+1,c.register.lastIndexOf("}"))))(c.options))}},function(a){(a=a.data)&&a.result?h(a.id,a.content,a.result,a.limit):c.debug&&console.log(a)},b);var f=z.toString();c.id=b;a.postMessage(b,{register:f,options:c,id:b});return a}var l={type:"integer",mode:"forward",boolean:!1,cache:!1,async:!1,worker:!1,encode:!1,threads:4,debug:!0}, | ||
r=[],A=0,p={add:0,update:1,remove:2};e.create=function(a){return e.new(a)};e.new=function(a){return new this(a)};e.addMatcher=function(a){for(var b in a)a.hasOwnProperty(b)&&(r[r.length]=[d(b),a[b]])};e.prototype.init=function(a){if(a){if(a.worker)if("undefined"===typeof Worker)a.worker=!1,this.i=null;else{var b=this,c=a.threads||l.threads;b.m=-1;b.l=0;b.h=[];b.s=null;b.i=Array(c);for(var h=0;h<c;h++)b.i[h]=E(b.id,h,a||l,function(a,c,h,d){b.l!==b.threads&&(b.h=b.h.concat(h),b.l++,d&&b.h.length>=d&& | ||
(b.l=b.threads),b.s&&b.l===b.threads&&(b.h.length?b.f="":b.f||(b.f=c),b.cache&&b.j.set(c,b.h),b.s(b.h),b.h=[]))})}this.mode=a.mode||this.mode||l.mode;this.boolean="or"===a["boolean"]||this.boolean||l.boolean;this.cache=a.cache||this.cache||l.cache;this.async=a.async||this.async||l.async;this.worker=a.worker||this.worker||l.worker;this.threads=a.threads||this.threads||l.threads;this.encoder=a.encode&&v[a.encode]||this.encoder||l.encode&&v[l.encode]||a.encode;this.debug=a.debug||this.debug||l.debug}this.b= | ||
{};this.a={};this.g={};this.c=[];this.u=null;this.f="";this.o=!0;this.j=this.cache?new F(3E4,50,!0):!1};e.prototype.encode=function(a){this.encoder&&(a=this.encoder(a));if(r.length)for(var b=0;b<r.length;b++){var c=r[b];a=a.replace(c[0],c[1])}return a};e.prototype.add=function(a,b){if("string"===typeof b&&b&&(a||0===a))if(this.a[a])this.update(a,b);else if(this.worker)++this.m>=this.i.length&&(this.m=0),this.i[this.m].postMessage(this.m,{add:!0,id:a,content:b}),this.a[a]=""+this.m;else if(this.async)this.g[a]|| | ||
(this.c[this.c.length]=a),this.g[a]=[p.add,a,b],u(this);else{var c={};b=b.split(" ");for(var h=0;h<b.length;h++){var d=b[h];if(d&&(this.encode&&(d=this.encode(d)),d))switch(this.mode){case "inverse":case "both":for(var e="",g=d.length-1;1<=g;g--)e=d[g]+e,m(this.b,c,e,a);case "forward":e="";for(g=0;g<d.length;g++)e+=d[g],m(this.b,c,e,a);break;case "full":for(g=0;g<d.length;g++)for(var k=d.length;k>g;k--)e=d.substring(g,k),m(this.b,c,e,a);break;default:m(this.b,c,d,a)}}this.a[a]="1";this.o=!1}};e.prototype.update= | ||
function(a,b){if("string"===typeof b&&(a||0===a)&&this.a[a])if(this.worker){var c=parseInt(this.a[a],10);this.i[c].postMessage(c,{update:!0,id:a,content:b})}else this.async?(this.g[a]||(this.c[this.c.length]=a),this.g[a]=[p.update,a,b],u(this)):(this.remove(a),b&&this.add(a,b))};e.prototype.remove=function(a){if(this.a[a])if(this.worker){var b=parseInt(this.a[a],10);this.i[b].postMessage(b,{remove:!0,id:a});delete this.a[a]}else if(this.async)this.g[a]||(this.c[this.c.length]=a),this.g[a]=[p.remove, | ||
a],u(this);else{b=Object.keys(this.b);for(var c=0;c<b.length;c++)for(var d=Object.keys(this.b[b[c]]),f=0;f<d.length;f++){var e=d[f],g=this.b[b[c]];if((g=g&&g[e])&&g.length)for(var k=0;k<g.length;k++)if(g[k]===a){g.splice(k,1);break}g.length||delete this.b[b[c]][e]}delete this.a[a];this.o=!1}};var G=d("[ -/]");e.prototype.search=function(a,b,c){if("string"===typeof a&&a)"function"===typeof b?(c=b,b=1E3):b||(b=1E3);else return[];var d=a;if(!this.o)this.cache&&(this.f="",this.j.reset()),this.o=!0;else if(this.cache){var f= | ||
this.j.get(a);if(f)return f}else if(this.f&&-1!==a.indexOf(this.f))return[];if(this.worker){this.s=c;this.l=0;this.h=[];for(d=0;d<this.threads;d++)this.i[d].postMessage(d,{search:!0,limit:b,content:a});return null}if(c){var e=this;x(function(){c(e.search(a,b));e=null},1,"search-"+this.id);return null}for(f=0;" "===a[f];)f++;f&&(d=a.substring(f));if(!d)return[];var g=d.split(G);1<g.length&&g.sort(B);f=[];var k=!0;d=[];for(var l={},n=0;n<g.length;n++){var m=g[n];if(!l[m]&&(m&&this.encode&&(m=this.encode(m)), | ||
m)){var p=this.b[m[0]];if((p=p&&p[m])&&p.length)d[d.length]=p;else{k=!1;break}l[g[n]]="1"}}if(k&&(1<d.length&&d.sort(C),g=0,k=d[g++])){for(f=d.length;k.length&&g<f;)l=d[g++],k=D(k,l,g===f?b:0);b&&k.length>b&&(k=k.slice(0,b));f=k}f.length?this.f="":this.f||(this.f=a);this.cache&&this.j.set(a,f);return f};e.prototype.info=function(){if(this.worker)for(var a=0;a<this.threads;a++)this.i[a].postMessage(a,{info:!0,id:this.id});else{var b=0,c=0,d=0;var f=Object.keys(this.b);for(a=0;a<f.length;a++){var e= | ||
f[a];var g=this.b[e].length;b+=g+2*e.length;c+=g;d+=g*e.length}f=Object.keys(this.a);g=f.length;for(a=0;a<g;a++)b+=2*f[a].length+2;return{id:this.id,memory:b,items:g,sequences:c,chars:d,status:this.o,cache:this.c.length,matchers:r.length}}};e.prototype.reset=function(){this.destroy();this.init()};e.prototype.destroy=function(){this.cache&&this.j.reset();this.j=this.a=this.b=null};var v={icase:function(a){return a.toLowerCase()},simple:function(){var a=[d("[\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5]"), | ||
"a",d("[\u00e8\u00e9\u00ea\u00eb]"),"e",d("[\u00ec\u00ed\u00ee\u00ef]"),"i",d("[\u00f2\u00f3\u00f4\u00f5\u00f6\u0151]"),"o",d("[\u00f9\u00fa\u00fb\u00fc\u0171]"),"u",d("[\u00fd\u0177\u00ff]"),"y",d("\u00f1"),"n",d("\u00e7"),"c",d("\u00df"),"s",d("[-/]")," ",d("[^a-z0-9 ]"),""];return function(b){return t(b.toLowerCase(),a)}}(),advanced:function(){var a=d(" "),b=[d("ae"),"a",d("ai"),"ei",d("ay"),"ei",d("ey"),"ei",d("oe"),"o",d("ue"),"u",d("ie"),"i",d("sz"),"s",d("zs"),"s",d("sh"),"s",d("ck"),"k",d("cc"), | ||
"k",d("dt"),"t",d("ph"),"f",d("ou"),"o",d("uo"),"u"];return function(c,d){if(!c)return c;c=v.simple(c);2<c.length&&(c=t(c,b));d||(c=c.replace(a,""),1<c.length&&(c=w(c)));return c}}(),extra:function(){var a=[d("p"),"b",d("[sz]"),"c",d("[gq]"),"k",d("[jy]"),"i",d("n"),"m",d("d"),"t",d("[vw]"),"f",d("[aeiouy]"),""];return function(b){if(!b)return b;b=v.advanced(b,!0);if(1<b.length){b=b.split(" ");for(var c=0;c<b.length;c++){var d=b[c];1<d.length&&(b[c]=d[0]+t(d.substring(1),a))}b=b.join("");b=w(b)}return b}}()}, | ||
x=function(){var a={};return function(b,c,d){var e=a[d];e&&clearTimeout(e);return a[d]=setTimeout(b,c)}}(),F=function(){function a(){this.cache={}}a.prototype.reset=function(){this.cache={}};a.prototype.set=function(a,c){this.cache[a]=c};a.prototype.get=function(a){return this.cache[a]};return a}();return e}(function(){var n={},q=!("undefined"===typeof Blob||"undefined"===typeof URL||!URL.createObjectURL);return function(e,d,t,m){d=q?URL.createObjectURL(new Blob(["("+d.toString()+")()"],{type:"text/javascript"})): | ||
"js/worker/"+e+".js";n[e]||(n[e]=[]);n[e][m]=new Worker(d);n[e][m].onmessage=t;console.log("Register Worker@"+e);return{postMessage:function(d,m){n[e][d].postMessage(m)}}}}()),this); | ||
'use strict';(function(l,v,d){var c;(c=d.define)&&c.amd?c([],function(){return v}):(c=d.modules)?c[l.toLowerCase()]=v:"undefined"!==typeof module?module.exports=v:d[l]=v})("FlexSearch",function B(l){function d(a){a||(a=n);this.name="FlexSearch";this.id=a.id||C++;this.init(a);Object.defineProperty(this,"index",{get:function(){return this.a}});Object.defineProperty(this,"length",{get:function(){return Object.keys(this.a).length}})}function c(a){return new RegExp(a,"g")}function p(a,b,f){if("undefined"=== | ||
typeof f){for(f=0;f<b.length;f+=2)a=a.replace(b[f],b[f+1]);return a}return a.replace(b,f)}function m(a,b,f,e,c){b[f]||(b[f]="1",b=c.indexOf(f),a=a[3/c.length*(c.length-b)+6/(b-c.lastIndexOf(" ",b))+.5|0],a=a[f]||(a[f]=[]),a[a.length]=e)}function x(a){for(var b="",f="",e="",c=0;c<a.length;c++){var h=a[c];h!==f&&(0<c&&" "!==h&&"h"===h?(e="a"===e||"e"===e||"i"===e||"o"===e||"u"===e||"y"===e,"a"!==f&&"e"!==f&&"i"!==f&&"o"!==f&&"u"!==f&&"y"!==f||!e||(b+=h)):b+=h);e=c===a.length-1?"":a[c+1];f=h}return b} | ||
function D(a,b){a=a.length-b.length;return 0>a?1:0<a?-1:0}function E(a,b){a=a.length-b.length;return 0>a?-1:0<a?1:0}function F(a,b,f){var e=a.length,c=b.length,h=[];if(e&&c)for(var g=0,k=0;k<e;k++)for(var d=a[k],l=0;l<c;l++)if(b[l]===d){h[g++]=d;if(f&&g===f)return h;break}return h}function w(a){a.v||(a.v=y(function(){a.v=null;var b=a.async;b&&(a.async=!1);if(a.c.length){for(var f=z(),c;(c=a.c.shift())||0===c;){var d=a.g[c];switch(d[0]){case q.add:a.add(d[1],d[2]);break;case q.update:a.update(d[1], | ||
d[2]);break;case q.remove:a.remove(d[1])}a.g[c]=null;delete a.g[c];if(100<z()-f)break}a.c.length&&w(a)}b&&(a.async=b)},1,"search-async-"+a.id))}function z(){return"undefined"!==typeof performance?performance.now():(new Date).getTime()}function G(a,b,c,e){a=l("flexsearch-"+a,function(){var a,b;self.a=function(c){if(c=c.data)b.debug&&console.log("Worker Job Started: "+c.id),c.search?self.postMessage({result:b.search(c.content,c.limit),id:a,content:c.content,limit:c.limit}):c.add?b.add(c.id,c.content): | ||
c.update?b.update(c.id,c.content):c.remove?b.remove(c.id):c.reset?b.reset():c.info?(c=b.info(),c.worker=a,b.debug&&console.log(c)):c.register&&(a=c.id,c.options.cache=!1,c.options.async=!0,c.options.worker=!1,b=(new Function(c.register.substring(c.register.indexOf("{")+1,c.register.lastIndexOf("}"))))(c.options))}},function(a){(a=a.data)&&a.result?e(a.id,a.content,a.result,a.limit):c.debug&&console.log(a)},b);var f=B.toString();c.id=b;a.postMessage(b,{register:f,options:c,id:b});return a}var n={type:"integer", | ||
mode:"forward",boolean:!1,cache:!1,async:!1,worker:!1,encode:!1,debug:!0},r=[],C=0,q={add:0,update:1,remove:2};d.new=function(a){return new this(a)};d.create=function(a){return d.new(a)};d.addMatcher=function(a){for(var b in a)a.hasOwnProperty(b)&&(r[r.length]=c(b),r[r.length]=a[b])};d.register=function(a,b){t[a]=b};d.encode=function(a,b){return t[a](b)};d.prototype.init=function(a){this.l=[];if(a){if(a.worker)if("undefined"===typeof Worker)a.worker=!1,this.i=null;else{var b=this,c=a.worker||4;b.o= | ||
-1;b.m=0;b.h=[];b.u=null;b.i=Array(c);for(var e=0;e<c;e++)b.i[e]=G(b.id,e,a||n,function(a,c,f,e){b.m!==b.worker&&(b.h=b.h.concat(f),b.m++,e&&b.h.length>=e&&(b.m=b.worker),b.u&&b.m===b.worker&&(b.h.length?b.f="":b.f||(b.f=c),b.cache&&b.j.set(c,b.h),b.u(b.h),b.h=[]))})}this.mode=a.mode||this.mode||n.mode;this.boolean="or"===a["boolean"]||this.boolean||n.boolean;this.cache=a.cache||this.cache||n.cache;this.async=a.async||this.async||n.async;this.worker=a.worker||this.worker||n.worker;this.encoder=a.encode&& | ||
t[a.encode]||this.encoder||n.encode&&t[n.encode]||a.encode;this.debug=a.debug||this.debug||n.debug;a.matcher&&this.addMatcher(a.matcher)}this.b=[{},{},{},{},{},{},{},{},{},{}];this.a={};this.g={};this.c=[];this.v=null;this.f="";this.s=!0;this.j=this.cache?new H(3E4,50,!0):!1};d.prototype.encode=function(a){this.encoder&&(a=this.encoder(a));r.length&&(a=p(a,r));this.l.length&&(a=p(a,this.l));return a};d.prototype.addMatcher=function(a){for(var b in a)a.hasOwnProperty(b)&&(this.l[this.l.length]=c(b), | ||
this.l[this.l.length]=a[b])};d.prototype.add=function(a,b){if("string"===typeof b&&b&&(a||0===a))if(this.a[a])this.update(a,b);else if(this.worker)++this.o>=this.i.length&&(this.o=0),this.i[this.o].postMessage(this.o,{add:!0,id:a,content:b}),this.a[a]=""+this.o;else if(this.async)this.g[a]||(this.c[this.c.length]=a),this.g[a]=[q.add,a,b],w(this);else if(b&&this.encode&&(b=this.encode(b)),b){for(var c={},e=b.split(A),d=0;d<e.length;d++){var h=e[d];if(h)switch(this.mode){case "inverse":case "both":for(var g= | ||
"",k=h.length-1;1<=k;k--)g=h[k]+g,m(this.b,c,g,a,b);case "forward":g="";for(k=0;k<h.length;k++)g+=h[k],m(this.b,c,g,a,b);break;case "full":for(k=0;k<h.length;k++)for(var l=h.length;l>k;l--)g=h.substring(k,l),m(this.b,c,g,a,b);break;default:m(this.b,c,h,a,b)}}this.a[a]="1";this.s=!1}};d.prototype.update=function(a,b){if("string"===typeof b&&(a||0===a)&&this.a[a])if(this.worker){var c=parseInt(this.a[a],10);this.i[c].postMessage(c,{update:!0,id:a,content:b})}else this.async?(this.g[a]||(this.c[this.c.length]= | ||
a),this.g[a]=[q.update,a,b],w(this)):(this.remove(a),b&&this.add(a,b))};d.prototype.remove=function(a){if(this.a[a])if(this.worker){var b=parseInt(this.a[a],10);this.i[b].postMessage(b,{remove:!0,id:a});delete this.a[a]}else if(this.async)this.g[a]||(this.c[this.c.length]=a),this.g[a]=[q.remove,a],w(this);else{for(b=0;10>b;b++)for(var c=Object.keys(this.b[b]),e=0;e<c.length;e++){var d=c[e],h=this.b[b];if((h=h&&h[d])&&h.length)for(var g=0;g<h.length;g++)if(h[g]===a){h.splice(g,1);break}h.length||delete this.b[b][d]}delete this.a[a]; | ||
this.s=!1}};var A=c("[ -/]");d.prototype.search=function(a,b,c){a&&"object"===typeof a&&(c=a.callback||b,b=a.limit,a=a.query);"function"===typeof b?(c=b,b=1E3):b||(b=1E3);if(this.worker){this.u=c;this.m=0;this.h=[];for(var e=0;e<this.worker;e++)this.i[e].postMessage(e,{search:!0,limit:b,content:a});return null}if(c){var f=this;y(function(){c(f.search(a,b));f=null},1,"search-"+this.id);return null}if(!a||"string"!==typeof a)return[];e=a;if(!this.s)this.cache&&(this.f="",this.j.reset()),this.s=!0;else if(this.cache){var d= | ||
this.j.get(a);if(d)return d}else if(this.f&&-1!==a.indexOf(this.f))return[];e&&this.encode&&(e=this.encode(e));if(!e)return[];var g=e.split(A);e=g.length;1<e&&g.sort(D);var k=[],l=!0;d=[];for(var n={},p=0;p<e;p++){var m=g[p];if(m&&!n[m]){for(var u,r=!1,q=[],t=9;0<=t;t--)(u=this.b[t][m])&&u.length&&(q[q.length]=u,r=!0);if(r)d[d.length]=[].concat.apply([],q);else{l=!1;break}n[m]="1"}}if(l&&(1<d.length&&d.sort(E),u=0,g=d[u++])){for(e=d.length;g.length&&u<e;)k=d[u++],g=F(g,k,u===e?b:0);b&&g.length>b&& | ||
(g=g.slice(0,b));k=g}k.length?this.f="":this.f||(this.f=a);this.cache&&this.j.set(a,k);return k};d.prototype.info=function(){if(this.worker)for(var a=0;a<this.worker;a++)this.i[a].postMessage(a,{info:!0,id:this.id});else{for(var b,c,e=0,d=0,h=0,g=0;10>g;g++)for(b=Object.keys(this.b[g]),a=0;a<b.length;a++)c=this.b[g][b[a]].length,e+=c+2*b[a].length+4,d+=c,h+=2*b[a].length;b=Object.keys(this.a);c=b.length;for(a=0;a<c;a++)e+=2*b[a].length+2;return{id:this.id,memory:e,items:c,sequences:d,chars:h,status:this.s, | ||
cache:this.c.length,matchers:r.length}}};d.prototype.reset=function(){this.destroy();this.init()};d.prototype.destroy=function(){this.cache&&this.j.reset();this.j=this.a=this.b=null};var t={icase:function(a){return a.toLowerCase()},simple:function(){var a=[c("[\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5]"),"a",c("[\u00e8\u00e9\u00ea\u00eb]"),"e",c("[\u00ec\u00ed\u00ee\u00ef]"),"i",c("[\u00f2\u00f3\u00f4\u00f5\u00f6\u0151]"),"o",c("[\u00f9\u00fa\u00fb\u00fc\u0171]"),"u",c("[\u00fd\u0177\u00ff]"),"y",c("\u00f1"), | ||
"n",c("\u00e7"),"c",c("\u00df"),"s",c("[-/]")," ",c("[^a-z0-9 ]"),""];return function(b){return p(b.toLowerCase(),a)}}(),advanced:function(){var a=[c("ae"),"a",c("ai"),"ei",c("ay"),"ei",c("ey"),"ei",c("oe"),"o",c("ue"),"u",c("ie"),"i",c("sz"),"s",c("zs"),"s",c("sh"),"s",c("ck"),"k",c("cc"),"k",c("dt"),"t",c("ph"),"f",c("ou"),"o",c("uo"),"u"];return function(b,c){if(!b)return b;b=t.simple(b);2<b.length&&(b=p(b,a));c||1<b.length&&(b=x(b));return b}}(),extra:function(){var a=[c("p"),"b",c("[sz]"),"c", | ||
c("[gq]"),"k",c("[jy]"),"i",c("n"),"m",c("d"),"t",c("[vw]"),"f",c("[aeiouy]"),""];return function(b){if(!b)return b;b=t.advanced(b,!0);if(1<b.length){b=b.split(" ");for(var c=0;c<b.length;c++){var d=b[c];1<d.length&&(b[c]=d[0]+p(d.substring(1),a))}b=b.join("");b=x(b)}return b}}()},y=function(){var a={};return function(b,c,d){var e=a[d];e&&clearTimeout(e);return a[d]=setTimeout(b,c)}}(),H=function(){function a(){this.cache={}}a.prototype.reset=function(){this.cache={}};a.prototype.set=function(a,c){this.cache[a]= | ||
c};a.prototype.get=function(a){return this.cache[a]};return a}();return d}(function(){var l={},v=!("undefined"===typeof Blob||"undefined"===typeof URL||!URL.createObjectURL);return function(d,c,p,m){c=v?URL.createObjectURL(new Blob(["("+c.toString()+")()"],{type:"text/javascript"})):"js/worker/"+d+".js";l[d]||(l[d]=[]);l[d][m]=new Worker(c);l[d][m].onmessage=p;console.log("Register Worker@"+d);return{postMessage:function(c,m){l[d][c].postMessage(m)}}}}()),this); |
{ | ||
"name": "flexsearch", | ||
"version": "0.1.24", | ||
"version": "0.1.25", | ||
"description": "Superfast, lightweight and memory efficient full text search library.", | ||
@@ -24,3 +24,3 @@ "keywords": [], | ||
"update": "node_modules/.bin/updtr --to non-breaking", | ||
"coverage": "nyc report --reporter=text-lcov | coveralls" | ||
"coverage": "nyc report --reporter=lcov --reporter=text-lcov | coveralls" | ||
}, | ||
@@ -40,8 +40,9 @@ "files": [ | ||
"google-closure-compiler": "^20180204.0.0", | ||
"phantomjs-prebuilt": "^2.1.16", | ||
"mocha": "^5.0.4", | ||
"mocha-lcov-reporter": "^1.3.0", | ||
"mocha-phantomjs": "^4.1.0", | ||
"nyc": "^11.5.0", | ||
"phantomjs-prebuilt": "^2.1.16", | ||
"updtr": "^2.0.0" | ||
} | ||
} |
@@ -16,3 +16,3 @@ <p align="center"> | ||
When it comes to raw search speed __FlexSearch outperforms every single searching library out there__ and also provides flexible search capabilities like multi-word, phonetic transformations or partial matching. It also has the __most possible memory-efficient index__. Keep in mind that updating items from the index has a significant cost. When your index needs to be updated continuously then <a href="https://github.com/nextapps-de/bulksearch" target="_blank">BulkSearch</a> may be a better choice. FlexSearch also provides you a non-blocking asynchronous processing model as well as web workers to perform any updates on the index and queries in background. | ||
When it comes to raw search speed __FlexSearch outperforms every single searching library out there__ and also provides flexible search capabilities like multi-word matching, phonetic transformations or partial matching. It also has the __most memory-efficient index__. Keep in mind that updating items from the index has a significant cost. When your index needs to be updated continuously then <a href="/bulksearch" target="_blank">BulkSearch</a> may be a better choice. FlexSearch also provides you a non-blocking asynchronous processing model as well as web workers to perform any updates on the index as well as queries through dedicated threads. | ||
@@ -40,2 +40,3 @@ Benchmark: | ||
<li><a href="#phonetic">Phonetic Search</a></li> | ||
<li>Sorted by Scoring</li> | ||
<li>Limit Results</li> | ||
@@ -42,0 +43,0 @@ <li>Caching</li> |
@@ -261,2 +261,29 @@ if(typeof module !== 'undefined'){ | ||
// ------------------------------------------------------------------------ | ||
// Scoring | ||
// ------------------------------------------------------------------------ | ||
describe('Apply Sort by Scoring', function(){ | ||
it('Should have been sorted properly by scoring', function(){ | ||
flexsearch_sync.add(0, "foo bar foobar"); | ||
flexsearch_sync.add(2, "bar foo foobar"); | ||
flexsearch_sync.add(1, "foobar foo bar"); | ||
expect(flexsearch_sync.length).to.equal(3); | ||
expect(flexsearch_sync.search("foo")[0]).to.equal(0); | ||
expect(flexsearch_sync.search("foo")[1]).to.equal(1); | ||
expect(flexsearch_sync.search("foo")[2]).to.equal(2); | ||
expect(flexsearch_sync.search("bar")[0]).to.equal(2); | ||
expect(flexsearch_sync.search("bar")[1]).to.equal(0); // partial scoring! | ||
expect(flexsearch_sync.search("bar")[2]).to.equal(1); | ||
expect(flexsearch_sync.search("foobar")[0]).to.equal(1); | ||
expect(flexsearch_sync.search("foobar")[1]).to.equal(0); | ||
expect(flexsearch_sync.search("foobar")[2]).to.equal(2); | ||
}); | ||
}); | ||
// ------------------------------------------------------------------------ | ||
// Async Tests | ||
@@ -263,0 +290,0 @@ // ------------------------------------------------------------------------ |
Sorry, the diff of this file is not supported yet
104736
1740
685
9