1
0
mirror of https://github.com/nextapps-de/flexsearch.git synced 2025-09-25 12:58:59 +02:00
Files
flexsearch/dist/module-debug/intersect.js
Thomas Wilkerling 103f617ad5 v0.8.2
2025-05-21 13:43:38 +02:00

261 lines
7.1 KiB
JavaScript

import Resolver from "./resolver.js";
import { create_object, concat, sort_by_length_up, get_max_len } from "./common.js";
import { SearchResults, IntermediateSearchResults } from "./type.js";
/*
from -> result[
res[score][id],
res[score][id],
]
to -> [id]
*/
/**
* @param {!Array<IntermediateSearchResults>} arrays
* @param {number} resolution
* @param {number} limit
* @param {number=} offset
* @param {boolean=} suggest
* @param {number=} boost
* @param {boolean=} resolve
* @returns {SearchResults|IntermediateSearchResults}
*/
export function intersect(arrays, resolution, limit, offset, suggest, boost, resolve) {
const length = arrays.length;
/** @type {Array<SearchResults|IntermediateSearchResults>} */
let result = [],
check,
count;
check = create_object();
for (let y = 0, ids, id, res_arr, tmp; y < resolution; y++) {
for (let x = 0; x < length; x++) {
res_arr = arrays[x];
if (y < res_arr.length && (ids = res_arr[y])) {
for (let z = 0; z < ids.length; z++) {
id = ids[z];
if (count = check[id]) {
check[id]++;
} else {
count = 0;
check[id] = 1;
}
tmp = result[count] || (result[count] = []);
if (!resolve) {
let score = y + (x || !suggest ? 0 : boost || 0);
tmp = tmp[score] || (tmp[score] = []);
}
tmp.push(id);
if (resolve) {
if (limit && count === length - 1) {
if (tmp.length - offset === limit) {
return offset ? tmp.slice(offset) : tmp;
}
}
}
}
}
}
}
const result_len = result.length;
if (result_len) {
if (!suggest) {
if (result_len < length) {
return [];
}
result = /** @type {SearchResults|IntermediateSearchResults} */result[result_len - 1];
if (limit || offset) {
if (resolve) {
if (result.length > limit || offset) {
result = result.slice(offset, limit + offset);
}
} else {
const final = [];
for (let i = 0, arr; i < result.length; i++) {
arr = result[i];
if (!arr) continue;
if (offset && arr.length > offset) {
offset -= arr.length;
continue;
}
if (limit && arr.length > limit || offset) {
arr = arr.slice(offset, limit + offset);
limit -= arr.length;
if (offset) offset -= arr.length;
}
final.push(arr);
if (!limit) {
break;
}
}
result = final;
}
}
} else {
result = 1 < result.length ? union(result, limit, offset, resolve, boost) : (result = result[0]) && limit && result.length > limit || offset ? result.slice(offset, limit + offset) : result;
}
}
return (/** @type {SearchResults|IntermediateSearchResults} */result
);
}
/**
* @param {Array<SearchResults|IntermediateSearchResults>} arrays
* @param {number} limit
* @param {number=} offset
* @param {boolean=} resolve
* @param {number=} boost
* @returns {SearchResults|IntermediateSearchResults}
*/
export function union(arrays, limit, offset, resolve, boost) {
/** @type {SearchResults|IntermediateSearchResults} */
const result = [],
check = create_object();
let ids,
id,
arr_len = arrays.length,
ids_len;
if (!resolve) {
for (let i = arr_len - 1, res, count = 0; 0 <= i; i--) {
res = arrays[i];
for (let k = 0; k < res.length; k++) {
ids = res[k];
ids_len = ids && ids.length;
if (ids_len) for (let j = 0; j < ids_len; j++) {
id = ids[j];
if (!check[id]) {
check[id] = 1;
if (offset) {
offset--;
} else {
let score = 0 | (k + (i < arr_len - 1 ? boost || 0 : 0)) / (i + 1),
arr = result[score] || (result[score] = []);
arr.push(id);
if (++count === limit) {
return result;
}
}
}
}
}
}
} else for (let i = arr_len - 1; 0 <= i; i--) {
ids = arrays[i];
ids_len = ids && ids.length;
if (ids_len) for (let j = 0; j < ids_len; j++) {
id = ids[j];
if (!check[id]) {
check[id] = 1;
if (offset) {
offset--;
} else {
result.push(id);
if (result.length === limit) {
return result;
}
}
}
}
}
return result;
}
/**
* @param {SearchResults|IntermediateSearchResults|Resolver} arrays
* @param {Array<SearchResults>} mandatory
* @param {boolean=} resolve
* @returns {SearchResults}
*/
export function intersect_union(arrays, mandatory, resolve) {
const check = create_object(),
result = [];
/** @type {SearchResults|IntermediateSearchResults} */
for (let x = 0, ids; x < mandatory.length; x++) {
ids = mandatory[x];
for (let i = 0; i < ids.length; i++) {
check[ids[i]] = 1;
}
}
if (resolve) {
for (let i = 0, id; i < arrays.length; i++) {
id = arrays[i];
if (check[id]) {
result.push(id);
check[id] = 0;
}
}
} else {
for (let i = 0, ids, id; i < arrays.result.length; i++) {
ids = arrays.result[i];
for (let j = 0; j < ids.length; j++) {
id = ids[j];
if (check[id]) {
const arr = result[i] || (result[i] = []);
arr.push(id);
check[id] = 0;
}
}
}
}
return result;
}
/**
* Implementation based on Array.includes() provides better performance,
* but it needs at least one word in the query which is less frequent.
* Also on large indexes it does not scale well performance-wise.
* This strategy also lacks of suggestion capabilities (matching & sorting).
*
* @param arrays
* @param limit
* @param offset
* @param {boolean|Array=} suggest
* @returns {Array}
*/