From 4a7a6371008d32ef33f4e91b46a8869b59c30164 Mon Sep 17 00:00:00 2001 From: Chun Shang Date: Mon, 5 Dec 2022 10:04:36 +0800 Subject: [PATCH] include score in each match --- src/core/config.js | 4 ++- src/core/format.js | 7 +++-- src/core/index.js | 4 ++- src/index.d.ts | 2 +- src/transform/index.js | 3 +- src/transform/transformMatchScore.js | 34 +++++++++++++++++++++ test/fuzzy-search.test.js | 44 +++++++++++++++++++++++++++- 7 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 src/transform/transformMatchScore.js diff --git a/src/core/config.js b/src/core/config.js index 13d019f9e..59e149729 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -5,6 +5,8 @@ export const MatchOptions = { // set will include the indices of the matched characters. // These can consequently be used for highlighting purposes. includeMatches: false, + // When true, every match will include its score + includeMatchScore: false, // When `true`, the matching function will continue to the end of a search pattern even if // a perfect match has already been located in the string. findAllMatches: false, @@ -16,7 +18,7 @@ export const BasicOptions = { // When `true`, the algorithm continues searching to the end of the input even if a perfect // match is found before the end of the same input. isCaseSensitive: false, - // When true, the matching function will continue to the end of a search pattern even if + // When true, each record in the result set will incude its match score includeScore: false, // List of properties that will be searched. This also supports nested properties. keys: [], diff --git a/src/core/format.js b/src/core/format.js index 0b3acf3d7..daf63e332 100644 --- a/src/core/format.js +++ b/src/core/format.js @@ -1,17 +1,20 @@ import Config from './config' -import { transformMatches, transformScore } from '../transform' +import { transformMatches, transformMatchScore, transformScore } from '../transform' export default function format( results, docs, { includeMatches = Config.includeMatches, + includeMatchScore = false, includeScore = Config.includeScore } = {} ) { const transformers = [] - if (includeMatches) transformers.push(transformMatches) + if (includeMatches) { + transformers.push(includeMatchScore ? transformMatchScore : transformMatches) + } if (includeScore) transformers.push(transformScore) return results.map((result) => { diff --git a/src/core/index.js b/src/core/index.js index f659bb043..cbac04049 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -77,6 +77,7 @@ export default class Fuse { search(query, { limit = -1, keys = [] } = {}) { const { includeMatches, + includeMatchScore, includeScore, shouldSort, sortFn, @@ -101,7 +102,8 @@ export default class Fuse { return format(results, this._docs, { includeMatches, - includeScore + includeScore, + includeMatchScore }) } diff --git a/src/index.d.ts b/src/index.d.ts index 41208f97c..3ce78502c 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -302,8 +302,8 @@ declare namespace Fuse { } export type FuseSearchOptions = { - limit?: number keys?: string[] + limit?: number } export type FuseResult = { diff --git a/src/transform/index.js b/src/transform/index.js index e6277f07c..4e0cc872a 100644 --- a/src/transform/index.js +++ b/src/transform/index.js @@ -1,4 +1,5 @@ import transformMatches from './transformMatches' +import transformMatchScore from './transformMatchScore' import transformScore from './transformScore' -export { transformMatches, transformScore } +export { transformMatches, transformMatchScore, transformScore } diff --git a/src/transform/transformMatchScore.js b/src/transform/transformMatchScore.js new file mode 100644 index 000000000..918c99872 --- /dev/null +++ b/src/transform/transformMatchScore.js @@ -0,0 +1,34 @@ +import { isDefined } from '../helpers/types' + +export default function transformMatchScore(result, data) { + const matches = result.matches + data.matches = [] + + if (!isDefined(matches)) { + return + } + + matches.forEach((match) => { + if (!isDefined(match.indices) || !match.indices.length) { + return + } + + const { indices, value, score } = match + + let obj = { + indices, + value, + score + } + + if (match.key) { + obj.key = match.key.src + } + + if (match.idx > -1) { + obj.refIndex = match.idx + } + + data.matches.push(obj) + }) +} diff --git a/test/fuzzy-search.test.js b/test/fuzzy-search.test.js index 1b7632c8b..8fb83e583 100644 --- a/test/fuzzy-search.test.js +++ b/test/fuzzy-search.test.js @@ -772,6 +772,48 @@ describe('Searching with findAllMatches', () => { }) }) +describe('Searching with includeMatchScore', () => { + const customBookList = [ + { + title: "Old Man's War fiction", + author: 'John X', + tags: ['war'] + }, + { + title: 'Right Ho Jeeves', + author: 'P.D. Mans', + tags: ['fiction', 'war'] + }, + { + title: 'The life of Jane', + author: 'John Smith', + tags: ['john', 'smith'] + }, + { + title: 'John Smith', + author: 'Steve Pearson', + tags: ['steve', 'pearson'] + } + ] + let fuse + + beforeEach( + () => + (fuse = new Fuse(customBookList, { + keys: ['title', 'author'], + includeMatches: true, + includeMatchScore: true, + findAllMatches: true + })) + ) + + test('Each match in every result item should have a score property', () => { + const result = fuse.search('life') + expect(result[0].matches[0]).toHaveProperty('score') + }) +}) + + describe('Searching with minCharLength', () => { const customList = ['t te tes test tes te t'] let fuse @@ -1067,7 +1109,7 @@ describe('Searching taking into account field length', () => { }) }) -describe.only('Searching with custom keys', () => { +describe('Searching with custom keys', () => { const customBookList = [ { title: "Old Man's War",