什么时候应该在 mongo 中使用 $limit?

When should you use $limit in mongo?

嗯,这是一个技术性能问题:

我有这样的查询

db.collection.aggregate([
    {$match:{...}},
    {$group:{...}},
    {$group:{...}},
    {$project:{...}},
    {$sort:...}
])

但是如果我想设置限制,我在查询的最后使用 $limit

db.collection.aggregate([
    {$match:{...}},
    {$group:{...}},
    {$group:{...}},
    {$project:{...}},
    {$sort:...},
    {$limit : 10}
])

所以我的问题是什么是设置 $limit 的最佳方式:

我的 logic/mind 说 You should to use "$limit" after $match to limit first results because maybe Mongo execute first $match and after will get result to process the next query's($group, $group, $project, $sort, ...)

谢谢

P.S:我刚开始使用 Mongo。抱歉我的英语不好。

使用$limit时,具体要看具体情况。但是,最好尽快使用 $limit,但顺序通常很重要。在不太可能的情况下,您只需要 10 个随机文档,那么您可以在 $match 之后使用 $limit。但是,在您的情况下,您还使用了 $sort,这将影响您想要返回的 10 个对象;因此,您应该在 $sort 之后包含 $limit 除非您的聚合查询可以以您可以更早使用排序和限制的方式进行优化。

db.collection.aggregate([
  { $match: { ... } },
  // Will limit results exactly as they come, unsorted
  { $limit: 10 },
  { $group: {...}},
  { $group: {...}},
  { $project: {...}},
  { $sort: ...} // Will only sort the random 10
]);

db.collection.aggregate([
  { $match: { ... } },
  { $group: {...}},
  { $group: {...}},
  { $project: {...}},
  { $sort: ...}, // The sort likely matters, so limit after
  { $limit: 10 }
]);

但是,它可以四处移动的情况是您尽早排序,并且您只是在处理数据,这可能会在处理更少数据的情况下提高性能:

db.collection.aggregate([
  { $match: { ... } },
  { $group: {...}},
  { $group: {...}},
  { $sort: ...},
  { $limit: 10 },
  { $project: {...}} // Since we only change the data format, it won't affect our limit
]);

那么,为什么 $limit 在您提议的管道中排在最后?:

db.collection.aggregate([
    {"$match":{...}},
    {"$group":{...}},
    {"$group":{...}},
    {"$project":{...}},
    {"$sort":...},
    {"$limit": 10}
])

因为这正是它应该做的。

所以在 "pipeline" 的 "end" 是只返回 "last 10 results" 的地方。

这不像游标修饰符,操作发生 "sequentially" 因此 "limit" 发生在它被实现的阶段之后。

因此:

db.collection.aggregate([
   { "$limit": 10 },
   { .. whatever .. }
])

基本上只通过查看集合中的非常 "first" 10 个文档来控制,没有任何其他条件,不管管道在其余阶段说什么。

管道是 "pipeline"。想想"Unix Pipe |":

grep | sed | awk | sed | grep | awk

因为这正是它的作用。您 "feed" 所得到的就是您通过所执行的操作得到的 "out"。

因此,每个流水线阶段对其执行顺序都很重要。这个地方是有目的的,不可互换。