From 4eafafcf709c16f9a72bdc0b427a2d56c34291b8 Mon Sep 17 00:00:00 2001 From: Luca Ongaro Date: Mon, 15 May 2023 22:55:57 +0200 Subject: [PATCH] Pass stored fields to boostDocument callback This makes it more convenient to perform dynamic boosting. --- CHANGELOG.md | 5 +++++ src/MiniSearch.test.js | 9 +++++---- src/MiniSearch.ts | 11 +++++++---- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e347e08d..9a3db9de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ `MiniSearch` follows [semantic versioning](https://semver.org/spec/v2.0.0.html). +# unreleased + + - Pass stored fields to the `boostDocument` callback function, making it + easier to perform dynamic document boosting. + # v6.0.1 - [fix] The `boost` search option now does not interfere with the `fields` diff --git a/src/MiniSearch.test.js b/src/MiniSearch.test.js index 7f5acabd..31e17035 100644 --- a/src/MiniSearch.test.js +++ b/src/MiniSearch.test.js @@ -1109,14 +1109,15 @@ describe('MiniSearch', () => { expect(results.map(({ id }) => id)).toEqual([2, 1]) }) - it('boosts documents by calling boostDocument with document ID and term', () => { - const query = 'divina commedia' + it('boosts documents by calling boostDocument with document ID, term, and stored fields', () => { + const query = 'divina commedia nova' const boostFactor = 1.234 const boostDocument = jest.fn((id, term) => boostFactor) const resultsWithoutBoost = ms.search(query) const results = ms.search(query, { boostDocument }) - expect(boostDocument).toHaveBeenCalledWith(1, 'divina') - expect(boostDocument).toHaveBeenCalledWith(1, 'commedia') + expect(boostDocument).toHaveBeenCalledWith(1, 'divina', {}) + expect(boostDocument).toHaveBeenCalledWith(1, 'commedia', {}) + expect(boostDocument).toHaveBeenCalledWith(3, 'nova', { category: 'poetry' }) expect(results[0].score).toBeCloseTo(resultsWithoutBoost[0].score * boostFactor) }) diff --git a/src/MiniSearch.ts b/src/MiniSearch.ts index 0af6c7c5..77b1cdee 100644 --- a/src/MiniSearch.ts +++ b/src/MiniSearch.ts @@ -38,9 +38,12 @@ export type SearchOptions = { /** * Function to calculate a boost factor for documents. It takes as arguments * the document ID, and a term that matches the search in that document, and - * should return a boosting factor. + * the value of the stored fields for the document (if any). It should return + * a boosting factor: a number higher than 1 increases the computed score, a + * number lower than 1 decreases the score, and a falsy value skips the search + * result completely. */ - boostDocument?: (documentId: any, term: string) => number, + boostDocument?: (documentId: any, term: string, storedFields?: Record) => number, /** * Controls whether to perform prefix search. It can be a simple boolean, or a @@ -1572,7 +1575,7 @@ export default class MiniSearch { termWeight: number, fieldTermData: FieldTermData | undefined, fieldBoosts: { [field: string]: number }, - boostDocumentFn: ((id: any, term: string) => number) | undefined, + boostDocumentFn: ((id: any, term: string, storedFields?: Record) => number) | undefined, bm25params: BM25Params, results: RawResult = new Map() ): RawResult { @@ -1595,7 +1598,7 @@ export default class MiniSearch { continue } - const docBoost = boostDocumentFn ? boostDocumentFn(this._documentIds.get(docId), derivedTerm) : 1 + const docBoost = boostDocumentFn ? boostDocumentFn(this._documentIds.get(docId), derivedTerm, this._storedFields.get(docId)) : 1 if (!docBoost) continue const termFreq = fieldTermFreqs.get(docId)!