mirror of
https://github.com/nextapps-de/flexsearch.git
synced 2025-09-25 04:51:29 +02:00
261 lines
7.5 KiB
JavaScript
261 lines
7.5 KiB
JavaScript
|
|
import { ResolverOptions, IntermediateSearchResults, SearchResults, EnrichedSearchResults, HighlightOptions } from "./type.js";
|
|
import Index from "./index.js";
|
|
import Document from "./document.js";
|
|
import WorkerIndex from "./worker.js";
|
|
import default_resolver from "./resolve/default.js";
|
|
import "./resolve/handler.js";
|
|
import "./resolve/or.js";
|
|
import "./resolve/and.js";
|
|
import "./resolve/xor.js";
|
|
import "./resolve/not.js";
|
|
import { apply_enrich } from "./document/search.js";
|
|
import { highlight_fields } from "./document/highlight.js";
|
|
|
|
/**
|
|
* @param {IntermediateSearchResults|ResolverOptions=} result
|
|
* @param {Index|Document|WorkerIndex=} index
|
|
* @return {Resolver}
|
|
* @constructor
|
|
*/
|
|
export default function Resolver(result, index) {
|
|
if (!this || this.constructor !== Resolver) {
|
|
return new Resolver(result, index);
|
|
}
|
|
|
|
let boost = 0,
|
|
promises,
|
|
query,
|
|
field,
|
|
highlight,
|
|
_await,
|
|
_return;
|
|
|
|
if (result && result.index) {
|
|
const options = /** @type {ResolverOptions} */result;
|
|
index = options.index;
|
|
boost = options.boost || 0;
|
|
if (query = options.query) {
|
|
field = options.field || options.pluck;
|
|
highlight = options.highlight;
|
|
const resolve = options.resolve,
|
|
async = options.async || options.queue;
|
|
|
|
options.resolve = !1;
|
|
options.index = null;
|
|
result = async ? index.searchAsync(options) : index.search(options);
|
|
options.resolve = resolve;
|
|
options.index = index;
|
|
result = result.result || result;
|
|
} else {
|
|
result = [];
|
|
}
|
|
}
|
|
|
|
if (result && result.then) {
|
|
const self = this;
|
|
result = result.then(function (result) {
|
|
self.promises[0] = self.result = result.result || result;
|
|
self.execute();
|
|
});
|
|
promises = [result];
|
|
result = [];
|
|
_await = new Promise(function (resolve) {
|
|
_return = resolve;
|
|
});
|
|
}
|
|
|
|
/** @type {Index|Document|WorkerIndex|null} */
|
|
this.index = index || null;
|
|
/** @type {IntermediateSearchResults} */
|
|
this.result = /** @type {IntermediateSearchResults} */result || [];
|
|
/** @type {number} */
|
|
this.boostval = boost;
|
|
/** @type {Array<Promise<IntermediateSearchResults>|IntermediateSearchResults|Function>} */
|
|
this.promises = promises || [];
|
|
/** @type {Promise<SearchResults|EnrichedSearchResults>} */
|
|
this.await = _await || null;
|
|
/** @type {Function} */
|
|
this.return = _return || null;
|
|
|
|
/** @type {HighlightOptions|null} */
|
|
this.highlight = /** @type {HighlightOptions|null} */highlight || null;
|
|
/** @type {string} */
|
|
this.query = query || "";
|
|
/** @type {string} */
|
|
this.field = field || "";
|
|
}
|
|
|
|
/**
|
|
* @param {number} limit
|
|
*/
|
|
Resolver.prototype.limit = function (limit) {
|
|
if (this.await) {
|
|
const self = this;
|
|
this.promises.push(function () {
|
|
return self.limit(limit).result;
|
|
});
|
|
} else {
|
|
if (this.result.length) {
|
|
/** @type {IntermediateSearchResults} */
|
|
const final = [];
|
|
for (let j = 0, ids; j < this.result.length; j++) {
|
|
if (ids = this.result[j]) {
|
|
if (ids.length <= limit) {
|
|
final[j] = ids;
|
|
limit -= ids.length;
|
|
if (!limit) break;
|
|
} else {
|
|
final[j] = ids.slice(0, limit);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
this.result = final;
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
*/
|
|
Resolver.prototype.offset = function (offset) {
|
|
if (this.await) {
|
|
const self = this;
|
|
this.promises.push(function () {
|
|
return self.offset(offset).result;
|
|
});
|
|
} else {
|
|
if (this.result.length) {
|
|
/** @type {IntermediateSearchResults} */
|
|
const final = [];
|
|
for (let j = 0, ids; j < this.result.length; j++) {
|
|
if (ids = this.result[j]) {
|
|
if (ids.length <= offset) {
|
|
offset -= ids.length;
|
|
} else {
|
|
final[j] = ids.slice(offset);
|
|
offset = 0;
|
|
}
|
|
}
|
|
}
|
|
this.result = final;
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* @param {number} boost
|
|
*/
|
|
Resolver.prototype.boost = function (boost) {
|
|
if (this.await) {
|
|
const self = this;
|
|
this.promises.push(function () {
|
|
return self.boost(boost).result;
|
|
});
|
|
} else {
|
|
this.boostval += boost;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* @param {boolean=} _skip_callback
|
|
* @this {Resolver}
|
|
*/
|
|
Resolver.prototype.execute = function (_skip_callback) {
|
|
let result = this.result,
|
|
execute = this.await;
|
|
|
|
this.await = null;
|
|
|
|
for (let i = 0, promise; i < this.promises.length; i++) {
|
|
if (promise = this.promises[i]) {
|
|
if ("function" == typeof promise) {
|
|
result = promise();
|
|
this.promises[i] = result = result.result || result;
|
|
i--;
|
|
} else if (promise._fn) {
|
|
result = promise._fn();
|
|
this.promises[i] = result = result.result || result;
|
|
i--;
|
|
} else if (promise.then) {
|
|
return this.await = execute;
|
|
}
|
|
}
|
|
}
|
|
|
|
const fn = this.return;
|
|
|
|
this.promises = [];
|
|
this.return = null;
|
|
|
|
_skip_callback || fn(result);
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* @param {number|ResolverOptions=} limit
|
|
* @param {number=} offset
|
|
* @param {boolean=} enrich
|
|
* @param {string|HighlightOptions|boolean=} highlight
|
|
* @param {boolean=} _resolved
|
|
*/
|
|
Resolver.prototype.resolve = function (limit, offset, enrich, highlight, _resolved) {
|
|
|
|
let result = this.await ? this.execute(!0) : this.result;
|
|
|
|
if (result.then) {
|
|
const self = this;
|
|
return result.then(function () {
|
|
return self.resolve(limit, offset, enrich, highlight, _resolved);
|
|
});
|
|
}
|
|
|
|
if (result.length) {
|
|
if ("object" == typeof limit) {
|
|
highlight = limit.highlight || this.highlight;
|
|
enrich = !!highlight || limit.enrich;
|
|
offset = limit.offset;
|
|
limit = limit.limit;
|
|
} else {
|
|
highlight = highlight || this.highlight;
|
|
enrich = !!highlight || enrich;
|
|
}
|
|
result = _resolved ? enrich ? apply_enrich.call(
|
|
/** @type {Document} */this.index,
|
|
/** @type {SearchResults} */result) : result : default_resolver.call(this.index, result, limit || 100, offset, enrich);
|
|
}
|
|
|
|
return this.finalize(result, highlight);
|
|
};
|
|
|
|
Resolver.prototype.finalize = function (result, highlight) {
|
|
|
|
if (result.then) {
|
|
const self = this;
|
|
return result.then(function (result) {
|
|
return self.finalize(result, highlight);
|
|
});
|
|
}
|
|
|
|
if (highlight && !this.query) {
|
|
console.warn('There was no query specified for highlighting. Please specify a query within the highlight resolver stage like { query: "...", highlight: ... }.');
|
|
}
|
|
|
|
if (highlight && result.length && this.query) {
|
|
result = highlight_fields(this.query, result, this.index.index, this.field, highlight);
|
|
}
|
|
|
|
const fn = this.return;
|
|
this.index = this.result = this.promises = this.await = this.return = null;
|
|
|
|
this.highlight = null;
|
|
this.query = this.field = "";
|
|
|
|
|
|
fn && fn(result);
|
|
return result;
|
|
}; |