问题简介
我希望从包含大约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”的文档。
潜在解决方案
我真的不能在该字段上添加常规索引,因为搜索功能又应该包含多个字段。我真正想做的是指定我不希望对搜索字符串进行标记化/定界。那可能吗?还有其他方法吗?
答案 0 :(得分:0)
mongo中的文本索引使用定界符,空格,连字符,破折号被视为定界符。您可以从程序中处理它,并将查询中正确的文本传递给mongodb
OR
将该短语用转义的双引号引起来:
db.testsearch.find({"$text" : {"$search" : "\"a@b\""}})