@akryum/flexsearch-es
Advanced tools
Comparing version 0.7.31 to 0.7.32
@@ -23,3 +23,8 @@ var FlexSearch = (() => { | ||
__export(src_exports, { | ||
default: () => src_default | ||
Document: () => document_default, | ||
Worker: () => worker_default, | ||
create: () => create2, | ||
default: () => src_default, | ||
registerCharset: () => registerCharset, | ||
registerLanguage: () => registerLanguage | ||
}); | ||
@@ -29,5 +34,8 @@ | ||
var DEBUG = false; | ||
var SUPPORT_WORKER = true; | ||
var SUPPORT_ENCODER = true; | ||
var SUPPORT_CACHE = true; | ||
var SUPPORT_ASYNC = true; | ||
var SUPPORT_STORE = true; | ||
var SUPPORT_TAGS = true; | ||
var SUPPORT_SUGGESTION = true; | ||
@@ -194,2 +202,8 @@ var SUPPORT_SERIALIZE = true; | ||
var global_charset = {}; | ||
function registerCharset(name, charset) { | ||
global_charset[name] = charset; | ||
} | ||
function registerLanguage(name, lang) { | ||
global_lang[name] = lang; | ||
} | ||
@@ -206,3 +220,3 @@ // src/async.js | ||
prototype[key + "Async"] = function() { | ||
const self = this; | ||
const self2 = this; | ||
const args = ( | ||
@@ -220,5 +234,5 @@ /*[].slice.call*/ | ||
setTimeout(function() { | ||
self.async = true; | ||
const res = self[key].apply(self, args); | ||
self.async = false; | ||
self2.async = true; | ||
const res = self2[key].apply(self2, args); | ||
self2.async = false; | ||
resolve(res); | ||
@@ -317,2 +331,23 @@ }); | ||
} | ||
function intersect_union(mandatory, arrays) { | ||
const check = create_object(); | ||
const union = create_object(); | ||
const result = []; | ||
for (let x = 0; x < mandatory.length; x++) { | ||
check[mandatory[x]] = 1; | ||
} | ||
for (let x = 0, arr; x < arrays.length; x++) { | ||
arr = arrays[x]; | ||
for (let y = 0, id; y < arr.length; y++) { | ||
id = arr[y]; | ||
if (check[id]) { | ||
if (!union[id]) { | ||
union[id] = 1; | ||
result[result.length] = id; | ||
} | ||
} | ||
} | ||
} | ||
return result; | ||
} | ||
@@ -455,3 +490,3 @@ // src/cache.js | ||
// src/serialize.js | ||
function async(callback, self, field, key, index_doc, index, data) { | ||
function async(callback, self2, field, key, index_doc, index, data) { | ||
setTimeout(function() { | ||
@@ -461,10 +496,10 @@ const res = callback(field ? field + "." + key : key, JSON.stringify(data)); | ||
res["then"](function() { | ||
self.export(callback, self, field, index_doc, index + 1); | ||
self2.export(callback, self2, field, index_doc, index + 1); | ||
}); | ||
} else { | ||
self.export(callback, self, field, index_doc, index + 1); | ||
self2.export(callback, self2, field, index_doc, index + 1); | ||
} | ||
}); | ||
} | ||
function exportIndex(callback, self, field, index_doc, index) { | ||
function exportIndex(callback, self2, field, index_doc, index) { | ||
let key, data; | ||
@@ -501,3 +536,3 @@ switch (index || (index = 0)) { | ||
} | ||
async(callback, self || this, field, key, index_doc, index, data); | ||
async(callback, self2 || this, field, key, index_doc, index, data); | ||
return true; | ||
@@ -528,4 +563,622 @@ } | ||
} | ||
function exportDocument(callback, self2, field, index_doc, index) { | ||
index || (index = 0); | ||
index_doc || (index_doc = 0); | ||
if (index_doc < this.field.length) { | ||
const field2 = this.field[index_doc]; | ||
const idx = this.index[field2]; | ||
self2 = this; | ||
setTimeout(function() { | ||
if (!idx.export(callback, self2, index ? field2 : "", index_doc, index++)) { | ||
index_doc++; | ||
index = 1; | ||
self2.export(callback, self2, field2, index_doc, index); | ||
} | ||
}); | ||
} else { | ||
let key, data; | ||
switch (index) { | ||
case 1: | ||
key = "tag"; | ||
data = this.tagindex; | ||
break; | ||
case 2: | ||
key = "store"; | ||
data = this.store; | ||
break; | ||
default: | ||
return; | ||
} | ||
async(callback, this, field, key, index_doc, index, data); | ||
} | ||
} | ||
function importDocument(key, data) { | ||
if (!data) { | ||
return; | ||
} | ||
if (is_string(data)) { | ||
data = JSON.parse(data); | ||
} | ||
switch (key) { | ||
case "tag": | ||
this.tagindex = data; | ||
break; | ||
case "reg": | ||
this.fastupdate = false; | ||
this.register = data; | ||
for (let i = 0, index; i < this.field.length; i++) { | ||
index = this.index[this.field[i]]; | ||
index.register = data; | ||
index.fastupdate = false; | ||
} | ||
break; | ||
case "store": | ||
this.store = data; | ||
break; | ||
default: | ||
key = key.split("."); | ||
const field = key[0]; | ||
key = key[1]; | ||
if (field && key) { | ||
this.index[field].import(key, data); | ||
} | ||
} | ||
} | ||
// src/worker/handler.js | ||
function handler_default(data) { | ||
data = data["data"]; | ||
const index = self["_index"]; | ||
const args = data["args"]; | ||
const task = data["task"]; | ||
switch (task) { | ||
case "init": | ||
const options = data["options"] || {}; | ||
const factory2 = data["factory"]; | ||
const encode2 = options["encode"]; | ||
options["cache"] = false; | ||
if (encode2 && encode2.indexOf("function") === 0) { | ||
options["encode"] = Function("return " + encode2)(); | ||
} | ||
if (factory2) { | ||
Function("return " + factory2)()(self); | ||
self["_index"] = new self["FlexSearch"]["Index"](options); | ||
delete self["FlexSearch"]; | ||
} else { | ||
self["_index"] = new src_default(options); | ||
} | ||
break; | ||
default: | ||
const id = data["id"]; | ||
const message = index[task].apply(index, args); | ||
postMessage(task === "search" ? { "id": id, "msg": message } : { "id": id }); | ||
} | ||
} | ||
// src/worker/index.js | ||
var pid = 0; | ||
function WorkerIndex(options) { | ||
if (!(this instanceof WorkerIndex)) { | ||
return new WorkerIndex(options); | ||
} | ||
let opt; | ||
if (options) { | ||
if (is_function(opt = options["encode"])) { | ||
options["encode"] = opt.toString(); | ||
} | ||
} else { | ||
options = {}; | ||
} | ||
let factory2 = (self || window)["_factory"]; | ||
if (factory2) { | ||
factory2 = factory2.toString(); | ||
} | ||
const is_node_js2 = typeof window === "undefined" && self["exports"]; | ||
const _self = this; | ||
this.worker = create(factory2, is_node_js2, options["worker"]); | ||
this.resolver = create_object(); | ||
if (!this.worker) { | ||
return; | ||
} | ||
if (is_node_js2) { | ||
this.worker["on"]("message", function(msg) { | ||
_self.resolver[msg["id"]](msg["msg"]); | ||
delete _self.resolver[msg["id"]]; | ||
}); | ||
} else { | ||
this.worker.onmessage = function(msg) { | ||
msg = msg["data"]; | ||
_self.resolver[msg["id"]](msg["msg"]); | ||
delete _self.resolver[msg["id"]]; | ||
}; | ||
} | ||
this.worker.postMessage({ | ||
"task": "init", | ||
"factory": factory2, | ||
"options": options | ||
}); | ||
} | ||
var worker_default = WorkerIndex; | ||
register2("add"); | ||
register2("append"); | ||
register2("search"); | ||
register2("update"); | ||
register2("remove"); | ||
function register2(key) { | ||
WorkerIndex.prototype[key] = WorkerIndex.prototype[key + "Async"] = function() { | ||
const self2 = 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) { | ||
setTimeout(function() { | ||
self2.resolver[++pid] = resolve; | ||
self2.worker.postMessage({ | ||
"task": key, | ||
"id": pid, | ||
"args": args | ||
}); | ||
}); | ||
}); | ||
if (callback) { | ||
promise.then(callback); | ||
return this; | ||
} else { | ||
return promise; | ||
} | ||
}; | ||
} | ||
function create(factory, is_node_js, worker_path) { | ||
let worker; | ||
try { | ||
worker = is_node_js ? eval('new (require("worker_threads")["Worker"])("../dist/node/node.js")') : factory ? new Worker(URL.createObjectURL( | ||
new Blob([ | ||
"onmessage=" + handler_default.toString() | ||
], { "type": "text/javascript" }) | ||
)) : new Worker(is_string(worker_path) ? worker_path : "worker/worker.js", { type: "module" }); | ||
} catch (e) { | ||
} | ||
return worker; | ||
} | ||
// src/document.js | ||
function Document(options) { | ||
if (!(this instanceof Document)) { | ||
return new Document(options); | ||
} | ||
const document = options["document"] || options["doc"] || options; | ||
let opt; | ||
this.tree = []; | ||
this.field = []; | ||
this.marker = []; | ||
this.register = create_object(); | ||
this.key = (opt = document["key"] || document["id"]) && parse_tree(opt, this.marker) || "id"; | ||
this.fastupdate = parse_option(options["fastupdate"], true); | ||
if (SUPPORT_STORE) { | ||
this.storetree = (opt = document["store"]) && opt !== true && []; | ||
this.store = opt && create_object(); | ||
} | ||
if (SUPPORT_TAGS) { | ||
this.tag = (opt = document["tag"]) && parse_tree(opt, this.marker); | ||
this.tagindex = opt && create_object(); | ||
} | ||
if (SUPPORT_CACHE) { | ||
this.cache = (opt = options["cache"]) && new cache_default(opt); | ||
options["cache"] = false; | ||
} | ||
if (SUPPORT_WORKER) { | ||
this.worker = options["worker"]; | ||
} | ||
if (SUPPORT_ASYNC) { | ||
this.async = false; | ||
} | ||
this.index = parse_descriptor.call(this, options, document); | ||
} | ||
var document_default = Document; | ||
function parse_descriptor(options, document) { | ||
const index = create_object(); | ||
let field = document["index"] || document["field"] || document; | ||
if (is_string(field)) { | ||
field = [field]; | ||
} | ||
for (let i = 0, key, opt; i < field.length; i++) { | ||
key = field[i]; | ||
if (!is_string(key)) { | ||
opt = key; | ||
key = key["field"]; | ||
} | ||
opt = is_object(opt) ? Object.assign({}, options, opt) : options; | ||
if (SUPPORT_WORKER && this.worker) { | ||
index[key] = new worker_default(opt); | ||
if (!index[key].worker) { | ||
this.worker = false; | ||
} | ||
} | ||
if (!this.worker) { | ||
index[key] = new src_default(opt, this.register); | ||
} | ||
this.tree[i] = parse_tree(key, this.marker); | ||
this.field[i] = key; | ||
} | ||
if (SUPPORT_STORE && this.storetree) { | ||
let store = document["store"]; | ||
if (is_string(store)) { | ||
store = [store]; | ||
} | ||
for (let i = 0; i < store.length; i++) { | ||
this.storetree[i] = parse_tree(store[i], this.marker); | ||
} | ||
} | ||
return index; | ||
} | ||
function parse_tree(key, marker) { | ||
const tree = key.split(":"); | ||
let count = 0; | ||
for (let i = 0; i < tree.length; i++) { | ||
key = tree[i]; | ||
if (key.indexOf("[]") >= 0) { | ||
key = key.substring(0, key.length - 2); | ||
if (key) { | ||
marker[count] = true; | ||
} | ||
} | ||
if (key) { | ||
tree[count++] = key; | ||
} | ||
} | ||
if (count < tree.length) { | ||
tree.length = count; | ||
} | ||
return count > 1 ? tree : tree[0]; | ||
} | ||
function parse_simple(obj, tree) { | ||
if (is_string(tree)) { | ||
obj = obj[tree]; | ||
} else { | ||
for (let i = 0; obj && i < tree.length; i++) { | ||
obj = obj[tree[i]]; | ||
} | ||
} | ||
return obj; | ||
} | ||
function store_value(obj, store, tree, pos, key) { | ||
obj = obj[key]; | ||
if (pos === tree.length - 1) { | ||
store[key] = obj; | ||
} else if (obj) { | ||
if (is_array(obj)) { | ||
store = store[key] = new Array(obj.length); | ||
for (let i = 0; i < obj.length; i++) { | ||
store_value(obj, store, tree, pos, i); | ||
} | ||
} else { | ||
store = store[key] || (store[key] = create_object()); | ||
key = tree[++pos]; | ||
store_value(obj, store, tree, pos, key); | ||
} | ||
} | ||
} | ||
function add_index(obj, tree, marker, pos, index, id, key, _append) { | ||
obj = obj[key]; | ||
if (obj) { | ||
if (pos === tree.length - 1) { | ||
if (is_array(obj)) { | ||
if (marker[pos]) { | ||
for (let i = 0; i < obj.length; i++) { | ||
index.add( | ||
id, | ||
obj[i], | ||
/* append: */ | ||
true, | ||
/* skip update: */ | ||
true | ||
); | ||
} | ||
return; | ||
} | ||
obj = obj.join(" "); | ||
} | ||
index.add( | ||
id, | ||
obj, | ||
_append, | ||
/* skip_update: */ | ||
true | ||
); | ||
} else { | ||
if (is_array(obj)) { | ||
for (let i = 0; i < obj.length; i++) { | ||
add_index(obj, tree, marker, pos, index, id, i, _append); | ||
} | ||
} else { | ||
key = tree[++pos]; | ||
add_index(obj, tree, marker, pos, index, id, key, _append); | ||
} | ||
} | ||
} | ||
} | ||
Document.prototype.add = function(id, content, _append) { | ||
if (is_object(id)) { | ||
content = id; | ||
id = parse_simple(content, this.key); | ||
} | ||
if (content && (id || id === 0)) { | ||
if (!_append && this.register[id]) { | ||
return this.update(id, content); | ||
} | ||
for (let i = 0, tree, field; i < this.field.length; i++) { | ||
field = this.field[i]; | ||
tree = this.tree[i]; | ||
if (is_string(tree)) { | ||
tree = [tree]; | ||
} | ||
add_index(content, tree, this.marker, 0, this.index[field], id, tree[0], _append); | ||
} | ||
if (SUPPORT_TAGS && this.tag) { | ||
let tag = parse_simple(content, this.tag); | ||
let dupes = create_object(); | ||
if (is_string(tag)) { | ||
tag = [tag]; | ||
} | ||
for (let i = 0, key, arr; i < tag.length; i++) { | ||
key = tag[i]; | ||
if (!dupes[key]) { | ||
dupes[key] = 1; | ||
arr = this.tagindex[key] || (this.tagindex[key] = []); | ||
if (!_append || !arr.includes(id)) { | ||
arr[arr.length] = id; | ||
if (this.fastupdate) { | ||
const tmp = this.register[id] || (this.register[id] = []); | ||
tmp[tmp.length] = arr; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
if (SUPPORT_STORE && this.store && (!_append || !this.store[id])) { | ||
let store; | ||
if (this.storetree) { | ||
store = create_object(); | ||
for (let i = 0, tree; i < this.storetree.length; i++) { | ||
tree = this.storetree[i]; | ||
if (is_string(tree)) { | ||
store[tree] = content[tree]; | ||
} else { | ||
store_value(content, store, tree, 0, tree[0]); | ||
} | ||
} | ||
} | ||
this.store[id] = store || content; | ||
} | ||
} | ||
return this; | ||
}; | ||
Document.prototype.append = function(id, content) { | ||
return this.add(id, content, true); | ||
}; | ||
Document.prototype.update = function(id, content) { | ||
return this.remove(id).add(id, content); | ||
}; | ||
Document.prototype.remove = function(id) { | ||
if (is_object(id)) { | ||
id = parse_simple(id, this.key); | ||
} | ||
if (this.register[id]) { | ||
for (let i = 0; i < this.field.length; i++) { | ||
this.index[this.field[i]].remove(id, !this.worker); | ||
if (this.fastupdate) { | ||
break; | ||
} | ||
} | ||
if (SUPPORT_TAGS && this.tag) { | ||
if (!this.fastupdate) { | ||
for (let key in this.tagindex) { | ||
const tag = this.tagindex[key]; | ||
const pos = tag.indexOf(id); | ||
if (pos !== -1) { | ||
if (tag.length > 1) { | ||
tag.splice(pos, 1); | ||
} else { | ||
delete this.tagindex[key]; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
if (SUPPORT_STORE && this.store) { | ||
delete this.store[id]; | ||
} | ||
delete this.register[id]; | ||
} | ||
return this; | ||
}; | ||
Document.prototype.search = function(query, limit, options, _resolve) { | ||
if (!options) { | ||
if (!limit && is_object(query)) { | ||
options = /** @type {Object} */ | ||
query; | ||
query = ""; | ||
} else if (is_object(limit)) { | ||
options = /** @type {Object} */ | ||
limit; | ||
limit = 0; | ||
} | ||
} | ||
let result = [], result_field = []; | ||
let pluck, enrich; | ||
let field, tag, bool, offset, count = 0; | ||
if (options) { | ||
if (is_array(options)) { | ||
field = options; | ||
options = null; | ||
} else { | ||
query = options["query"] || query; | ||
pluck = options["pluck"]; | ||
field = pluck || options["index"] || options["field"]; | ||
tag = SUPPORT_TAGS && options["tag"]; | ||
enrich = SUPPORT_STORE && this.store && options["enrich"]; | ||
bool = options["bool"] === "and"; | ||
limit = options["limit"] || limit || 100; | ||
offset = options["offset"] || 0; | ||
if (tag) { | ||
if (is_string(tag)) { | ||
tag = [tag]; | ||
} | ||
if (!query) { | ||
for (let i = 0, res; i < tag.length; i++) { | ||
res = get_tag.call(this, tag[i], limit, offset, enrich); | ||
if (res) { | ||
result[result.length] = res; | ||
count++; | ||
} | ||
} | ||
return count ? result : []; | ||
} | ||
} | ||
if (is_string(field)) { | ||
field = [field]; | ||
} | ||
} | ||
} | ||
field || (field = this.field); | ||
bool = bool && (field.length > 1 || tag && tag.length > 1); | ||
const promises = !_resolve && (this.worker || this.async) && []; | ||
for (let i = 0, res, key, len; i < field.length; i++) { | ||
let field_options; | ||
key = field[i]; | ||
if (!is_string(key)) { | ||
field_options = key; | ||
key = field_options["field"]; | ||
query = field_options["query"] || query; | ||
limit = field_options["limit"] || limit; | ||
} | ||
if (promises) { | ||
promises[i] = this.index[key].searchAsync(query, limit, field_options || options); | ||
continue; | ||
} else if (_resolve) { | ||
res = _resolve[i]; | ||
} else { | ||
res = this.index[key].search(query, limit, field_options || options); | ||
} | ||
len = res && res.length; | ||
if (tag && len) { | ||
const arr = []; | ||
let count2 = 0; | ||
if (bool) { | ||
arr[0] = [res]; | ||
} | ||
for (let y = 0, key2, res2; y < tag.length; y++) { | ||
key2 = tag[y]; | ||
res2 = this.tagindex[key2]; | ||
len = res2 && res2.length; | ||
if (len) { | ||
count2++; | ||
arr[arr.length] = bool ? [res2] : res2; | ||
} | ||
} | ||
if (count2) { | ||
if (bool) { | ||
res = intersect(arr, limit || 100, offset || 0); | ||
} else { | ||
res = intersect_union(res, arr); | ||
} | ||
len = res.length; | ||
} | ||
} | ||
if (len) { | ||
result_field[count] = key; | ||
result[count++] = res; | ||
} else if (bool) { | ||
return []; | ||
} | ||
} | ||
if (promises) { | ||
const self2 = this; | ||
return new Promise(function(resolve) { | ||
Promise.all(promises).then(function(result2) { | ||
resolve(self2.search(query, limit, options, result2)); | ||
}); | ||
}); | ||
} | ||
if (!count) { | ||
return []; | ||
} | ||
if (pluck && (!enrich || !this.store)) { | ||
return result[0]; | ||
} | ||
for (let i = 0, res; i < result_field.length; i++) { | ||
res = result[i]; | ||
if (res.length) { | ||
if (enrich) { | ||
res = apply_enrich.call(this, res); | ||
} | ||
} | ||
if (pluck) { | ||
return res; | ||
} | ||
result[i] = { | ||
"field": result_field[i], | ||
"result": res | ||
}; | ||
} | ||
return result; | ||
}; | ||
function get_tag(key, limit, offset, enrich) { | ||
let res = this.tagindex[key]; | ||
let len = res && res.length - offset; | ||
if (len && len > 0) { | ||
if (len > limit || offset) { | ||
res = res.slice(offset, offset + limit); | ||
} | ||
if (enrich) { | ||
res = apply_enrich.call(this, res); | ||
} | ||
return { | ||
"tag": key, | ||
"result": res | ||
}; | ||
} | ||
} | ||
function apply_enrich(res) { | ||
const arr = new Array(res.length); | ||
for (let x = 0, id; x < res.length; x++) { | ||
id = res[x]; | ||
arr[x] = { | ||
"id": id, | ||
"doc": this.store[id] | ||
}; | ||
} | ||
return arr; | ||
} | ||
Document.prototype.contain = function(id) { | ||
return !!this.register[id]; | ||
}; | ||
if (SUPPORT_STORE) { | ||
Document.prototype.get = function(id) { | ||
return this.store[id]; | ||
}; | ||
Document.prototype.set = function(id, data) { | ||
this.store[id] = data; | ||
return this; | ||
}; | ||
} | ||
if (SUPPORT_CACHE) { | ||
Document.prototype.searchCache = searchCache; | ||
} | ||
if (SUPPORT_SERIALIZE) { | ||
Document.prototype.export = exportDocument; | ||
Document.prototype.import = importDocument; | ||
} | ||
if (SUPPORT_ASYNC) { | ||
async_default(Document.prototype); | ||
} | ||
// src/index.js | ||
function create2(options) { | ||
return new Index(options); | ||
} | ||
function Index(options, _register) { | ||
@@ -532,0 +1185,0 @@ if (!(this instanceof Index)) { |
@@ -23,3 +23,8 @@ var FlexSearch = (() => { | ||
__export(src_exports, { | ||
default: () => src_default | ||
Document: () => document_default, | ||
Worker: () => worker_default, | ||
create: () => create2, | ||
default: () => src_default, | ||
registerCharset: () => registerCharset, | ||
registerLanguage: () => registerLanguage | ||
}); | ||
@@ -29,5 +34,8 @@ | ||
var DEBUG = false; | ||
var SUPPORT_WORKER = true; | ||
var SUPPORT_ENCODER = true; | ||
var SUPPORT_CACHE = true; | ||
var SUPPORT_ASYNC = true; | ||
var SUPPORT_STORE = true; | ||
var SUPPORT_TAGS = true; | ||
var SUPPORT_SUGGESTION = true; | ||
@@ -194,2 +202,8 @@ var SUPPORT_SERIALIZE = true; | ||
var global_charset = {}; | ||
function registerCharset(name, charset) { | ||
global_charset[name] = charset; | ||
} | ||
function registerLanguage(name, lang) { | ||
global_lang[name] = lang; | ||
} | ||
@@ -206,3 +220,3 @@ // src/async.js | ||
prototype[key + "Async"] = function() { | ||
const self = this; | ||
const self2 = this; | ||
const args = ( | ||
@@ -220,5 +234,5 @@ /*[].slice.call*/ | ||
setTimeout(function() { | ||
self.async = true; | ||
const res = self[key].apply(self, args); | ||
self.async = false; | ||
self2.async = true; | ||
const res = self2[key].apply(self2, args); | ||
self2.async = false; | ||
resolve(res); | ||
@@ -317,2 +331,23 @@ }); | ||
} | ||
function intersect_union(mandatory, arrays) { | ||
const check = create_object(); | ||
const union = create_object(); | ||
const result = []; | ||
for (let x = 0; x < mandatory.length; x++) { | ||
check[mandatory[x]] = 1; | ||
} | ||
for (let x = 0, arr; x < arrays.length; x++) { | ||
arr = arrays[x]; | ||
for (let y = 0, id; y < arr.length; y++) { | ||
id = arr[y]; | ||
if (check[id]) { | ||
if (!union[id]) { | ||
union[id] = 1; | ||
result[result.length] = id; | ||
} | ||
} | ||
} | ||
} | ||
return result; | ||
} | ||
@@ -455,3 +490,3 @@ // src/cache.js | ||
// src/serialize.js | ||
function async(callback, self, field, key, index_doc, index, data) { | ||
function async(callback, self2, field, key, index_doc, index, data) { | ||
setTimeout(function() { | ||
@@ -461,10 +496,10 @@ const res = callback(field ? field + "." + key : key, JSON.stringify(data)); | ||
res["then"](function() { | ||
self.export(callback, self, field, index_doc, index + 1); | ||
self2.export(callback, self2, field, index_doc, index + 1); | ||
}); | ||
} else { | ||
self.export(callback, self, field, index_doc, index + 1); | ||
self2.export(callback, self2, field, index_doc, index + 1); | ||
} | ||
}); | ||
} | ||
function exportIndex(callback, self, field, index_doc, index) { | ||
function exportIndex(callback, self2, field, index_doc, index) { | ||
let key, data; | ||
@@ -501,3 +536,3 @@ switch (index || (index = 0)) { | ||
} | ||
async(callback, self || this, field, key, index_doc, index, data); | ||
async(callback, self2 || this, field, key, index_doc, index, data); | ||
return true; | ||
@@ -528,4 +563,622 @@ } | ||
} | ||
function exportDocument(callback, self2, field, index_doc, index) { | ||
index || (index = 0); | ||
index_doc || (index_doc = 0); | ||
if (index_doc < this.field.length) { | ||
const field2 = this.field[index_doc]; | ||
const idx = this.index[field2]; | ||
self2 = this; | ||
setTimeout(function() { | ||
if (!idx.export(callback, self2, index ? field2 : "", index_doc, index++)) { | ||
index_doc++; | ||
index = 1; | ||
self2.export(callback, self2, field2, index_doc, index); | ||
} | ||
}); | ||
} else { | ||
let key, data; | ||
switch (index) { | ||
case 1: | ||
key = "tag"; | ||
data = this.tagindex; | ||
break; | ||
case 2: | ||
key = "store"; | ||
data = this.store; | ||
break; | ||
default: | ||
return; | ||
} | ||
async(callback, this, field, key, index_doc, index, data); | ||
} | ||
} | ||
function importDocument(key, data) { | ||
if (!data) { | ||
return; | ||
} | ||
if (is_string(data)) { | ||
data = JSON.parse(data); | ||
} | ||
switch (key) { | ||
case "tag": | ||
this.tagindex = data; | ||
break; | ||
case "reg": | ||
this.fastupdate = false; | ||
this.register = data; | ||
for (let i = 0, index; i < this.field.length; i++) { | ||
index = this.index[this.field[i]]; | ||
index.register = data; | ||
index.fastupdate = false; | ||
} | ||
break; | ||
case "store": | ||
this.store = data; | ||
break; | ||
default: | ||
key = key.split("."); | ||
const field = key[0]; | ||
key = key[1]; | ||
if (field && key) { | ||
this.index[field].import(key, data); | ||
} | ||
} | ||
} | ||
// src/worker/handler.js | ||
function handler_default(data) { | ||
data = data["data"]; | ||
const index = self["_index"]; | ||
const args = data["args"]; | ||
const task = data["task"]; | ||
switch (task) { | ||
case "init": | ||
const options = data["options"] || {}; | ||
const factory2 = data["factory"]; | ||
const encode2 = options["encode"]; | ||
options["cache"] = false; | ||
if (encode2 && encode2.indexOf("function") === 0) { | ||
options["encode"] = Function("return " + encode2)(); | ||
} | ||
if (factory2) { | ||
Function("return " + factory2)()(self); | ||
self["_index"] = new self["FlexSearch"]["Index"](options); | ||
delete self["FlexSearch"]; | ||
} else { | ||
self["_index"] = new src_default(options); | ||
} | ||
break; | ||
default: | ||
const id = data["id"]; | ||
const message = index[task].apply(index, args); | ||
postMessage(task === "search" ? { "id": id, "msg": message } : { "id": id }); | ||
} | ||
} | ||
// src/worker/index.js | ||
var pid = 0; | ||
function WorkerIndex(options) { | ||
if (!(this instanceof WorkerIndex)) { | ||
return new WorkerIndex(options); | ||
} | ||
let opt; | ||
if (options) { | ||
if (is_function(opt = options["encode"])) { | ||
options["encode"] = opt.toString(); | ||
} | ||
} else { | ||
options = {}; | ||
} | ||
let factory2 = (self || window)["_factory"]; | ||
if (factory2) { | ||
factory2 = factory2.toString(); | ||
} | ||
const is_node_js2 = typeof window === "undefined" && self["exports"]; | ||
const _self = this; | ||
this.worker = create(factory2, is_node_js2, options["worker"]); | ||
this.resolver = create_object(); | ||
if (!this.worker) { | ||
return; | ||
} | ||
if (is_node_js2) { | ||
this.worker["on"]("message", function(msg) { | ||
_self.resolver[msg["id"]](msg["msg"]); | ||
delete _self.resolver[msg["id"]]; | ||
}); | ||
} else { | ||
this.worker.onmessage = function(msg) { | ||
msg = msg["data"]; | ||
_self.resolver[msg["id"]](msg["msg"]); | ||
delete _self.resolver[msg["id"]]; | ||
}; | ||
} | ||
this.worker.postMessage({ | ||
"task": "init", | ||
"factory": factory2, | ||
"options": options | ||
}); | ||
} | ||
var worker_default = WorkerIndex; | ||
register2("add"); | ||
register2("append"); | ||
register2("search"); | ||
register2("update"); | ||
register2("remove"); | ||
function register2(key) { | ||
WorkerIndex.prototype[key] = WorkerIndex.prototype[key + "Async"] = function() { | ||
const self2 = 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) { | ||
setTimeout(function() { | ||
self2.resolver[++pid] = resolve; | ||
self2.worker.postMessage({ | ||
"task": key, | ||
"id": pid, | ||
"args": args | ||
}); | ||
}); | ||
}); | ||
if (callback) { | ||
promise.then(callback); | ||
return this; | ||
} else { | ||
return promise; | ||
} | ||
}; | ||
} | ||
function create(factory, is_node_js, worker_path) { | ||
let worker; | ||
try { | ||
worker = is_node_js ? eval('new (require("worker_threads")["Worker"])("../dist/node/node.js")') : factory ? new Worker(URL.createObjectURL( | ||
new Blob([ | ||
"onmessage=" + handler_default.toString() | ||
], { "type": "text/javascript" }) | ||
)) : new Worker(is_string(worker_path) ? worker_path : "worker/worker.js", { type: "module" }); | ||
} catch (e) { | ||
} | ||
return worker; | ||
} | ||
// src/document.js | ||
function Document(options) { | ||
if (!(this instanceof Document)) { | ||
return new Document(options); | ||
} | ||
const document = options["document"] || options["doc"] || options; | ||
let opt; | ||
this.tree = []; | ||
this.field = []; | ||
this.marker = []; | ||
this.register = create_object(); | ||
this.key = (opt = document["key"] || document["id"]) && parse_tree(opt, this.marker) || "id"; | ||
this.fastupdate = parse_option(options["fastupdate"], true); | ||
if (SUPPORT_STORE) { | ||
this.storetree = (opt = document["store"]) && opt !== true && []; | ||
this.store = opt && create_object(); | ||
} | ||
if (SUPPORT_TAGS) { | ||
this.tag = (opt = document["tag"]) && parse_tree(opt, this.marker); | ||
this.tagindex = opt && create_object(); | ||
} | ||
if (SUPPORT_CACHE) { | ||
this.cache = (opt = options["cache"]) && new cache_default(opt); | ||
options["cache"] = false; | ||
} | ||
if (SUPPORT_WORKER) { | ||
this.worker = options["worker"]; | ||
} | ||
if (SUPPORT_ASYNC) { | ||
this.async = false; | ||
} | ||
this.index = parse_descriptor.call(this, options, document); | ||
} | ||
var document_default = Document; | ||
function parse_descriptor(options, document) { | ||
const index = create_object(); | ||
let field = document["index"] || document["field"] || document; | ||
if (is_string(field)) { | ||
field = [field]; | ||
} | ||
for (let i = 0, key, opt; i < field.length; i++) { | ||
key = field[i]; | ||
if (!is_string(key)) { | ||
opt = key; | ||
key = key["field"]; | ||
} | ||
opt = is_object(opt) ? Object.assign({}, options, opt) : options; | ||
if (SUPPORT_WORKER && this.worker) { | ||
index[key] = new worker_default(opt); | ||
if (!index[key].worker) { | ||
this.worker = false; | ||
} | ||
} | ||
if (!this.worker) { | ||
index[key] = new src_default(opt, this.register); | ||
} | ||
this.tree[i] = parse_tree(key, this.marker); | ||
this.field[i] = key; | ||
} | ||
if (SUPPORT_STORE && this.storetree) { | ||
let store = document["store"]; | ||
if (is_string(store)) { | ||
store = [store]; | ||
} | ||
for (let i = 0; i < store.length; i++) { | ||
this.storetree[i] = parse_tree(store[i], this.marker); | ||
} | ||
} | ||
return index; | ||
} | ||
function parse_tree(key, marker) { | ||
const tree = key.split(":"); | ||
let count = 0; | ||
for (let i = 0; i < tree.length; i++) { | ||
key = tree[i]; | ||
if (key.indexOf("[]") >= 0) { | ||
key = key.substring(0, key.length - 2); | ||
if (key) { | ||
marker[count] = true; | ||
} | ||
} | ||
if (key) { | ||
tree[count++] = key; | ||
} | ||
} | ||
if (count < tree.length) { | ||
tree.length = count; | ||
} | ||
return count > 1 ? tree : tree[0]; | ||
} | ||
function parse_simple(obj, tree) { | ||
if (is_string(tree)) { | ||
obj = obj[tree]; | ||
} else { | ||
for (let i = 0; obj && i < tree.length; i++) { | ||
obj = obj[tree[i]]; | ||
} | ||
} | ||
return obj; | ||
} | ||
function store_value(obj, store, tree, pos, key) { | ||
obj = obj[key]; | ||
if (pos === tree.length - 1) { | ||
store[key] = obj; | ||
} else if (obj) { | ||
if (is_array(obj)) { | ||
store = store[key] = new Array(obj.length); | ||
for (let i = 0; i < obj.length; i++) { | ||
store_value(obj, store, tree, pos, i); | ||
} | ||
} else { | ||
store = store[key] || (store[key] = create_object()); | ||
key = tree[++pos]; | ||
store_value(obj, store, tree, pos, key); | ||
} | ||
} | ||
} | ||
function add_index(obj, tree, marker, pos, index, id, key, _append) { | ||
obj = obj[key]; | ||
if (obj) { | ||
if (pos === tree.length - 1) { | ||
if (is_array(obj)) { | ||
if (marker[pos]) { | ||
for (let i = 0; i < obj.length; i++) { | ||
index.add( | ||
id, | ||
obj[i], | ||
/* append: */ | ||
true, | ||
/* skip update: */ | ||
true | ||
); | ||
} | ||
return; | ||
} | ||
obj = obj.join(" "); | ||
} | ||
index.add( | ||
id, | ||
obj, | ||
_append, | ||
/* skip_update: */ | ||
true | ||
); | ||
} else { | ||
if (is_array(obj)) { | ||
for (let i = 0; i < obj.length; i++) { | ||
add_index(obj, tree, marker, pos, index, id, i, _append); | ||
} | ||
} else { | ||
key = tree[++pos]; | ||
add_index(obj, tree, marker, pos, index, id, key, _append); | ||
} | ||
} | ||
} | ||
} | ||
Document.prototype.add = function(id, content, _append) { | ||
if (is_object(id)) { | ||
content = id; | ||
id = parse_simple(content, this.key); | ||
} | ||
if (content && (id || id === 0)) { | ||
if (!_append && this.register[id]) { | ||
return this.update(id, content); | ||
} | ||
for (let i = 0, tree, field; i < this.field.length; i++) { | ||
field = this.field[i]; | ||
tree = this.tree[i]; | ||
if (is_string(tree)) { | ||
tree = [tree]; | ||
} | ||
add_index(content, tree, this.marker, 0, this.index[field], id, tree[0], _append); | ||
} | ||
if (SUPPORT_TAGS && this.tag) { | ||
let tag = parse_simple(content, this.tag); | ||
let dupes = create_object(); | ||
if (is_string(tag)) { | ||
tag = [tag]; | ||
} | ||
for (let i = 0, key, arr; i < tag.length; i++) { | ||
key = tag[i]; | ||
if (!dupes[key]) { | ||
dupes[key] = 1; | ||
arr = this.tagindex[key] || (this.tagindex[key] = []); | ||
if (!_append || !arr.includes(id)) { | ||
arr[arr.length] = id; | ||
if (this.fastupdate) { | ||
const tmp = this.register[id] || (this.register[id] = []); | ||
tmp[tmp.length] = arr; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
if (SUPPORT_STORE && this.store && (!_append || !this.store[id])) { | ||
let store; | ||
if (this.storetree) { | ||
store = create_object(); | ||
for (let i = 0, tree; i < this.storetree.length; i++) { | ||
tree = this.storetree[i]; | ||
if (is_string(tree)) { | ||
store[tree] = content[tree]; | ||
} else { | ||
store_value(content, store, tree, 0, tree[0]); | ||
} | ||
} | ||
} | ||
this.store[id] = store || content; | ||
} | ||
} | ||
return this; | ||
}; | ||
Document.prototype.append = function(id, content) { | ||
return this.add(id, content, true); | ||
}; | ||
Document.prototype.update = function(id, content) { | ||
return this.remove(id).add(id, content); | ||
}; | ||
Document.prototype.remove = function(id) { | ||
if (is_object(id)) { | ||
id = parse_simple(id, this.key); | ||
} | ||
if (this.register[id]) { | ||
for (let i = 0; i < this.field.length; i++) { | ||
this.index[this.field[i]].remove(id, !this.worker); | ||
if (this.fastupdate) { | ||
break; | ||
} | ||
} | ||
if (SUPPORT_TAGS && this.tag) { | ||
if (!this.fastupdate) { | ||
for (let key in this.tagindex) { | ||
const tag = this.tagindex[key]; | ||
const pos = tag.indexOf(id); | ||
if (pos !== -1) { | ||
if (tag.length > 1) { | ||
tag.splice(pos, 1); | ||
} else { | ||
delete this.tagindex[key]; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
if (SUPPORT_STORE && this.store) { | ||
delete this.store[id]; | ||
} | ||
delete this.register[id]; | ||
} | ||
return this; | ||
}; | ||
Document.prototype.search = function(query, limit, options, _resolve) { | ||
if (!options) { | ||
if (!limit && is_object(query)) { | ||
options = /** @type {Object} */ | ||
query; | ||
query = ""; | ||
} else if (is_object(limit)) { | ||
options = /** @type {Object} */ | ||
limit; | ||
limit = 0; | ||
} | ||
} | ||
let result = [], result_field = []; | ||
let pluck, enrich; | ||
let field, tag, bool, offset, count = 0; | ||
if (options) { | ||
if (is_array(options)) { | ||
field = options; | ||
options = null; | ||
} else { | ||
query = options["query"] || query; | ||
pluck = options["pluck"]; | ||
field = pluck || options["index"] || options["field"]; | ||
tag = SUPPORT_TAGS && options["tag"]; | ||
enrich = SUPPORT_STORE && this.store && options["enrich"]; | ||
bool = options["bool"] === "and"; | ||
limit = options["limit"] || limit || 100; | ||
offset = options["offset"] || 0; | ||
if (tag) { | ||
if (is_string(tag)) { | ||
tag = [tag]; | ||
} | ||
if (!query) { | ||
for (let i = 0, res; i < tag.length; i++) { | ||
res = get_tag.call(this, tag[i], limit, offset, enrich); | ||
if (res) { | ||
result[result.length] = res; | ||
count++; | ||
} | ||
} | ||
return count ? result : []; | ||
} | ||
} | ||
if (is_string(field)) { | ||
field = [field]; | ||
} | ||
} | ||
} | ||
field || (field = this.field); | ||
bool = bool && (field.length > 1 || tag && tag.length > 1); | ||
const promises = !_resolve && (this.worker || this.async) && []; | ||
for (let i = 0, res, key, len; i < field.length; i++) { | ||
let field_options; | ||
key = field[i]; | ||
if (!is_string(key)) { | ||
field_options = key; | ||
key = field_options["field"]; | ||
query = field_options["query"] || query; | ||
limit = field_options["limit"] || limit; | ||
} | ||
if (promises) { | ||
promises[i] = this.index[key].searchAsync(query, limit, field_options || options); | ||
continue; | ||
} else if (_resolve) { | ||
res = _resolve[i]; | ||
} else { | ||
res = this.index[key].search(query, limit, field_options || options); | ||
} | ||
len = res && res.length; | ||
if (tag && len) { | ||
const arr = []; | ||
let count2 = 0; | ||
if (bool) { | ||
arr[0] = [res]; | ||
} | ||
for (let y = 0, key2, res2; y < tag.length; y++) { | ||
key2 = tag[y]; | ||
res2 = this.tagindex[key2]; | ||
len = res2 && res2.length; | ||
if (len) { | ||
count2++; | ||
arr[arr.length] = bool ? [res2] : res2; | ||
} | ||
} | ||
if (count2) { | ||
if (bool) { | ||
res = intersect(arr, limit || 100, offset || 0); | ||
} else { | ||
res = intersect_union(res, arr); | ||
} | ||
len = res.length; | ||
} | ||
} | ||
if (len) { | ||
result_field[count] = key; | ||
result[count++] = res; | ||
} else if (bool) { | ||
return []; | ||
} | ||
} | ||
if (promises) { | ||
const self2 = this; | ||
return new Promise(function(resolve) { | ||
Promise.all(promises).then(function(result2) { | ||
resolve(self2.search(query, limit, options, result2)); | ||
}); | ||
}); | ||
} | ||
if (!count) { | ||
return []; | ||
} | ||
if (pluck && (!enrich || !this.store)) { | ||
return result[0]; | ||
} | ||
for (let i = 0, res; i < result_field.length; i++) { | ||
res = result[i]; | ||
if (res.length) { | ||
if (enrich) { | ||
res = apply_enrich.call(this, res); | ||
} | ||
} | ||
if (pluck) { | ||
return res; | ||
} | ||
result[i] = { | ||
"field": result_field[i], | ||
"result": res | ||
}; | ||
} | ||
return result; | ||
}; | ||
function get_tag(key, limit, offset, enrich) { | ||
let res = this.tagindex[key]; | ||
let len = res && res.length - offset; | ||
if (len && len > 0) { | ||
if (len > limit || offset) { | ||
res = res.slice(offset, offset + limit); | ||
} | ||
if (enrich) { | ||
res = apply_enrich.call(this, res); | ||
} | ||
return { | ||
"tag": key, | ||
"result": res | ||
}; | ||
} | ||
} | ||
function apply_enrich(res) { | ||
const arr = new Array(res.length); | ||
for (let x = 0, id; x < res.length; x++) { | ||
id = res[x]; | ||
arr[x] = { | ||
"id": id, | ||
"doc": this.store[id] | ||
}; | ||
} | ||
return arr; | ||
} | ||
Document.prototype.contain = function(id) { | ||
return !!this.register[id]; | ||
}; | ||
if (SUPPORT_STORE) { | ||
Document.prototype.get = function(id) { | ||
return this.store[id]; | ||
}; | ||
Document.prototype.set = function(id, data) { | ||
this.store[id] = data; | ||
return this; | ||
}; | ||
} | ||
if (SUPPORT_CACHE) { | ||
Document.prototype.searchCache = searchCache; | ||
} | ||
if (SUPPORT_SERIALIZE) { | ||
Document.prototype.export = exportDocument; | ||
Document.prototype.import = importDocument; | ||
} | ||
if (SUPPORT_ASYNC) { | ||
async_default(Document.prototype); | ||
} | ||
// src/index.js | ||
function create2(options) { | ||
return new Index(options); | ||
} | ||
function Index(options, _register) { | ||
@@ -532,0 +1185,0 @@ if (!(this instanceof Index)) { |
508
index.d.ts
@@ -1,147 +0,395 @@ | ||
declare module "flexsearch" { | ||
export interface Index<T> { | ||
readonly id: string; | ||
readonly index: string; | ||
readonly length: number; | ||
// Type definitions for flexsearch 0.7 | ||
// Project: https://github.com/nextapps-de/flexsearch/ | ||
// Definitions by: LOSSES Don <https://github.com/Losses> | ||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped | ||
init(options?: CreateOptions): this; | ||
info(): { | ||
id: any; | ||
items: any; | ||
cache: any; | ||
matcher: number; | ||
worker: any; | ||
threshold: any; | ||
depth: any; | ||
resolution: any; | ||
contextual: boolean; | ||
}; | ||
add(o: T): this; | ||
add(id: number, o: string): this; | ||
/************************************/ | ||
/* Utils */ | ||
/************************************/ | ||
export type Id = number | string; | ||
export type Limit = number; | ||
export type ExportHandler<T> = (id: string | number, value: T) => void; | ||
export type AsyncCallback<T = undefined> = T extends undefined ? () => void : (result: T) => void; | ||
export type UnknownFunction = (...x: unknown[]) => unknown; | ||
// Result without pagination -> T[] | ||
search( | ||
export type StoreOption = boolean | string | string[]; | ||
export type EnrichStoreOption = true | string | string[]; | ||
/************************************/ | ||
/* Common Options */ | ||
/************************************/ | ||
/** | ||
* **Document:** | ||
* * Presets: https://github.com/nextapps-de/flexsearch#presets | ||
*/ | ||
export type Preset = "memory" | "performance" | "match" | "score" | "default"; | ||
/** | ||
* **Document:** | ||
* * Tokenizer: https://github.com/nextapps-de/flexsearch#tokenizer-prefix-search | ||
* * Add custom tokenizer: https://github.com/nextapps-de/flexsearch#add-custom-tokenizer | ||
*/ | ||
export type Tokenizer = | ||
| "strict" | ||
| "forward" | ||
| "reverse" | ||
| "full" | ||
| ((x: string) => string[]); | ||
/** | ||
* **Document:** | ||
* * Encoders: https://github.com/nextapps-de/flexsearch#encoders | ||
*/ | ||
export type Encoders = | ||
| false | ||
| "default" | ||
| "simple" | ||
| "balance" | ||
| "advanced" | ||
| "extra" | ||
| ((x: string) => string[]); | ||
/** | ||
* **Document:** | ||
* * Contextual search: https://github.com/nextapps-de/flexsearch#contextual | ||
*/ | ||
export interface ContextOptions { | ||
resolution: number; | ||
depth: false | number; | ||
bidirectional: boolean; | ||
} | ||
/** | ||
* **Document:** | ||
* * Search options: https://github.com/nextapps-de/flexsearch#search-options | ||
*/ | ||
export interface SearchOptions { | ||
query?: string; | ||
limit?: number; | ||
offset?: number; | ||
suggest?: boolean; | ||
} | ||
/** | ||
* **Document:** | ||
* * The document descriptor: https://github.com/nextapps-de/flexsearch#the-document-descriptor | ||
*/ | ||
export interface Descriptor<T, Store extends StoreOption = false> { | ||
id: string | number; | ||
field: string[] | Array<IndexOptions<T, Store>>; | ||
} | ||
/** | ||
* **Document:** | ||
* * Context Options: https://github.com/nextapps-de/flexsearch#context-options | ||
*/ | ||
export interface ContextOptions { | ||
resolution: number; | ||
depth: false | number; | ||
bidirectional: boolean; | ||
} | ||
/** | ||
* **Document:** | ||
* * Charset options: https://github.com/nextapps-de/flexsearch#charset-options | ||
*/ | ||
export interface CharsetOptions { | ||
split: false | string | RegExp; | ||
rtl: boolean; | ||
encode: (x: string) => string[]; | ||
} | ||
export interface Stemmer { | ||
[key: string]: string; | ||
} | ||
export interface Matcher { | ||
[key: string]: string; | ||
} | ||
export type FilterFunction = (x: string) => boolean; | ||
export type FilterArray = string[]; | ||
/** | ||
* **Document:** | ||
* * Language Options: https://github.com/nextapps-de/flexsearch#language-options | ||
* * Language: https://github.com/nextapps-de/flexsearch#languages | ||
*/ | ||
export interface LanguageOptions { | ||
stemmer: false | string | Stemmer | UnknownFunction; | ||
filter: false | string | FilterArray | FilterFunction; | ||
matcher: false | string | Matcher | UnknownFunction; | ||
} | ||
/** | ||
* These options will determine how the documents be indexed. | ||
* | ||
* **Generic type parameters:** | ||
* | ||
* @template T The type of the document. | ||
* @template Store If store is enabled. | ||
* | ||
* **Document:** | ||
* * Index options: https://github.com/nextapps-de/flexsearch#index-options | ||
* * Language: https://github.com/nextapps-de/flexsearch#languages | ||
*/ | ||
export interface IndexOptions<T, Store extends StoreOption = false> { | ||
preset?: Preset; | ||
tokenize?: Tokenizer; | ||
cache?: boolean | number; | ||
resolution?: number; | ||
context?: boolean | IndexOptions<T, Store> | ContextOptions; | ||
optimize?: boolean; | ||
boost?: (words: string[], term: string, index: number) => number; | ||
// Language-specific Options and Encoding | ||
charset?: CharsetOptions | string; | ||
language?: LanguageOptions | string; | ||
encode?: Encoders; | ||
stemmer?: LanguageOptions['stemmer']; | ||
filter?: LanguageOptions['filter']; | ||
matcher?: LanguageOptions['matcher']; | ||
} | ||
/************************************/ | ||
/* Index Search */ | ||
/************************************/ | ||
export type IndexSearchResult = Id[]; | ||
/** | ||
* **Document:** | ||
* * Basic usage and variants: https://github.com/nextapps-de/flexsearch#basic-usage-and-variants | ||
* * API overview: https://github.com/nextapps-de/flexsearch#api-overview | ||
* * Usage: https://github.com/nextapps-de/flexsearch#usage | ||
*/ | ||
export class Index { | ||
constructor(x?: Preset | IndexOptions<string>); | ||
add(id: Id, item: string): this; | ||
append(id: Id, item: string): this; | ||
update(id: Id, item: string): this; | ||
remove(target: Id): this; | ||
search(query: string, options?: Limit | SearchOptions): IndexSearchResult; | ||
search( | ||
query: string, | ||
options: number | SearchOptions, | ||
callback: (results: T[]) => void | ||
): void; | ||
search(query: string, options?: number | SearchOptions): Promise<T[]>; | ||
search( | ||
options: SearchOptions & { query: string }, | ||
callback: (results: T[]) => void | ||
): void; | ||
search(options: SearchOptions & { query: string }): Promise<T[]>; | ||
limit: number, | ||
options: SearchOptions | ||
): IndexSearchResult; | ||
search(options: SearchOptions): IndexSearchResult; | ||
// Result with pagination -> SearchResults<T> | ||
search( | ||
// https://github.com/nextapps-de/flexsearch#check-existence-of-already-indexed-ids | ||
contain(id: Id): boolean; | ||
export(handler: ExportHandler<string>): Promise<void>; | ||
import(id: Id, item: string): Promise<void>; | ||
// Async Methods | ||
addAsync(id: Id, item: string, callback?: AsyncCallback<this>): Promise<this>; | ||
appendAsync(id: Id, item: string, callback?: AsyncCallback<this>): Promise<this>; | ||
updateAsync(id: Id, item: string, callback?: AsyncCallback<this>): Promise<this>; | ||
removeAsync(target: Id, callback?: AsyncCallback<this>): Promise<this>; | ||
searchAsync( | ||
query: string, | ||
options: number | (SearchOptions & { page?: boolean | Cursor }), | ||
callback: (results: SearchResults<T>) => void | ||
): void; | ||
search( | ||
options?: Limit | SearchOptions, | ||
callback?: AsyncCallback<IndexSearchResult> | ||
): Promise<IndexSearchResult>; | ||
searchAsync( | ||
query: string, | ||
options?: number | (SearchOptions & { page?: boolean | Cursor }) | ||
): Promise<SearchResults<T>>; | ||
search( | ||
options: SearchOptions & { query: string; page?: boolean | Cursor }, | ||
callback: (results: SearchResults<T>) => void | ||
): void; | ||
search( | ||
options: SearchOptions & { query: string; page?: boolean | Cursor } | ||
): Promise<SearchResults<T>>; | ||
limit: number, | ||
options?: Limit | SearchOptions | ||
): IndexSearchResult; | ||
searchAsync(options: SearchOptions): Promise<IndexSearchResult>; | ||
} | ||
update(id: number, o: T): this; | ||
remove(id: number): this; | ||
clear(): this; | ||
destroy(): this; | ||
addMatcher(matcher: Matcher): this; | ||
/** | ||
* **Document:** | ||
* * Basic usage and variants: https://github.com/nextapps-de/flexsearch#basic-usage-and-variants | ||
* * API overview: https://github.com/nextapps-de/flexsearch#api-overview | ||
* * Worker index: https://github.com/nextapps-de/flexsearch#worker-index | ||
*/ | ||
export class Worker { | ||
constructor(x?: Preset | IndexOptions<string>); | ||
where(whereObj: { [key: string]: string } | ((o: T) => boolean)): T[]; | ||
encode(str: string): string; | ||
export( | ||
callback: (key: string, data: any) => any, | ||
self?: this, | ||
field?: string, | ||
index_doc?: Number, | ||
index?: Number | ||
): Promise<boolean>; | ||
import(exported: string): this; | ||
} | ||
add(id: Id, item: string, callback?: AsyncCallback<Worker>): Promise<this>; | ||
append(id: Id, item: string, callback?: AsyncCallback<this>): Promise<this>; | ||
update(id: Id, item: string, callback?: AsyncCallback<this>): Promise<this>; | ||
remove(target: Id, callback?: AsyncCallback<this>): Promise<this>; | ||
search( | ||
query: string, | ||
options?: Limit | SearchOptions, | ||
callback?: AsyncCallback<IndexSearchResult> | ||
): Promise<IndexSearchResult>; | ||
search( | ||
query: string, | ||
limit: number, | ||
options?: Limit | SearchOptions | ||
): IndexSearchResult; | ||
search(options: SearchOptions): Promise<IndexSearchResult>; | ||
interface SearchOptions { | ||
limit?: number; | ||
suggest?: boolean; | ||
where?: { [key: string]: string }; | ||
field?: string | string[]; | ||
bool?: "and" | "or" | "not"; | ||
//TODO: Sorting | ||
} | ||
// Async Methods | ||
addAsync(id: Id, item: string, callback?: AsyncCallback<this>): Promise<this>; | ||
appendAsync(id: Id, item: string, callback?: AsyncCallback<this>): Promise<this>; | ||
updateAsync(id: Id, item: string, callback?: AsyncCallback<this>): Promise<this>; | ||
removeAsync(target: Id, callback?: AsyncCallback<this>): Promise<this>; | ||
searchAsync( | ||
query: string, | ||
options?: Limit | SearchOptions, | ||
callback?: AsyncCallback<IndexSearchResult> | ||
): Promise<IndexSearchResult>; | ||
searchAsync( | ||
query: string, | ||
limit: number, | ||
options?: Limit | SearchOptions | ||
): IndexSearchResult; | ||
searchAsync(options: SearchOptions): Promise<IndexSearchResult>; | ||
} | ||
interface SearchResults<T> { | ||
page?: Cursor; | ||
next?: Cursor; | ||
result: T[]; | ||
} | ||
/************************************/ | ||
/* Document Search */ | ||
/************************************/ | ||
interface Document { | ||
id: string; | ||
field: any; | ||
} | ||
/* | ||
* **Document:** | ||
* * Document options: https://github.com/nextapps-de/flexsearch#document-options | ||
*/ | ||
export interface DocumentOptions<T, Store extends StoreOption = false> { | ||
id: string; | ||
tag?: false | string; | ||
index: string | string[] | Array<IndexOptions<T, Store> & { field: string }>; | ||
store?: Store; | ||
} | ||
export type CreateOptions = { | ||
profile?: IndexProfile; | ||
tokenize?: DefaultTokenizer | TokenizerFn; | ||
split?: RegExp; | ||
encode?: DefaultEncoder | EncoderFn | false; | ||
cache?: boolean | number; | ||
async?: boolean; | ||
worker?: false | number; | ||
depth?: false | number; | ||
threshold?: false | number; | ||
resolution?: number; | ||
stemmer?: Stemmer | string | false; | ||
filter?: FilterFn | string | false; | ||
rtl?: boolean; | ||
doc?: Document; | ||
}; | ||
/* | ||
* **Document:** | ||
* * Index options: https://github.com/nextapps-de/flexsearch#index-options | ||
*/ | ||
export interface IndexOptionsForDocumentSearch< | ||
T, | ||
Store extends StoreOption = false | ||
> extends IndexOptions<T, Store> { | ||
// Additional Options for Document Indexes | ||
worker?: boolean; | ||
document?: DocumentOptions<T, Store> | Descriptor<T, Store>; | ||
} | ||
// limit number Sets the limit of results. | ||
// suggest true, false Enables suggestions in results. | ||
// where object Use a where-clause for non-indexed fields. | ||
// field string, Array<string> Sets the document fields which should be searched. When no field is set, all fields will be searched. Custom options per field are also supported. | ||
// bool "and", "or" Sets the used logical operator when searching through multiple fields. | ||
// page true, false, cursor Enables paginated results. | ||
export interface SimpleDocumentSearchResultSetUnit { | ||
field: string; | ||
result: Id[]; | ||
} | ||
type IndexProfile = | ||
| "memory" | ||
| "speed" | ||
| "match" | ||
| "score" | ||
| "balance" | ||
| "fast"; | ||
type DefaultTokenizer = "strict" | "forward" | "reverse" | "full"; | ||
type TokenizerFn = (str: string) => string[]; | ||
type DefaultEncoder = "icase" | "simple" | "advanced" | "extra" | "balance"; | ||
type EncoderFn = (str: string) => string; | ||
type Stemmer = { [key: string]: string }; | ||
type Matcher = { [key: string]: string }; | ||
type FilterFn = (str: string) => boolean; | ||
type Cursor = string; | ||
export interface EnrichedDocumentSearchResultSetUnitResultUnit<T> { | ||
id: Id[]; | ||
doc: T; | ||
} | ||
export default class FlexSearch { | ||
static create<T>(options?: CreateOptions): Index<T>; | ||
static registerMatcher(matcher: Matcher): typeof FlexSearch; | ||
static registerEncoder(name: string, encoder: EncoderFn): typeof FlexSearch; | ||
static registerLanguage( | ||
lang: string, | ||
options: { stemmer?: Stemmer; filter?: string[] } | ||
): typeof FlexSearch; | ||
static encode(name: string, str: string): string; | ||
} | ||
export interface EnrichedDocumentSearchResultSetUnit<T> { | ||
field: string; | ||
result: Array<EnrichedDocumentSearchResultSetUnitResultUnit<T>>; | ||
} | ||
// FlexSearch.create(<options>) | ||
// FlexSearch.registerMatcher({KEY: VALUE}) | ||
// FlexSearch.registerEncoder(name, encoder) | ||
// FlexSearch.registerLanguage(lang, {stemmer:{}, filter:[]}) | ||
// FlexSearch.encode(name, string) | ||
/** | ||
* # Document Search Result | ||
* | ||
* To make your result return the full document: | ||
* * set `store` to `true` while creating the document; | ||
* * set `enrich` to `true` while searching. | ||
* | ||
* If neither of these conditions is met, then the returned result will be a `ISimpleDocumentSearchResult`. | ||
*/ | ||
export type DocumentSearchResult< | ||
T, | ||
Store extends StoreOption = false, | ||
Enrich extends boolean = false | ||
> = [Store, Enrich] extends [EnrichStoreOption, true] | ||
? Array<EnrichedDocumentSearchResultSetUnit<T>> | ||
: SimpleDocumentSearchResultSetUnit[]; | ||
/** | ||
* **Document:** | ||
* * Document search options: https://github.com/nextapps-de/flexsearch#document-search-options | ||
*/ | ||
export interface DocumentSearchOptions<T extends boolean> | ||
extends SearchOptions { | ||
index?: string | string[] | SearchOptions[]; | ||
tag?: string | string[]; | ||
enrich?: T; | ||
bool?: "and" | "or"; | ||
} | ||
/** | ||
* **Document:** | ||
* * Basic usage and variants: https://github.com/nextapps-de/flexsearch#basic-usage-and-variants | ||
* * API overview: https://github.com/nextapps-de/flexsearch#api-overview | ||
* * Document store: https://github.com/nextapps-de/flexsearch#document-store | ||
*/ | ||
export class Document<T, Store extends StoreOption = false> { | ||
constructor( | ||
options: IndexOptionsForDocumentSearch<T, Store>, | ||
typeHack?: T | ||
); | ||
add(document: T): this; | ||
add(id: Id, document: T): this; | ||
append(document: T): this; | ||
append(id: Id, document: T): this; | ||
update(document: T): this; | ||
update(id: Id, document: T): this; | ||
remove(target: Id | T): this; | ||
search(query: string, limit?: number): SimpleDocumentSearchResultSetUnit[]; | ||
// https://github.com/nextapps-de/flexsearch#field-search | ||
search(query: string, options: string[] | Partial<DocumentSearchOptions<boolean>>): SimpleDocumentSearchResultSetUnit[]; | ||
search<Enrich extends boolean = false>( | ||
query: string, | ||
limit?: number, | ||
options?: Partial<DocumentSearchOptions<Enrich>> | ||
): DocumentSearchResult<T, Store, Enrich>; | ||
search( | ||
options: Partial<DocumentSearchOptions<boolean>> | ||
): SimpleDocumentSearchResultSetUnit[]; | ||
export(handler: ExportHandler<T>): Promise<void>; | ||
import(id: Id, document: T): Promise<void>; | ||
// Async Methods | ||
addAsync(id: Id, document: T, callback?: AsyncCallback): Promise<this>; | ||
appendAsync(id: Id, document: T, callback?: AsyncCallback): Promise<this>; | ||
updateAsync(id: Id, document: T, callback?: AsyncCallback): Promise<this>; | ||
removeAsync(target: Id | T, callback?: AsyncCallback): Promise<this>; | ||
searchAsync<Enrich extends boolean = false>( | ||
query: string, | ||
options: string[] | Partial<DocumentSearchOptions<Enrich>> | ||
): Promise<DocumentSearchResult<T, Store, Enrich>>; | ||
searchAsync( | ||
query: string, | ||
limit?: number, | ||
): Promise<SimpleDocumentSearchResultSetUnit[]>; | ||
searchAsync( | ||
query: string, | ||
limit: number, | ||
callback: AsyncCallback<SimpleDocumentSearchResultSetUnit[]> | ||
): Promise<this>; | ||
searchAsync<Enrich extends boolean = false>( | ||
query: string, | ||
options: Partial<DocumentSearchOptions<Enrich>>, | ||
callback: AsyncCallback<DocumentSearchResult<T, Store, Enrich>> | ||
): Promise<this>; | ||
searchAsync<Enrich extends boolean = false>( | ||
options: Partial<DocumentSearchOptions<Enrich>> | ||
): Promise<DocumentSearchResult<T, Store, Enrich>>; | ||
searchAsync<Enrich extends boolean = false>( | ||
options: Partial<DocumentSearchOptions<Enrich>>, | ||
callback: AsyncCallback<DocumentSearchResult<T, Store, Enrich>> | ||
): Promise<this>; | ||
} | ||
/************************************/ | ||
/* Miscellaneous */ | ||
/************************************/ | ||
export function create(options: IndexOptions<string>): Index; | ||
export function registerCharset(name: string, charset: CharsetOptions): void; | ||
export function registerLanguage( | ||
name: string, | ||
language: LanguageOptions | ||
): void; |
{ | ||
"name": "@akryum/flexsearch-es", | ||
"version": "0.7.31", | ||
"version": "0.7.32", | ||
"description": "Next-Generation full text search library with zero dependencies.", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/Akryum/flexsearch-es/", |
@@ -19,6 +19,5 @@ /**! | ||
import { IndexInterface } from "./type.js"; | ||
import { encode as default_encoder } from "./lang/latin/default.js"; | ||
import { create_object, create_object_array, concat, sort_by_length_down, is_array, is_string, is_object, parse_option } from "./common.js"; | ||
import { pipeline, init_stemmer_or_matcher, init_filter } from "./lang.js"; | ||
import { init_stemmer_or_matcher, init_filter } from "./lang.js"; | ||
import { global_lang, global_charset } from "./global.js"; | ||
@@ -31,2 +30,12 @@ import apply_async from "./async.js"; | ||
export { registerCharset, registerLanguage } from "./global.js"; | ||
export { default as Document } from "./document.js"; | ||
export { default as Worker } from "./worker/index.js"; | ||
export function create(options) { | ||
return new Index(options); | ||
} | ||
/** | ||
@@ -33,0 +42,0 @@ * @constructor |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
393642
10454
4
46