From 4c71a28c93d7d62bfc9715ac1692aaac9b11cb18 Mon Sep 17 00:00:00 2001 From: Luca Ongaro Date: Wed, 1 Feb 2023 09:48:26 +0100 Subject: [PATCH] Fix unwanted side effects of boost, and cascading of combineWith The `boost` search option was mistakenly causing boosted fields to be included in search, even when they were not in the `fields` search option. The `combineWith` search option was not properly taking its default from the `SearchOptions` argument when using `search` with a `QuerySpec` tree. Both issues are fixed by this commit, that also adds corresponding tests. --- src/MiniSearch.test.js | 50 +++++++++++++++++++++++++++++++++++++++++- src/MiniSearch.ts | 4 ++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/MiniSearch.test.js b/src/MiniSearch.test.js index 5482104c..7f5acabd 100644 --- a/src/MiniSearch.test.js +++ b/src/MiniSearch.test.js @@ -1003,12 +1003,18 @@ describe('MiniSearch', () => { }) }) - it('searches in the given fields', () => { + it('searches only selected fields', () => { const results = ms.search('vita', { fields: ['title'] }) expect(results).toHaveLength(1) expect(results[0].id).toEqual(3) }) + it('searches only selected fields even if other fields are boosted', () => { + const results = ms.search('vita', { fields: ['title'], boost: { text: 2 } }) + expect(results).toHaveLength(1) + expect(results[0].id).toEqual(3) + }) + it('combines results with OR by default', () => { const results = ms.search('cammin como sottomarino') expect(results.length).toEqual(2) @@ -1222,6 +1228,48 @@ describe('MiniSearch', () => { expect(results.length).toEqual(2) expect(results.map(({ id }) => id)).toEqual([3, 2]) }) + + it('uses the search options in the second argument as default', () => { + let reference = ms.search({ + queries: [ + { fields: ['text'], queries: ['vita'] }, + { fields: ['title'], queries: ['promessi'] } + ] + }) + + // Boost field + let results = ms.search({ + queries: [ + { fields: ['text'], queries: ['vita'] }, + { fields: ['title'], queries: ['promessi'] } + ] + }, { boost: { title: 2 } }) + + expect(results.length).toEqual(reference.length) + expect(results.find((r) => r.id === 2).score) + .toBeGreaterThan(reference.find((r) => r.id === 2).score) + + // Combine with AND + results = ms.search({ + queries: [ + { fields: ['text'], queries: ['vita'] }, + { fields: ['title'], queries: ['promessi'] } + ] + }, { combineWith: 'AND' }) + + expect(results.length).toEqual(0) + + // Combine with AND, then override it with OR + results = ms.search({ + queries: [ + { fields: ['text'], queries: ['vita'] }, + { fields: ['title'], queries: ['promessi'] } + ], + combineWith: 'OR' + }, { combineWith: 'AND' }) + + expect(results.length).toEqual(reference.length) + }) }) describe('match data', () => { diff --git a/src/MiniSearch.ts b/src/MiniSearch.ts index 7350b9c4..0af6c7c5 100644 --- a/src/MiniSearch.ts +++ b/src/MiniSearch.ts @@ -1420,7 +1420,7 @@ export default class MiniSearch { if (typeof query !== 'string') { const options = { ...searchOptions, ...query, queries: undefined } const results = query.queries.map((subquery) => this.executeQuery(subquery, options)) - return this.combineResults(results, query.combineWith) + return this.combineResults(results, options.combineWith) } const { tokenize, processTerm, searchOptions: globalSearchOptions } = this._options @@ -1442,7 +1442,7 @@ export default class MiniSearch { const options: SearchOptionsWithDefaults = { ...this._options.searchOptions, ...searchOptions } const boosts = (options.fields || this._options.fields).reduce((boosts, field) => - ({ ...boosts, [field]: getOwnProperty(boosts, field) || 1 }), options.boost || {}) + ({ ...boosts, [field]: getOwnProperty(options.boost, field) || 1 }), {}) const { boostDocument,