MongoDB 按多个字段过滤文本搜索
MongoDB text search filter by multiple fields
我有以下文档结构。
{
content: 'cat dog bird',
uid: <another_unique_id>
cid: <another_unique_id>
}
我正在尝试搜索此集合并希望按 uid
and/or cid
筛选结果。我想要的一些查询 运行:
1) db.mycollection.find({uid: '1', cid: '2', $text: {$search: 'cat'}});
2) db.mycollection.find({cid: '2', $text: {$search: 'cat'}});
3) db.mycollection.find({uid: '1', $text: {$search: 'cat'}});
4) db.mycollection.find({$text: {$search: 'cat'}});
//etc...
我试过创建这样的复合索引
db.mycollection.ensureIndex({uid: 1, cid: 1, content: 'text'});
但它只适用于查询 #1,如果我不提供其中一个字段,我会收到以下错误。
planner returned error: failed to use text index to satisfy $text query
(if text index is compound, are equality predicates given for all prefix fields?)
我尝试的其他事情:
在 uid
/cid
上创建非复合索引 = 导致扫描大量文档
将 uid
cid
索引移动到文本索引之后,即
db.mycollection.ensureIndex({content: 'text', uid: 1, cid: 1});
与#1 相同,未使用 uid 和 cid 索引。
关于我正在尝试的信息:
http://docs.mongodb.org/manual/tutorial/limit-number-of-items-scanned-for-text-search/
我是不是遗漏了什么,或者 MongoDB 使用索引是不可能的?
不仅是预期的行为 completely documented,而且我还发现您的断言是错误的。在满足您指定条件的标准样品上,结果将如图所示。但首先是文档参考:
- If the compound text index includes keys preceding the text index key, to perform a $text search, the query predicate must include equality match conditions on the preceding keys.
然后有效查询的解释输出:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.mycollection",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"cid" : {
"$eq" : 2
}
},
{
"uid" : {
"$eq" : 1
}
},
{
"$text" : {
"$search" : "cat",
"$language" : ""
}
}
]
},
"winningPlan" : {
"stage" : "TEXT",
"indexPrefix" : {
"uid" : 1,
"cid" : 2
},
"indexName" : "uid_1_cid_1_content_text",
"parsedTextQuery" : {
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "trashbox",
"port" : 27017,
"version" : "3.0.0",
"gitVersion" : "a841fd6394365954886924a35076691b4d149168"
},
"ok" : 1
}
因此,如果您想发出与您实际创建的 "compound key" 具有不同模式并且符合明确指定的规则的查询,那么您可能还应该注意要点:
- A collection can have at most one text index.
所以在 "any form" 复合或其他中,如果您正在寻找 MongoDB 文本索引的多个定义,那么您不能这样做。这同样适用于 "geospatial" 索引,以及在 $or
expression, or a .sort()
之外的一般考虑,查询引擎一次只能 select 一个索引。
现代版本应该报告非常具体的行以及错误:
(if text index is compound, are equality predicates given for all prefix fields?)
因此 "all" 个字段是必需的,它们 "must be" 完全匹配,无需使用不等运算符。
如果您不打算 "always" 使用其他字段作为带有 "exact match" 条件的查询的一部分,那么您不能在文本搜索的同时形成复合索引。
我有以下文档结构。
{
content: 'cat dog bird',
uid: <another_unique_id>
cid: <another_unique_id>
}
我正在尝试搜索此集合并希望按 uid
and/or cid
筛选结果。我想要的一些查询 运行:
1) db.mycollection.find({uid: '1', cid: '2', $text: {$search: 'cat'}});
2) db.mycollection.find({cid: '2', $text: {$search: 'cat'}});
3) db.mycollection.find({uid: '1', $text: {$search: 'cat'}});
4) db.mycollection.find({$text: {$search: 'cat'}});
//etc...
我试过创建这样的复合索引
db.mycollection.ensureIndex({uid: 1, cid: 1, content: 'text'});
但它只适用于查询 #1,如果我不提供其中一个字段,我会收到以下错误。
planner returned error: failed to use text index to satisfy $text query
(if text index is compound, are equality predicates given for all prefix fields?)
我尝试的其他事情:
在
uid
/cid
上创建非复合索引 = 导致扫描大量文档将
uid
cid
索引移动到文本索引之后,即db.mycollection.ensureIndex({content: 'text', uid: 1, cid: 1});
与#1 相同,未使用 uid 和 cid 索引。
关于我正在尝试的信息: http://docs.mongodb.org/manual/tutorial/limit-number-of-items-scanned-for-text-search/
我是不是遗漏了什么,或者 MongoDB 使用索引是不可能的?
不仅是预期的行为 completely documented,而且我还发现您的断言是错误的。在满足您指定条件的标准样品上,结果将如图所示。但首先是文档参考:
- If the compound text index includes keys preceding the text index key, to perform a $text search, the query predicate must include equality match conditions on the preceding keys.
然后有效查询的解释输出:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.mycollection",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"cid" : {
"$eq" : 2
}
},
{
"uid" : {
"$eq" : 1
}
},
{
"$text" : {
"$search" : "cat",
"$language" : ""
}
}
]
},
"winningPlan" : {
"stage" : "TEXT",
"indexPrefix" : {
"uid" : 1,
"cid" : 2
},
"indexName" : "uid_1_cid_1_content_text",
"parsedTextQuery" : {
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "trashbox",
"port" : 27017,
"version" : "3.0.0",
"gitVersion" : "a841fd6394365954886924a35076691b4d149168"
},
"ok" : 1
}
因此,如果您想发出与您实际创建的 "compound key" 具有不同模式并且符合明确指定的规则的查询,那么您可能还应该注意要点:
- A collection can have at most one text index.
所以在 "any form" 复合或其他中,如果您正在寻找 MongoDB 文本索引的多个定义,那么您不能这样做。这同样适用于 "geospatial" 索引,以及在 $or
expression, or a .sort()
之外的一般考虑,查询引擎一次只能 select 一个索引。
现代版本应该报告非常具体的行以及错误:
(if text index is compound, are equality predicates given for all prefix fields?)
因此 "all" 个字段是必需的,它们 "must be" 完全匹配,无需使用不等运算符。
如果您不打算 "always" 使用其他字段作为带有 "exact match" 条件的查询的一部分,那么您不能在文本搜索的同时形成复合索引。