mongodb排序和regex查询
mongodb sort and regex query in efficient way
db.location.find(
{ "$or": [
{ "country_lc": /^unit/, "docType": "country" },
{ "region_lc": /^unit/, "docType": "region" },
{ "city_lc": /^unit/, "docType": "city" }
]},
{ "country": 1, "region": 1, "city": 1, "docType" :1 }
).sort({ "country_lc" :1, "region_lc": 1, "city_lc":1 })
monodb中的这个is查询花费了很多时间。如何有效地查询?下面是上面查询的explain((输出。我在收集地点总共有442161份文件。我必须做一些前缀搜索。我已经在(country_lc,docType(、(region_lc,docType(、(city_lc,docType。我的mongo版本是2.4.9。
{
"cursor" : "BtreeCursor country_lc_1_region_lc_1_city_lc_1",
"isMultiKey" : false,
"n" : 29,
"nscannedObjects" : 76935,
"nscanned" : 442161,
"nscannedObjectsAllPlans" : 76935,
"nscannedAllPlans" : 442161,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 79,
"nChunkSkips" : 0,
"millis" : 81531,
"indexBounds" : {
"country_lc" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"region_lc" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"city_lc" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "prashanta:27017"
}
您可以尝试在country_lc
、region_lc
和city_lc
字段上创建文本索引:
db.reviews.ensureIndex( { "country_lc": "text" } )
db.reviews.ensureIndex( { "region_lc": "text" } )
db.reviews.ensureIndex( { "city_lc": "text" } )
文本索引是MongoDB 2.4中的一个新功能。添加它们是为了支持对集合文档中的字符串内容进行文本搜索。有关性能提示,请查看官方文档。
此外,您可以尝试将查询重写为
db.location.find(
{ "docType": {"$in": [ "country", "region", "city" ]},
"$or": [
{ "country_lc": /^unit/ },
{ "region_lc": /^unit/ },
{ "city_lc": /^unit/ },
]
},
{ "country": 1, "region": 1, "city": 1, "docType" :1 }
).sort({ "country_lc" :1, "region_lc": 1, "city_lc":1 })
(注意:根据文档的结构,这等同于或不等同于您的查询。(
现在我碰巧知道你正在运行2.4.9,这意味着你没有索引分区,$or
不能使用排序索引。这个答案可能与2.6中的答案不同。
您的查询存在多个问题,在MongoDB中,除了regex之外,它被认为是一个"坏"查询。
好的,让我们进行排序,在2.4.9中,$or
上的排序将不会正确使用索引(https://jira.mongodb.org/browse/SERVER-1205(,这意味着你没有scanAndOrder
,但你有一个nscanned
计数,它是你收藏大小的数倍。
nscanned
准确地说是442161,因为$or
实际上是运行许多查询(http://docs.mongodb.org/manual/reference/operator/query/or/#or-子句和索引(,同时其结果被合并然后返回,即使在2.4.9中,您也可以在$or
上使用多个索引中看到这一证明。
我看不出你的子句使用了什么索引,但我认为这些索引可能也不适合索引。
问题是2.4.9根本无法执行$or
并使用适当的索引进行排序。您必须在为$or
建立索引或排序之间进行选择,即使这样也只能部分覆盖查询。
你可以做一些事情来解决这个问题:
- 升级至2.6,其中
$or
和sort可以使用索引 - 即使在2.6中,由于添加了
docType
字段,您也可能会遇到问题。您可以尝试在country_lc
之后立即将其添加到索引中,但也可以将其添加在索引末尾,它会正常工作,但请记住,它会扫描country_lc
中匹配项下方的所有条目 - 您可能可以利用2.6中的索引intersection来解决每个或子句的这个问题,但正如文档所述(http://docs.mongodb.org/manual/reference/operator/query/or/#or-和排序操作(
$or
特定的索引将被删除,所以我认为这不会起作用
无论以何种方式摇动它,这都是一个可怕的查询,它总是会导致完整的集合扫描,或者至少是完整的索引扫描。
只需在这一份文件上:
{
"country_lc" : "unitize",
"region_lc" : "unitmost",
"city_lc" : "unitleast"
}
查询不可能锚定在索引中的任何位置,因为无论您如何组织作为索引的字段的顺序,由于$or
运算符的"排他性"(如排除所有内容(性质,它们都不会匹配。
因此,这些方法或其他组合都不会真正包含一个索引:
db.location.ensureIndex({
"country_lc" : 1,
"region_lc" : 1,
"city_lc" : 1
})
db.location.ensureIndex({
"region_lc" : 1,
"city_lc" : 1,
"country_lc" : 1
})
db.location.ensureIndex({
"region_lc" : 1,
"country_lc" : 1,
"city_lc" : 1
})
即使您.hint()
查询,它也不可能找到范围,这也是由于"排他性"性质:
db.location.find(
{ "$or": [
{ "country_lc": /^unit/ },
{ "region_lc": /^unit/ },
{ "city_lc": /^unit/ }
]}
).hint(
{ country_lc: 1, region_lc: 1, city_lc: 1 }
).explain()
我所能想到的是,你实际上并不是指"以‘单位’开头的单词",而是指其他的意思。
这不仅仅是MongoDB的事情,这对任何数据库引擎来说都是一件可怕的事情。
你可能真的想要一个专门的"文本搜索"引擎。
编辑
有些人发布了不知情的回复,所以我想我会实际发布建议查询的解释输出:
{
"cursor" : "BtreeCursor country_lc_1_region_lc_1_city_lc_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"country_lc" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"region_lc" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"city_lc" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "ubuntu:27017",
"filterSet" : false
}
这清楚地表明,即使选择了索引,也不可能匹配索引范围内的任何内容。
关于已经做出的错误评论,这个查询解释响应来自MongoDB的2.6版本。并且也在当前的夜间构建中进行了复制。
- 内部分区字体大小获胜'调整浏览器窗口大小时不会随媒体查询而更改
- RegEx删除空属性?例如,如果(class=“”||class=“”)移除;否则就下课
- Regex代码只允许一个空格
- j查询utc offSets的时差
- Regex匹配除“”之外的所有字符;.js”;
- RegExp:匹配Javascript中除regex值之外的所有内容
- 如何有效地将游戏数据存储在URL查询字符串中
- Javascript RegEx validator
- 如何处理node.js节点mongodb中的连接和查询队列
- 使用regex的jquery keydown绑定不会验证撇号和句点
- 如何从 HTML 查询中删除项目
- 从查询字符串参数推断出正确的数据类型
- 将curl查询转换为jQuery.ajax()
- Datatables查询url字符串:需要regex来修复url解析
- 如何在php和javascript中使用regex检测空格分隔词(在全文搜索查询中)
- 使用regex-unicode的mysql查询
- Regex将特定URL与查询字符串匹配
- sequelizejs,使用RegEx进行查询
- Regex-获取不带哈希的查询字符串
- mongodb排序和regex查询