Mongodb 聚合框架中的$skip和$limit
当我阅读该文件时,我发现以下注释: 当$sort紧跟在管道中的$limit之前时,$sort操作只会在执行过程中维护前n个结果,其中n是指定的限制,MongoDB只需要在内存中存储n个项。当allowDiskUse为true且n项超过聚合内存限制时,此优化仍然适用 如果我对这一点是正确的,那么它只适用于同时使用$sort和$limit的情况,如Mongodb 聚合框架中的$skip和$limit,mongodb,aggregation-framework,Mongodb,Aggregation Framework,当我阅读该文件时,我发现以下注释: 当$sort紧跟在管道中的$limit之前时,$sort操作只会在执行过程中维护前n个结果,其中n是指定的限制,MongoDB只需要在内存中存储n个项。当allowDiskUse为true且n项超过聚合内存限制时,此优化仍然适用 如果我对这一点是正确的,那么它只适用于同时使用$sort和$limit的情况,如 db.coll.aggregate([ ..., {$sort: ...}, {$limit: limit}, ...
db.coll.aggregate([
...,
{$sort: ...},
{$limit: limit},
...
]);
然而,我想大多数时候我们会
db.coll.aggregate([
...,
{$sort: ...},
{$skip: skip},
{$limit: limit},
...
]);
问题1:如果我在此处使用$skip,是否意味着上述规则不适用
我问这个问题是因为理论上MongoDB仍然可以计算topn记录,并通过只排序topn记录来提高性能。但是我没有找到任何关于这个的文件。如果规则不适用
问题2:我是否需要将查询更改为以下内容以提高性能
db.coll.aggregate([
...,
{$sort: ...},
{$limit: skip + limit},
{$skip: skip},
{$limit: limit},
...
]);
编辑:我认为解释我的用例会使上述问题更有意义。我正在使用MongoDB 2.6提供的文本搜索功能查找产品。我担心如果用户输入一个非常常见的关键字,比如“red”,那么返回的结果会太多。因此,我正在寻找更好的方法来产生这个结果
EDIT2:上面的最后一个代码等于
db.coll.aggregate([
...,
{$sort: ...},
{$limit: skip + limit},
{$skip: skip},
...
]);
因此,我们可以始终使用此表单应用top n规则。由于这是我们正在讨论的文本搜索查询,因此最理想的表单如下:
db.collection.aggregate([
{
“$match”:{
“$text”:{“$search”:“蛋糕茶”}
}
},
{“$sort”:{“score”:{“$meta”:“textScore”}},
{“$limit”:跳过+限制},
{“$skip”:skip}
])
顶部“排序”结果中的内存保留的基本原理只能在其自身的“限制”范围内工作,这对于超出几个合理的数据“页面”的任何内容都不是最佳的
除了合理的内存消耗之外,额外的阶段可能会产生负面影响,而不是正面影响
这些实际上是MongoDB在当前形式下可用的文本搜索功能的实际限制。但是,对于任何更详细和需要更高性能的内容,就像许多SQL“全文”解决方案一样,最好使用外部“专门构建”的文本搜索解决方案。我发现
限制
和跳过
的顺序似乎无关紧要。如果我在limit
之前指定skip
,mongoDB将在skip
之前在引擎盖下设置limit
>db.system.profile.find().limit(1).sort({ts:-1}).pretty()
{
“op”:“命令”,
“ns”:“archiprod.userinfos”,
“命令”:{
“聚合”:“用户信息”,
“管道”:[
{
“$sort”:{
“updatedAt”:-1
}
},
{
“$限额”:625
},
{
“$skip”:600
}
],
},
“钥匙”:625,
“docsExamined”:625,
“cursorExhausted”:正确,
“努米菲尔德”:4,
“未回复”:25,
“米利斯”:25,
“计划摘要”:“IXSCAN{updatedAt:-1}”,
/*省略了一些字段*/
}
如果我切换$skip
和$limit
,会发生什么?在键检查
和文档检查
方面,我得到了相同的结果
>db.system.profile.find().limit(1).sort({ts:-1}).pretty()
{
“op”:“命令”,
“ns”:“archiprod.userinfos”,
“命令”:{
“聚合”:“用户信息”,
“管道”:[
{
“$sort”:{
“updatedAt”:-1
}
},
{
“$skip”:600
},
{
“$限额”:25
}
],
},
“钥匙”:625,
“docsExamined”:625,
“cursorExhausted”:正确,
“努米菲尔德”:5,
“未回复”:25,
“米利斯”:71岁,
“计划摘要”:“IXSCAN{updatedAt:-1}”,
}
然后我检查了查询的解释结果。我发现totalDocsExamined
已经625
处于limit
阶段
> db.userinfos.explain('executionStats').aggregate([ { "$sort" : { "updatedAt" : -1 } }, { "$limit" : 625 }, { "$skip" : 600 } ])
{
"stages" : [
{
"$cursor" : {
"sort" : {
"updatedAt" : -1
},
"limit" : NumberLong(625),
"queryPlanner" : {
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"updatedAt" : -1
},
"indexName" : "updatedAt_-1",
}
},
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 625,
"executionTimeMillis" : 22,
"totalKeysExamined" : 625,
"totalDocsExamined" : 625,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 625,
"executionTimeMillisEstimate" : 0,
"works" : 625,
"advanced" : 625,
"docsExamined" : 625,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 625,
"works" : 625,
"advanced" : 625,
"keyPattern" : {
"updatedAt" : -1
},
"indexName" : "updatedAt_-1",
"keysExamined" : 625,
}
}
}
}
},
{
"$skip" : NumberLong(600)
}
]
}
令人惊讶的是,我发现切换$skip
和$limit
会得到相同的explain
结果
> db.userinfos.explain('executionStats').aggregate([ { "$sort" : { "updatedAt" : -1 } }, { "$skip" : 600 }, { "$limit" : 25 } ])
{
"stages" : [
{
"$cursor" : {
"sort" : {
"updatedAt" : -1
},
"limit" : NumberLong(625),
"queryPlanner" : {
/* Omitted */
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 625,
"executionTimeMillis" : 31,
"totalKeysExamined" : 625,
"totalDocsExamined" : 625,
/* Omitted */
}
}
},
{
"$skip" : NumberLong(600)
}
]
}
如您所见,尽管我在
$limit
之前指定了$skip
,但在解释
结果中,它仍然是$limit
之前的$skip您在当前表单中所说的。您知道吗,是否正在进行增强MongoDB文本搜索的工作?关于将Solr与MongoDB结合使用,这里有一些很好的评论,@JohnBarça您寻求的答案实际上更“正式”,并且在性质上有点负载。无可否认,IMO MongoDB并没有试图成为一个“最优”的键/值存储,也没有像“数据库”那样尝试实现传统关系系统的所有功能。这一点的延伸是,通用“数据库”通常不会“进入”诸如“文本搜索”等专门领域。但这是一种观点,观点往往会发生变化。无论如何,用最有效的方法。我一直涉猎Mongo,非常喜欢某些功能。但我听到你在说什么。我是一个GIS爱好者,我喜欢已经完成的geojson功能和聚合空间增强功能,但就功能而言,离离开Postgres/Postgis还有很长的路要走。不过,我承认这是一个非常利基的领域。@JohnBarç;a我同意你们的看法。这只是一个临时解决方案,我可以用它快速和简单。我们确实想过集成一个搜索引擎。但直到