是否可以指定Mongo文本搜索分隔符?

时间:2019-09-11 20:19:45

标签: mongodb

问题简介

我希望从包含大约1000万个条目的集合中返回最匹配的Mongo文档。我在集合上有一个文本索引,跨越多个字段(firstName,lastName,id等)。 ID的格式为#-###-###

我发现,当为这些ID ${search: '"1-234-567"'}指定一个确切的短语时,我确实收到了正确的文档,但是性能却损失了大约60秒钟以上。另一方面,如果删除搜索的连字符${search: '"1234567"'},结果将立即返回。

诊断

我相信这是因为Mongo用连字号分隔了我的查询(即使短语被加了引号),也许第二个过滤器正在确保我只得到完全匹配。这似乎可以通过查询解释来证明:

带连字符的搜索

db.person.find({$text: {$search: '"1-234-567"'}}, { score: { $meta: "textScore" } }).limit(1).sort({ score: { $meta: "textScore" } }).explain()
{
        ...
                        "indexName" : "Person_TextIndex",
                        "parsedTextQuery" : {
                            "terms" : [
                                "1",
                                "234",
                                "567"
                            ],
                            "negatedTerms" : [ ],
                            "phrases" : [
                                "1-234-567"
                            ],
                            "negatedPhrases" : [ ]
                        },
        ...
}

非连字符搜索

db.person.find({$text: {$search: '"1234567"'}}, { score: { $meta: "textScore" } }).limit(1).sort({ score: { $meta: "textScore" } }).explain()
{
        ...
                        "indexName" : "Person_TextIndex",
                        "parsedTextQuery" : {
                            "terms" : [
                                "1234567"
                            ],
                            "negatedTerms" : [ ],
                            "phrases" : [
                                "1234567"
                            ],
                            "negatedPhrases" : [ ]
                        },
        ...
}

请注意连字搜索中的术语数组。我相信,在最终给我正确的文档之前,这将筛选出匹配“ 1”,“ 234”,“ 567”的文档。

潜在解决方案

我真的不能在该字段上添加常规索引,因为搜索功能又应该包含多个字段。我真正想做的是指定我不希望对搜索字符串进行标记化/定界。那可能吗?还有其他方法吗?

1 个答案:

答案 0 :(得分:0)

mongo中的文本索引使用定界符,空格,连字符,破折号被视为定界符。您可以从程序中处理它,并将查询中正确的文本传递给mongodb

https://books.google.com.sg/books?id=JkBPDwAAQBAJ&pg=PA155&lpg=PA155&dq=Tokenization+Delimiters%2Bmongodb&source=bl&ots=OXjjadWjMD&sig=ACfU3U1U02DeKS-Gchx92f-hJ0HErCdCzA&hl=en&sa=X&ved=2ahUKEwiHzo26s8rkAhUTgUsFHd2OAicQ6AEwDXoECAkQAQ#v=onepage&q=Tokenization%20Delimiters%2Bmongodb&f=false

OR

将该短语用转义的双引号引起来:

db.testsearch.find({"$text" : {"$search" : "\"a@b\""}})