mirror of
https://github.com/nextapps-de/flexsearch.git
synced 2025-09-26 05:19:00 +02:00
bundle pre-release
This commit is contained in:
430
dist/module-debug/intersect.js
vendored
430
dist/module-debug/intersect.js
vendored
@@ -1,4 +1,231 @@
|
||||
import { create_object, concat } from "./common.js";
|
||||
import { create_object, concat, sort_by_length_up, get_max_len } from "./common.js";
|
||||
|
||||
/*
|
||||
|
||||
from -> result[
|
||||
res[score][id],
|
||||
res[score][id],
|
||||
]
|
||||
|
||||
to -> [id]
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation based on Object[key] provides better suggestions
|
||||
* capabilities and has less performance scaling issues on large indexes.
|
||||
*
|
||||
* @param arrays
|
||||
* @param limit
|
||||
* @param offset
|
||||
* @param {boolean|Array=} suggest
|
||||
* @param {boolean=} resolve
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
export function intersect(arrays, limit, offset, suggest) {
|
||||
|
||||
const length = arrays.length;
|
||||
|
||||
// todo remove
|
||||
// if(length < 2){
|
||||
// throw new Error("Not optimized intersect");
|
||||
// }
|
||||
|
||||
let result = [],
|
||||
size = 0,
|
||||
check,
|
||||
check_suggest,
|
||||
check_new,
|
||||
res_arr;
|
||||
|
||||
|
||||
if (suggest) {
|
||||
suggest = [];
|
||||
}
|
||||
|
||||
// 1. a reversed order prioritize the order of words from a query
|
||||
// because it ends with the first term.
|
||||
// 2. process terms in reversed order often has advantage for
|
||||
// the fast path "end reached".
|
||||
|
||||
// alternatively the results could be sorted by length up
|
||||
//arrays.sort(sort_by_length_up);
|
||||
|
||||
// todo the outer loop should be the res array instead of term array,
|
||||
// this isn't just simple because the intersection calculation needs to reflect this
|
||||
//const maxlen = get_max_len(arrays);
|
||||
|
||||
for (let x = length - 1, found; 0 <= x; x--) {
|
||||
//for(let x = 0, found; x < length; x++){
|
||||
|
||||
res_arr = arrays[x];
|
||||
check_new = create_object();
|
||||
found = !check;
|
||||
|
||||
// process relevance in forward order (direction is
|
||||
// important for adding IDs during the last round)
|
||||
|
||||
for (let y = 0, ids; y < res_arr.length; y++) {
|
||||
|
||||
ids = res_arr[y];
|
||||
if (!ids || !ids.length) continue;
|
||||
|
||||
for (let z = 0, id; z < ids.length; z++) {
|
||||
|
||||
id = ids[z];
|
||||
|
||||
// check exists starting from the 2nd slot
|
||||
if (check) {
|
||||
if (check[id]) {
|
||||
|
||||
// check if in last round
|
||||
if (!x) {
|
||||
//if(x === length - 1){
|
||||
|
||||
if (offset) {
|
||||
offset--;
|
||||
} else {
|
||||
|
||||
result[size++] = id;
|
||||
|
||||
if (size === limit) {
|
||||
// fast path "end reached"
|
||||
return result; /*resolve === false
|
||||
? { result, suggest }
|
||||
:*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x || suggest) {
|
||||
//if((x < length - 1) || suggest){
|
||||
check_new[id] = 1;
|
||||
}
|
||||
|
||||
found = /* tag? */ /* stringify */ /* stringify */ /* skip update: */ /* append: */ /* skip update: */ /* skip_update: */ /* skip deletion */!0 /*await rows.hasNext()*/ /*await rows.hasNext()*/ /*await rows.hasNext()*/;
|
||||
}
|
||||
|
||||
if (suggest) {
|
||||
|
||||
if (!check_suggest[id]) {
|
||||
check_suggest[id] = 1;
|
||||
const arr = suggest[y] || (suggest[y] = []);
|
||||
arr.push(id);
|
||||
}
|
||||
|
||||
// OLD:
|
||||
//
|
||||
// check_idx = (check_suggest[id] || 0) + 1;
|
||||
// check_suggest[id] = check_idx;
|
||||
//
|
||||
// // do not adding IDs which are already included in the result (saves one loop)
|
||||
// // the first intersection match has the check index 2, so shift by -2
|
||||
//
|
||||
// if(check_idx < length){
|
||||
//
|
||||
// const tmp = suggest[check_idx - 2] || (suggest[check_idx - 2] = []);
|
||||
// tmp[tmp.length] = id;
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
|
||||
// pre-fill in first round
|
||||
check_new[id] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (suggest) {
|
||||
|
||||
// re-use the first pre-filled check for suggestions
|
||||
check || (check_suggest = check_new);
|
||||
} else if (!found) {
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
check = check_new;
|
||||
}
|
||||
|
||||
// return intermediate result
|
||||
// if(resolve === false){
|
||||
// return { result, suggest };
|
||||
// }
|
||||
|
||||
if (suggest) {
|
||||
|
||||
// needs to iterate in reverse direction
|
||||
for (let x = suggest.length - 1, ids, len; 0 <= x; x--) {
|
||||
|
||||
ids = suggest[x];
|
||||
len = ids.length;
|
||||
|
||||
for (let y = 0, id; y < len; y++) {
|
||||
|
||||
id = ids[y];
|
||||
|
||||
if (!check[id]) {
|
||||
|
||||
if (offset) {
|
||||
offset--;
|
||||
} else {
|
||||
|
||||
result[size++] = id;
|
||||
|
||||
if (size === limit) {
|
||||
// fast path "end reached"
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
check[id] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mandatory
|
||||
* @param arrays
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
export function intersect_union(mandatory, arrays) {
|
||||
const check = create_object(),
|
||||
union = create_object(),
|
||||
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.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation based on Array.includes() provides better performance,
|
||||
@@ -192,203 +419,4 @@ import { create_object, concat } from "./common.js";
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Implementation based on Object[key] provides better suggestions
|
||||
* capabilities and has less performance scaling issues on large indexes.
|
||||
*
|
||||
* @param arrays
|
||||
* @param limit
|
||||
* @param offset
|
||||
* @param {boolean|Array=} suggest
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
export function intersect(arrays, limit, offset, suggest) {
|
||||
|
||||
const length = arrays.length;
|
||||
let result = [],
|
||||
check,
|
||||
check_suggest,
|
||||
size = 0;
|
||||
|
||||
|
||||
if (suggest) {
|
||||
|
||||
suggest = [];
|
||||
}
|
||||
|
||||
// process terms in reversed order often has advantage for the fast path "end reached".
|
||||
// also a reversed order prioritize the order of words from a query.
|
||||
|
||||
for (let x = length - 1; 0 <= x; x--) {
|
||||
const word_arr = arrays[x],
|
||||
word_arr_len = word_arr.length,
|
||||
check_new = create_object();
|
||||
|
||||
|
||||
let found = !check;
|
||||
|
||||
// process relevance in forward order (direction is
|
||||
// important for adding IDs during the last round)
|
||||
|
||||
for (let y = 0; y < word_arr_len; y++) {
|
||||
const arr = word_arr[y],
|
||||
arr_len = arr.length;
|
||||
|
||||
|
||||
if (arr_len) {
|
||||
|
||||
// loop through IDs
|
||||
|
||||
for (let z = 0, check_idx, id; z < arr_len; z++) {
|
||||
|
||||
id = arr[z];
|
||||
|
||||
if (check) {
|
||||
|
||||
if (check[id]) {
|
||||
|
||||
// check if in last round
|
||||
|
||||
if (!x) {
|
||||
|
||||
if (offset) {
|
||||
|
||||
offset--;
|
||||
} else {
|
||||
|
||||
result[size++] = id;
|
||||
|
||||
if (size === limit) {
|
||||
|
||||
// fast path "end reached"
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x || suggest) {
|
||||
|
||||
check_new[id] = 1;
|
||||
}
|
||||
|
||||
found = /* append: */ /* skip update: */ /* skip_update: */!0;
|
||||
}
|
||||
|
||||
if (suggest) {
|
||||
|
||||
check_idx = (check_suggest[id] || 0) + 1;
|
||||
check_suggest[id] = check_idx;
|
||||
|
||||
// do not adding IDs which are already included in the result (saves one loop)
|
||||
// the first intersection match has the check index 2, so shift by -2
|
||||
|
||||
if (check_idx < length) {
|
||||
|
||||
const tmp = suggest[check_idx - 2] || (suggest[check_idx - 2] = []);
|
||||
tmp[tmp.length] = id;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// pre-fill in first round
|
||||
|
||||
check_new[id] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (suggest) {
|
||||
|
||||
// re-use the first pre-filled check for suggestions
|
||||
|
||||
check || (check_suggest = check_new);
|
||||
} else if (!found) {
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
check = check_new;
|
||||
}
|
||||
|
||||
if (suggest) {
|
||||
|
||||
// needs to iterate in reverse direction
|
||||
|
||||
for (let x = suggest.length - 1, arr, len; 0 <= x; x--) {
|
||||
|
||||
arr = suggest[x];
|
||||
len = arr.length;
|
||||
|
||||
for (let y = 0, id; y < len; y++) {
|
||||
|
||||
id = arr[y];
|
||||
|
||||
if (!check[id]) {
|
||||
|
||||
if (offset) {
|
||||
|
||||
offset--;
|
||||
} else {
|
||||
|
||||
result[size++] = id;
|
||||
|
||||
if (size === limit) {
|
||||
|
||||
// fast path "end reached"
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
check[id] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mandatory
|
||||
* @param arrays
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
export function intersect_union(mandatory, arrays) {
|
||||
const check = create_object(),
|
||||
union = create_object(),
|
||||
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;
|
||||
}
|
||||
// }
|
Reference in New Issue
Block a user