1
0
mirror of https://github.com/nextapps-de/flexsearch.git synced 2025-10-04 09:01:41 +02:00
Files
flexsearch/src/document/add.js
2025-03-20 21:58:45 +01:00

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);
}
}
}