Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions src/db/indexeddb/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@ import {
} from "../../type.js";

const VERSION = 1;
const IndexedDB = typeof window !== "undefined" && (
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB
// use globalThis instead of window so this also resolves inside Web Workers,
// where IndexedDB is available but there is no window object
const IndexedDB = typeof globalThis !== "undefined" && (
globalThis.indexedDB ||
globalThis.mozIndexedDB ||
globalThis.webkitIndexedDB ||
globalThis.msIndexedDB
);
const IDBTransaction = typeof window !== "undefined" && (
window.IDBTransaction ||
window.webkitIDBTransaction ||
window.msIDBTransaction
const IDBTransaction = typeof globalThis !== "undefined" && (
globalThis.IDBTransaction ||
globalThis.webkitIDBTransaction ||
globalThis.msIDBTransaction
);
const IDBKeyRange = typeof window !== "undefined" && (
window.IDBKeyRange ||
window.webkitIDBKeyRange ||
window.msIDBKeyRange
const IDBKeyRange = typeof globalThis !== "undefined" && (
globalThis.IDBKeyRange ||
globalThis.webkitIDBKeyRange ||
globalThis.msIDBKeyRange
);
const fields = ["map", "ctx", "tag", "reg", "cfg"];
import StorageInterface from "../interface.js";
Expand Down
21 changes: 16 additions & 5 deletions src/document/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Document.prototype.search = function(query, limit, options, _promises){
let result = [];
let result_field = [];
let pluck, enrich, merge, suggest, boost, cache;
let field, tag, offset, count = 0, resolve = true, highlight;
let field, tag, offset, count = 0, resolve = true, highlight, merge_limit = 0;

if(options){

Expand Down Expand Up @@ -123,6 +123,10 @@ Document.prototype.search = function(query, limit, options, _promises){
limit = options.limit || limit;
offset = options.offset || 0;
limit || (limit = (resolve ? 100 : 0));
// per-field options below may override "limit" for individual fields,
// so the overall limit requested by the caller has to be captured here
// to cap the merged result correctly.
merge_limit = limit;

if(tag && (!SUPPORT_PERSISTENT || !this.db || !_promises)){

Expand Down Expand Up @@ -550,7 +554,7 @@ Document.prototype.search = function(query, limit, options, _promises){
result = highlight_fields(/** @type {string} */ (query), result, self.index, pluck, highlight);
}
return merge
? merge_fields(result)
? merge_fields(result, merge_limit)
: /** @type {DocumentSearchResults} */ (result);
});
}
Expand All @@ -559,7 +563,7 @@ Document.prototype.search = function(query, limit, options, _promises){
result = highlight_fields(/** @type {string} */ (query), result, this.index, pluck, highlight);
}
return merge
? merge_fields(result)
? merge_fields(result, merge_limit)
: /** @type {DocumentSearchResults} */ (result);
}

Expand All @@ -570,14 +574,15 @@ Document.prototype.search = function(query, limit, options, _promises){

/**
* @param {DocumentSearchResults} fields
* @param {number=} limit
* @return {MergedDocumentSearchResults}
*/
function merge_fields(fields){
function merge_fields(fields, limit){
/** @type {MergedDocumentSearchResults} */
const final = [];
const group_field = create_object();
const group_highlight = create_object();
for(let i = 0, field, key, res, id, entry, tmp, highlight; i < fields.length; i++){
outer: for(let i = 0, field, key, res, id, entry, tmp, highlight; i < fields.length; i++){
field = fields[i];
key = field.field;
res = field.result;
Expand All @@ -589,6 +594,12 @@ function merge_fields(fields){
: id = entry["id"];
tmp = group_field[id];
if(!tmp){
// results are merged across fields, so the per-field limit
// applied earlier does not cap the merged total; stop once
// the overall requested limit has been reached
if(limit && final.length === limit){
break outer;
}
entry["field"] = group_field[id] = [key];
final.push(/** @type {!MergedDocumentSearchEntry} */ (entry));
}
Expand Down
37 changes: 37 additions & 0 deletions test/db.indexeddb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { expect } from "chai";

describe("Persistent: IndexedDB", function(){

it("Should resolve IndexedDB from globalThis (e.g. inside a Web Worker, where there is no window)", async function(){

// Node has no "window" global, which is exactly the condition that
// broke this adapter inside Web Workers (see #546): "window" is not
// defined there either, even though "indexedDB" is available via
// "globalThis"/"self".
expect(typeof window).to.equal("undefined");

let openCalledWith = null;

globalThis.indexedDB = {
open(name, version){
openCalledWith = [name, version];
// return a minimal request-like object; the adapter only
// assigns handlers to it, it doesn't need to ever resolve
// for this test
return {};
}
};

try{
const { default: IdxDB } = await import("../src/db/indexeddb/index.js?t=" + Date.now());
const db = new IdxDB("worker-test");

db.open();

expect(openCalledWith).to.eql(["flexsearch:worker-test", 1]);
}
finally{
delete globalThis.indexedDB;
}
});
});
36 changes: 36 additions & 0 deletions test/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,42 @@ if(!build_light) describe("Document (Multi-Field Search)", function(){
]);
});

it("Should cap merged results at the requested limit", function(){

const document = new Document({
document: {
id: "id",
field: [
"name_1",
"name_2",
"name_3"
]
}
});

const names = ["foo", "bar"];

// each field matches a different, non-overlapping half of the ids,
// so merging the per-field results (each already capped at "limit")
// produces more unique ids than "limit" unless the merge step
// re-applies the cap itself
for(let i = 0; i < 30; i++){
document.add({
id: i,
name_1: names[i % 2],
name_2: names[(i + 1) % 2],
name_3: names[i % 2]
});
}

const result = document.search("foo", {
merge: true,
limit: 10
});

expect(result.length).to.equal(10);
});

it("Using BigInt", function(){

const document = new Document({
Expand Down