MongoDB $ text搜索如何工作?

时间:2018-12-06 13:13:42

标签: node.js mongodb mongoose mongodb-query

我在事件集合中插入了以下值

db.events.insert(
   [
     { _id: 1, name: "Amusement Ride", description: "Fun" },
     { _id: 2, name: "Walk in Mangroves", description: "Adventure" },
     { _id: 3, name: "Walking in Cypress", description: "Adventure" },
     { _id: 4, name: "Trek at Tikona", description: "Adventure" },
     { _id: 5, name: "Trekking at Tikona", description: "Adventure" }
   ]
)

我还通过以下方式创建了索引:

db.events.createIndex( { name: "text" } )

现在,当我执行以下查询(搜索-步行)时:

db.events.find({
    '$text': {
        '$search': 'Walk'
    },
})

我得到这些结果:

{ _id: 2, name: "Walk in Mangroves", description: "Adventure" },
{ _id: 3, name: "Walking in Cypress", description: "Adventure" }

但是当我搜索《迷航》时:

db.events.find({
    '$text': {
        '$search': 'Trek'
    },
})

我只有一个结果:

{ _id: 4, name: "Trek at Tikona", description: "Adventure" }

所以我的问题是为什么要这样做:

{ _id: 4, name: "Trek at Tikona", description: "Adventure" },
{ _id: 5, name: "Trekking at Tikona", description: "Adventure" }

当我搜索步行时,结果显示包含步行和步行的文档。但是,当我搜索“迷航”时,它只会得到包括“迷航”在内的文档,而该文档本应同时导致“迷航”和“迷航”

1 个答案:

答案 0 :(得分:2)

MongoDB文本搜索使用Snowball stemming library根据通用语言规则将单词简化为期望的词根形式(或 stem )。算法词干提取可以快速简化,但是语言具有会影响准确性的异常(例如不规则或矛盾的动词缀合模式)。 Snowball introduction很好地概述了算法词干的某些局限性。

您的walking示例源自walk并符合预期。

但是,您的示例trekking源自trekk,因此与您的搜索关键字trek不匹配。

您可以通过解释查询并查看parsedTextQuery信息(显示使用的词干搜索词)来确认这一点:

db.events.find({$text: {$search: 'Trekking'} }).explain().queryPlanner.winningPlan.parsedTextQuery
{
​   "terms" : [
​       "trekk"
​   ],
​   "negatedTerms" : [ ],
​   "phrases" : [ ],
​   "negatedPhrases" : [ ]
}

您还可以使用在线Snowball Demo或通过查找您喜欢的编程语言的Snowball库来检查预期的Snowball词干。

要解决通常可能会影响用例的异常,您可以考虑在文本索引中添加带有关键字的另一个字段来影响搜索结果。对于此示例,您将添加trek作为关键字,以使描述为trekking的事件也与您的搜索结果匹配。

还有其他更精确的变形方法,通常称为 lemmatization 。缩编算法更加复杂,并且开始进入natural language processing的领域。如果要在应用程序中实现更高级的文本搜索,可以使用许多开源(和商业)工具包,但是这些工具包超出了MongoDB文本搜索功能的当前范围。