MongoDB聚合框架的解释

152

在MongoDB的聚合框架中是否有解释函数?我在文档中找不到。

如果没有,还有其他方法可以检查查询在聚合框架中的性能吗?

我知道对于find,你只需要执行

db.collection.find().explain()

但是使用聚合框架时,我收到了一个错误

db.collection.aggregate(
    { $project : { "Tags._id" : 1 }},
    { $unwind : "$Tags" },
    { $match: {$or: [{"Tags._id":"tag1"},{"Tags._id":"tag2"}]}},
    { 
        $group: 
        { 
            _id : { id: "$_id"},
            "count": { $sum:1 } 
        }
    },
    { $sort: {"count":-1}}
).explain()
3个回答

228
从MongoDB 3.0版本开始,只需将顺序更改为
collection.aggregate(...).explain()

collection.explain().aggregate(...)

我会给你想要的结果(文档在这里)。

对于版本号大于等于2.6的旧版本,你需要使用聚合管道操作的explain选项

explain:true

db.collection.aggregate([
    { $project : { "Tags._id" : 1 }},
    { $unwind : "$Tags" },
    { $match: {$or: [{"Tags._id":"tag1"},{"Tags._id":"tag2"}]}},
    { $group: { 
        _id : "$_id",
        count: { $sum:1 } 
    }},
    {$sort: {"count":-1}}
  ],
  {
    explain:true
  }
)

重要的一点是,聚合框架只能用于获取管道初始数据的索引(例如在管道开头使用 $match、$sort、$geonear),以及后续的 $lookup 和 $graphLookup 阶段。一旦数据已经被获取到聚合管道中进行处理(例如通过 $project、$unwind 和 $group 等阶段),进一步的操作将在内存中进行(如果设置了 allowDiskUse 选项,则可能使用临时文件)。
优化管道
通常,您可以通过以下方式优化聚合管道:
  • 使用$match阶段启动管道以将处理限制为相关文档。
  • 确保初始的$match / $sort阶段由高效索引支持。
  • 使用$match$limit$skip尽早过滤数据。
  • 最小化不必要的阶段和文档操作(如果需要复杂的聚合操作,则可以重新考虑模式)。
  • 利用较新的聚合运算符,如果您已升级MongoDB服务器。例如,MongoDB 3.4添加了许多新的聚合阶段和表达式,包括支持数组、字符串和特征。

还有一些聚合管道优化,根据您的MongoDB服务器版本自动发生。例如,相邻的阶段可能会合并和/或重新排序,以提高执行效率而不影响输出结果。

限制

截至MongoDB 3.4版本,聚合框架explain选项提供了有关管道处理方式的信息,但不支持与find()查询的executionStats模式相同级别的详细信息。如果您专注于优化初始查询执行,您可能会发现检查具有executionStatsallPlansExecution冗长度的等效find().explain()查询是有益的。

在MongoDB问题跟踪器中需要关注/点赞几个相关的功能请求,以帮助优化/分析聚合管道的更详细的执行统计信息:


谢谢提供信息,我会看看能否做出任何更改。 - SCB
$sort 对象不应该在管道数组内吗? - JohnnyHK
@JohnnyHK:是的,一些好心人正在“错误地”更正答案 :)。 - Stennie
但是这并没有提供“executionStats”。 - Kanagavelu Sugumar
1
@KanagaveluSugumar 我已更新答案,澄清了聚合框架中“explain”限制以及相关功能请求以获取额外的执行统计信息。 - Stennie
上述限制已在3.6中得到解决,因此您现在可以发出像“db.price_per_minute.explain("executionStats").aggregate(["...的查询。 - Robert Walters

30

从版本2.6.x开始,MongoDB允许用户使用聚合框架进行解释(explain)

你只需要添加 explain : true即可。

db.records.aggregate(
  [ ...your pipeline...],
  { explain: true }
)

多亏了Rafa的指导,我知道即使在2.4版本中也可以做到这一点,但只能通过runCommand()。但现在你也可以使用聚合功能。


6
自 MongoDB 2.2 版本以来,您可以使用 db.collection.runCommand('aggregate', {pipeline: [PIPELINE], explain: true}) 来解释聚合操作。该操作能够使您更好地理解 MongoDB 中的聚合查询。请注意,此操作不会改变原始意思。 - Rafa Viotti
1
你说得对,在2.2和2.4中,只能通过runCommand来解释聚合。感谢您的支持。 - Rafa Viotti
3
虽然在2.6之前的版本中,可以通过runCommand选项来实现该功能,但这种方法不能保证产生正确的结果,因此不应被推荐使用。你真正应该只在2.5.3或更新版本中使用它(并且要预计在2.6正式发布之前可能仍会存在一些潜在的漏洞)。 - Stennie

23

聚合框架

聚合框架是 MongoDB 中的一组分析工具,允许我们对一个或多个集合中的文档运行各种类型的报告或分析。基于管道的思想,我们从一个 MongoDB 集合中获取输入,并将该集合中的文档通过一个或多个阶段传递,每个阶段执行不同的操作。每个阶段将上一个阶段产生的输出作为其输入。所有阶段的输入和输出都是一系列文档流。每个阶段都有特定的任务。期望接收特定格式的文档并生成某些输出,这本身也是一系列文档流。在管道的末尾,我们可以访问输出。

聚合框架阶段

单个阶段是一个数据处理单元。每个阶段以一个文档流为输入,逐个处理每个文档,并产生输出文档流,同样一个接一个。每个阶段提供一组旋钮或调整器,我们可以控制它们来参数化阶段以执行我们感兴趣的任务。因此,一个阶段执行一项通用任务 - 某种通用目的的任务,并为我们正在使用的特定文档集参数化阶段。我们可以使用这些调整器来修改字段、执行算术运算、重塑文档或执行某些累积任务以及其他各种事情。通常情况下,我们会在单个管道中多次包含相同类型的阶段。

在单个管道中多次包含相同类型的阶段

例如,我们可能希望进行初始筛选,以便不必将整个集合传递到我们的管道中。但是,随后经过一些附加处理后,又想使用不同的标准再次进行筛选。因此,简要概括一下,管道与 MongoDB 集合一起工作。它们由多个阶段组成,每个阶段在其输入上执行不同的数据处理任务,并生成文档作为输出传递到下一个阶段。最终,在管道的末尾产生输出,我们可以在应用程序中执行某些操作。在许多情况下,需要在单个管道中多次包含相同类型的阶段。


谢谢,这很有帮助,让我更好地理解了。 - Arun Pratap Singh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接