mirror of
https://github.com/nextapps-de/flexsearch.git
synced 2025-10-04 09:01:41 +02:00
268 lines
7.8 KiB
JavaScript
268 lines
7.8 KiB
JavaScript
// COMPILER BLOCK -->
|
|
import {
|
|
DEBUG,
|
|
SUPPORT_KEYSTORE,
|
|
SUPPORT_PERSISTENT,
|
|
SUPPORT_STORE,
|
|
SUPPORT_TAGS, SUPPORT_WORKER
|
|
} from "../config.js";
|
|
// <-- COMPILER BLOCK
|
|
import { create_object, is_array, is_object, is_string, parse_simple } from "../common.js";
|
|
import { KeystoreArray } from "../keystore.js";
|
|
import Document from "../document.js";
|
|
|
|
/**
|
|
*
|
|
* @param id
|
|
* @param content
|
|
* @param {boolean=} _append
|
|
* @returns {Document|Promise}
|
|
*/
|
|
|
|
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.reg.has(id)){
|
|
return this.update(id, content);
|
|
}
|
|
|
|
// this.field does not include db tag indexes
|
|
for(let i = 0, tree; i < this.field.length; i++){
|
|
|
|
tree = this.tree[i];
|
|
|
|
const index = this.index.get(this.field[i]);
|
|
if(typeof tree === "function"){
|
|
const tmp = tree(content);
|
|
if(tmp){
|
|
index.add(id, tmp, /* append: */ false, /* skip update: */ true);
|
|
}
|
|
}
|
|
else{
|
|
const filter = tree._filter;
|
|
if(filter && !filter(content)){
|
|
continue;
|
|
}
|
|
if(tree.constructor === String){
|
|
tree = ["" + tree];
|
|
}
|
|
else if(is_string(tree)){
|
|
tree = [tree];
|
|
}
|
|
add_index(content, tree, this.marker, 0, index, id, tree[0], _append);
|
|
}
|
|
}
|
|
|
|
if(SUPPORT_TAGS && this.tag){
|
|
|
|
//console.log(this.tag, this.tagtree)
|
|
|
|
for(let x = 0; x < this.tagtree.length; x++){
|
|
|
|
let tree = this.tagtree[x];
|
|
let field = this.tagfield[x];
|
|
let ref = this.tag.get(field);
|
|
let dupes = create_object();
|
|
let tags;
|
|
|
|
if(typeof tree === "function"){
|
|
tags = tree(content);
|
|
if(!tags) continue;
|
|
}
|
|
else{
|
|
const filter = tree._filter;
|
|
if(filter && !filter(content)){
|
|
continue;
|
|
}
|
|
if(tree.constructor === String){
|
|
tree = "" + tree;
|
|
}
|
|
tags = parse_simple(content, tree);
|
|
}
|
|
|
|
if(!ref || !tags){
|
|
ref || (DEBUG && console.warn("Tag '" + field + "' was not found"));
|
|
continue;
|
|
}
|
|
|
|
if(is_string(tags)){
|
|
tags = [tags];
|
|
}
|
|
|
|
for(let i = 0, tag, arr; i < tags.length; i++){
|
|
|
|
tag = tags[i];
|
|
//console.log(this.tag, tag, key, field)
|
|
|
|
if(!dupes[tag]){
|
|
dupes[tag] = 1;
|
|
|
|
let tmp;
|
|
tmp = ref.get(tag);
|
|
tmp ? arr = tmp : ref.set(tag, arr = []);
|
|
|
|
if(!_append || ! /** @type {!Array|KeystoreArray} */(arr).includes(id)){
|
|
|
|
// auto-upgrade to keystore array if max size exceeded
|
|
if(SUPPORT_KEYSTORE){
|
|
if(arr.length === 2**31-1 /*|| !(arr instanceof KeystoreArray)*/){
|
|
const keystore = new KeystoreArray(arr);
|
|
if(this.fastupdate){
|
|
for(let value of this.reg.values()){
|
|
if(value.includes(arr)){
|
|
value[value.indexOf(arr)] = keystore;
|
|
}
|
|
}
|
|
}
|
|
ref.set(tag, arr = keystore);
|
|
}
|
|
}
|
|
|
|
arr.push(id);
|
|
|
|
// add a reference to the register for fast updates
|
|
if(this.fastupdate){
|
|
const tmp = this.reg.get(id);
|
|
tmp ? tmp.push(arr)
|
|
: this.reg.set(id, [arr]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(SUPPORT_STORE && this.store && (!_append || !this.store.has(id))){
|
|
|
|
let payload;
|
|
|
|
if(this.storetree){
|
|
|
|
payload = create_object();
|
|
|
|
for(let i = 0, tree; i < this.storetree.length; i++){
|
|
tree = this.storetree[i];
|
|
|
|
const filter = tree._filter;
|
|
if(filter && !filter(content)){
|
|
continue;
|
|
}
|
|
let custom;
|
|
if(typeof tree === "function"){
|
|
custom = tree(content);
|
|
if(!custom) continue;
|
|
tree = [tree._field];
|
|
}
|
|
else if(is_string(tree) || tree.constructor === String){
|
|
payload[tree] = content[tree];
|
|
continue;
|
|
}
|
|
|
|
store_value(content, payload, tree, 0, tree[0], custom);
|
|
}
|
|
}
|
|
|
|
this.store.set(id, payload || content);
|
|
}
|
|
|
|
if(SUPPORT_WORKER && this.worker){
|
|
this.fastupdate || this.reg.add(id);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// TODO support generic function created from string when tree depth > 1
|
|
|
|
/**
|
|
* @param obj
|
|
* @param store
|
|
* @param tree
|
|
* @param pos
|
|
* @param key
|
|
* @param {*=} custom
|
|
*/
|
|
|
|
function store_value(obj, store, tree, pos, key, custom){
|
|
|
|
obj = obj[key];
|
|
|
|
// reached target field
|
|
if(pos === (tree.length - 1)){
|
|
|
|
// store target value
|
|
store[key] = custom || obj;
|
|
}
|
|
else if(obj){
|
|
|
|
if(is_array(obj)){
|
|
|
|
store = store[key] = new Array(obj.length);
|
|
|
|
for(let i = 0; i < obj.length; i++){
|
|
// do not increase pos (an array is not a field)
|
|
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){
|
|
|
|
if((obj = obj[key])){
|
|
|
|
// reached target field
|
|
if(pos === (tree.length - 1)){
|
|
|
|
// handle target value
|
|
if(is_array(obj)){
|
|
|
|
// append array contents so each entry gets a new scoring context
|
|
if(marker[pos]){
|
|
for(let i = 0; i < obj.length; i++){
|
|
index.add(id, obj[i], /* append: */ true, /* skip update: */ true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// or join array contents and use one scoring context
|
|
obj = obj.join(" ");
|
|
}
|
|
|
|
index.add(id, obj, _append, /* skip_update: */ true);
|
|
}
|
|
else{
|
|
|
|
if(is_array(obj)){
|
|
for(let i = 0; i < obj.length; i++){
|
|
// do not increase index, an array is not a field
|
|
add_index(obj, tree, marker, pos, index, id, i, _append);
|
|
}
|
|
}
|
|
else{
|
|
key = tree[++pos];
|
|
add_index(obj, tree, marker, pos, index, id, key, _append);
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
if(SUPPORT_PERSISTENT && index.db){
|
|
index.remove(id);
|
|
}
|
|
}
|
|
}
|