MongoDB全文搜索+针对部分单词匹配的解决方法

27

由于使用mongodb全文搜索无法通过单词“blue”找到“blueberry”,我想帮助我的用户将单词“blue”自动补全为“blueberry”。为此,是否可以查询mongodb全文索引中的所有单词,以便我可以将这些单词用作建议,例如typeahead.js?


我不相信这已经存在,你可能能够使用查询条件,但我认为它们没有得分:http://docs.mongodb.org/manual/reference/command/text/#search-with-additional-query-conditions - Sammaye
谁说在MongoDB中无法进行字符串的部分匹配?https://dev59.com/8XA75IYBdhLWcg3wboUz - Deniz Zoeteman
6
@DenizZoeteman,我不确定您是否理解问题,这是关于FTS而不是一般查询。 - Sammaye
你可以尝试这里提到的解决方案: https://dev59.com/gVsW5IYBdhLWcg3wSVqM#48250561 - TomoMiha
5个回答

12

文本搜索中的语言词干处理使用算法来尝试关联来自相同基础的单词(例如,“running”应该匹配“run”)。这与您要实现的自动完成功能的前缀匹配(例如,“blue”匹配“blueberry”)不同。

为了最有效地使用typeahead.js与MongoDB文本搜索,我建议专注于typeahead中的prefetch支持:

  • 创建一个关键词集合,其中包含在您的集合中使用的常见单词(可能带有使用频率计数)。 您可以通过运行Map / Reduce跨您拥有文本搜索索引的集合来创建此集合,并使用定期的增量Map / Reduce来保持单词列表最新。

  • 让您的应用程序从关键词集合生成JSON文档,其中包含唯一的关键词(可能仅限于基于单词频率的“流行”关键词,以使列表易于管理/相关)。

然后,您可以使用生成的关键字JSON作为客户端自动完成的类型前瞻功能:

$('.mysearch .typeahead').typeahead({
  name: 'mysearch',
  prefetch: '/data/keywords.json'
});

typeahead.js会将prefetch JSON数据缓存在localStorage中,以供客户端搜索使用。当搜索表单提交时,您的应用程序可以使用服务器端MongoDB文本搜索按相关性顺序返回完整结果。


这比我想要的更费力,但是是一个不错的想法!谢谢 - KIC

4

我现在正在使用的一个简单解决方法是将文本分成单个字符,并将其存储为文本索引数组。

然后,当您执行$search查询时,只需再次将查询拆分为字符即可。

请注意,这仅适用于短字符串,长度小于32,否则索引构建过程将非常耗时,因此在插入新记录时性能会显著降低。


1
可能被踩是因为这个回答很少尝试解释解决方案的内容。没有提供如何实现所描述的内容的示例,只会引发更多问题和困惑。 - flash

1

我不知道这对一些面临这个问题的新手是否有用。

根据你的集合大小和可用的RAM,你可以通过创建适当的索引来使用$regex进行搜索。例如:

db.collection.find( {query : {$regex: /querywords/}}).sort({'criteria': -1}).limit(limit)

您需要如下索引:
db.collection.ensureIndex( { "query": 1, "criteria" : -1 } )

如果您有足够的内存,这可能会非常快。

希望这可以帮到您。


如果您不想从文本开头进行搜索,那么索引也不会被使用。在这种情况下,索引只是资源的浪费。 - Skarllot

1

对于那些尚未开始实施任何数据库架构并且正在寻找解决方案的人,请选择Elasticsearch。它是一种类似于MongoDB结构的JSON文档驱动型数据库。它具有“edge-ngram”分析器,非常高效快速地提供拼写错误搜索的建议。您还可以进行部分搜索。


1
您无法查询索引中的所有单词,但当然可以查询原始文档的字段。搜索索引中的单词通常也不是完整的单词,而是进行了词干处理。因此,您可能无法在索引中找到“blueberry”,而只能找到“blueberri”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接