为提高效率,Mongo文档建议限制语句紧跟在排序语句之后,最终会有点荒谬:
collection.find(f).sort(s).limit(l).skip(p)
我说这有点荒谬,因为它似乎说先拿l项,然后放下那些l的第一个p。由于p通常大于l,你认为最终没有结果,但实际上你最终会得到l结果。
聚合比你期望的更多:
collection.aggregate({$unwind: u}, {$group: g},{$match: f}, {$sort: s}, {$limit: l}, {$skip: p})
如果p> gt; = l。,则返回0结果
collection.aggregate({$unwind: u}, {$group: g}, {$match: f}, {$sort: s}, {$skip: p}, {$limit: l})
有效,但文档似乎暗示如果匹配返回的结果集大于工作内存,则会失败。这是真的?如果是这样,是否有更好的方法对通过聚合返回的结果集执行分页?
来源:本页末尾的“版本2.4更改”评论:http://docs.mongodb.org/manual/reference/operator/aggregation/sort/
答案 0 :(得分:10)
在MongoDB游标方法(即使用find()
时)limit
,sort
,skip
可以按任意顺序应用=>订单没关系。 find()
返回应用了修改的游标。排序总是在限制之前完成,跳过也在限制之前完成。换句话说,订单是: sort - >跳过 - >限强>
聚合框架不返回数据库游标。相反,它返回带有聚合结果的文档。它的工作原理是在管道的每个步骤产生中间结果,因此操作顺序非常重要。
我猜MongoDB不支持游标修饰符方法的顺序,因为它在内部实现的方式。
您无法对聚合框架的结果进行分页,因为只有一个文档只包含结果。您仍然可以使用跳过和限制对常规查询进行分页,但更好的做法是使用范围查询,因为它使用索引的效率。
<强>更新强>
答案 1 :(得分:1)
文档似乎暗示如果匹配返回的结果集大于工作内存,则此(聚合)将失败。这是真的吗?
没有。例如,您可以在不使用$match
运算符的情况下聚合大于物理内存的集合。它可能很慢,但它应该工作。如果$match
返回大于RAM的内容,则没有问题。
以下是实际的管道限制。
http://docs.mongodb.org/manual/core/aggregation-pipeline-limits/
$match
运算符不会导致内存问题。如文档中所述,$group
和$sort
是常见的恶棍。它们是累积的,可能需要访问整个输入集才能生成任何输出。如果他们将太多数据加载到物理内存中,它们将会失败。
如果是这样,是否有更好的方法对通过聚合返回的结果集执行分页?
我已经正确地说你不能“聚合”(应用$skip
和$limit
)聚合的结果,因为它只是一个MongoDB文档。但是您可以对聚合管道的中间结果进行“分页”。
在管道上使用$limit
将有助于将结果集保持在16 MB边界内,即最大BSON文档大小。即使收集增长,你也应该是安全的。
$group
可能会出现问题,特别是$sort
。如果实际发生,您可以创建“排序友好”索引来处理它们。看看有关索引策略的文档。
http://docs.mongodb.org/manual/tutorial/sort-results-with-indexes/
最后,请注意$skip
对性能没有帮助。相反,它们往往会减慢应用程序的速度,因为它会强制MongoDB扫描每个跳过的文档以达到集合中的所需点。
http://docs.mongodb.org/manual/reference/method/cursor.skip/
答案 2 :(得分:0)
$sort preceding $limit的MongoDB建议是绝对正确的,因为它会在发生前n个结果时优化执行该操作所需的内存。
仅仅是您提出的解决方案不适合您的用例,即分页。
您可以修改查询以从此优化中受益。
collection.aggregate([
{
$unwind: u
},
{
$group: g
},
{
$match: f
},
{
$sort: s
},
{
$limit: l+p
},
{
$skip: p
}
]);
或用于find
查询
collection.find(f).sort(s).limit(l+p).skip(p)
尽管如此,您可以看到分页较大,即使进行了这种优化,内存也会越来越多。