如何在 JavaScript 中搜索最接近的标签集匹配项?

How to search for closest tag set match in JavaScript?

我有一组文档,每个文档都用一组标签进行注释,其中可能包含空格。用户提供了一组可能拼写错误的标签,我想找到具有最多匹配标签(可选加权)的文档。

有数千个文档和标签,但每个文档最多有 100 个标签。

我正在寻找一种轻量级和高性能的解决方案,其中搜索应该完全在客户端使用 JavaScript 但可以使用 node.js 对索引进行一些预处理。

我的想法是使用多重集创建文档标签的反向索引,以及找到拼写错误标签的正确拼写的模糊索引,这些索引是在 node.js 中的预处理步骤中创建的,并且序列化为 JSON 个文件。在搜索步骤中,我想首先为查询集中的每个项目查询模糊索引以获得最可能正确的标签,如果存在则查询反向索引并将结果集添加到一个包(编号集) .对所有输入标签执行此操作后,包中的内容按降序排序,应提供最佳匹配文档。

我的问题

  1. 这似乎是一个常见问题,是否已经有我可以重复使用的实现?我查看了 lunr.js 和 fuse.js,但它们似乎有不同的重点。
    1. 这是解决问题的明智方法吗?你看到任何明显的改进吗?
    2. 将模糊步骤与倒排索引分开更好还是有办法将它们结合起来?

你应该能够使用 Lunr 实现你想要的,这里是一个简化的例子(和一个 jsfiddle):

var documents = [{
  id: 1, tags: ["foo", "bar"],
 },{
  id: 2, tags: ["hurp", "durp"]
}]

var idx = lunr(function (builder) {
  builder.ref('id')
  builder.field('tags')

  documents.forEach(function (doc) {
    builder.add(doc)
  })
})

console.log(idx.search("fob~1"))
console.log(idx.search("hurd~2"))

这利用了 Lunr 中的几个功能:

  1. 如果文档字段是一个数组,那么 Lunr 假定元素已经被标记化,这将允许您按原样索引包含空格的标签,即 "foo bar" 将被视为单个标签(如果这是你想要的,从问题中不清楚)
  2. 支持模糊搜索,这里使用查询字符串格式。波浪号后的数字是最大编辑距离,还有一些 documentation 进入细节。

结果将根据与查询最匹配的文档进行排序,简单来说,包含更多匹配标签的文档排名更高。

Is it better to keep the fuzzy step separate from the inverted index or is there a way to combine them?

一如既往,视情况而定。 Lunr维护了两个数据结构,一个倒排索引一个图。该图用于进行通配符和模糊匹配。它保留单独的数据结构,以便于在倒排索引中存储与匹配无关的术语的额外信息。

根据您的用例,可以将两者结合起来,一个有趣的方法是有限状态传感器,只要您要存储的数据很简单,例如一个整数(想想文档 id)。有一篇很棒的文章讨论了这种数据结构,它类似于 Lunr 中使用的数据结构 - http://blog.burntsushi.net/transducers/