【问题标题】:When should you use $limit in mongo?什么时候应该在 mongo 中使用 $limit?
【发布时间】:2023-04-04 12:52:01
【问题描述】:

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

我有这样的查询

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

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

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

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

  • 咨询开始时。
  • 咨询结束时。
  • 在咨询的任何部分:顺序并不重要。

我的逻辑/头脑说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 的位置取决于您的需求。想想“Unix管道|”:sed | grep | awk | grep | sed等等。这取决于“您在哪里需要它”。
  • 那和我想的一样:要看我想在哪里影响限制,优先考虑句子的顺序。如果我想要 10 个结果,最好在 $match 之后使用它,因为 $group 只会对咨询的原始结果进行分组/编辑。然后,如果需要,您可以在 $group 中重用 $limit。显然,这是一个重要的顺序问题。
  • 你需要先真正了解“管道”原理。执行顺序成其他。不回头,不修改。进去的东西出来,通常会改变。这就是重点。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

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

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

因为这正是它应该做的。

所以在“管道”的“末端”是只返回“最后 10 个结果”的地方。

这不像游标修饰符,操作“顺序”发生,因此“限制”发生在它实施的阶段之后。

因此:

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

基本上通过仅查看集合中最“前”的 10 个文档作为检索而没有任何其他条件来控制,无论管道在剩余阶段说什么。

管道是“管道”。想想“Unix管道|”:

grep | sed | awk | sed | grep | awk

因为正是它的作用。您“输入”的内容就是您通过执行的操作“输出”的内容。

因此,每个管道阶段对于它的执行顺序都很重要。这个地方是有目的的,不可互换。

【讨论】:

    【解决方案2】:

    在使用$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
    ]);
    

    【讨论】:

    • @BlakesSeven:我认为您误解了这个答案。对我来说,他说的和你说的一样。
    • @BlakesSeven:嗯,唯一的观察方法是带一些新人并让他们接受这个答案。 :)
    • @BlakesSeven 一个更有成效的评论将与改进答案和具体解决问题有关,而不是说我什么都不知道,当你明显不明白我在说什么时你什么都知道。
    • @BlakesSeven:你说得有道理。经过一些改写,这个问题看起来像一个参考问题,因此值得一个好的答案。但阿森纳在这里,他也是对的。批评而不提出改进意见几乎没有建设性。
    • SO 的设计是把最好的答案冒出来,让剩下的下沉。评论是有建设性的,如果没有什么建设性的话,投你的票,试着写一个更好的答案。谢谢@SergioTulentsev
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2011-04-15
    • 2017-04-10
    • 2012-03-19
    • 2018-05-12
    • 2018-12-11
    • 1970-01-01
    相关资源
    最近更新 更多