Fuse.js搜索评分异常 精确匹配结果排序错误问题排查
问题根因
Fuse.js默认配置存在两个问题导致排序异常:
- 默认配置下括号等特殊符号、字符串位置权重计算逻辑有偏差,
Paper Beauty (Winter)和Paper Beauty (Awakened)两个条目和搜索词的匹配度会被计算出完全相同的score值 - 当多个条目score完全一致时,Fuse会默认按照条目在原数据源数组中的索引顺序排序,
Paper Beauty (Winter)在names数组里的refIndex是77,比目标条目的135更靠前,所以被排在了首位。
修复代码
直接调整Fuse初始化参数,再加一层同得分兜底排序即可,修改后的完整实现:
const Fuse = require("fuse.js"); const { trendSystem, demandSystem } = require("../../util/functions"); const names = require("../../names.json"); module.exports = { name: "stats", category: "trading", devOnly: false, run: async ({ client, message, args }) => { const options = { includeScore: true, // 关闭位置权重影响,避免匹配字符位置带来的得分误差 ignoreLocation: true, // 调低模糊匹配阈值,降低容错率,差异项不会再和精确项拿到相同得分 threshold: 0.3, // 开启分词,让括号内的后缀作为独立匹配单元参与权重计算 tokenize: true }; const searcher = new Fuse(names, options); const results = searcher.search(args[0]).slice(0, 11); // 同得分兜底排序:完全匹配输入关键词的条目强制置顶 results.sort((a, b) => { if (Math.abs(a.score - b.score) < Number.EPSILON) { return a.item === args[0] ? -1 : b.item === args[0] ? 1 : 0; } return a.score - b.score; }); console.log(results); } }
关键配置说明
ignoreLocation: true:关闭匹配字符所在位置的权重加成,避免靠前的字符匹配拿到不合理的额外高分threshold: 0.3:默认阈值是0.6,容错率太高,调低后只有匹配度足够高的条目才会拿到低得分,括号后缀不同的条目得分会明显拉开差距- 末尾的自定义排序是极端情况兜底:就算出现得分完全相等的情况,和输入关键词完全一致的精确匹配项一定会排在最前面,不会受原数组索引顺序影响。
内容的提问来源于stack exchange,提问作者pygon
相关产品推荐
相关产品推荐

