mongodb - 在 MongoDB 的聚合管道中使用阶段之间的投影是否有内存性能优势?
问题描述
一个集合可能有多个列,每个列都包含大量数据,如文章内容或图像数据等。
在使用聚合管道阶段时,我认为使用投影修剪字段会有好处,因此我们只将所需字段传递到后续阶段以帮助内存使用。
一个简单的例子:我们需要从一个集合中找到所有articles
没有匹配作者的人。authors
我会假设我们不会再投射不必要的文章字段。与$lookup
我们只需要和 id 为此目的的作者相同。演示:
db.getCollection("articles").aggregate(
[
{
$match: {
somecolumn: { "$ne": null, $exists: true }
}
},
{
$project: {
id: 1,
authorId: 1
}
},
{
$lookup: {
from: "authors",
let: { author: "$authorId" },
pipeline: [
{
$match: {
$expr:
{
$eq: ["$$author","$id"] }
}
},
{ $project: { id: 1, } }
],
as: "author"
}
},
{
$match: {
"author.0": {$exists: false}
}
}
]
);
我的这个假设是正确的,还是内部流程的工作方式不同?
解决方案
通常,您唯一希望拥有 $project 的地方是作为最后一个阶段,以便仅将所需的字段返回给客户端,在某些情况下可能会重命名或重新计算它们。
您不需要在管道中更早地使用 $project 来“修剪字段”,因为聚合已经进行了依赖性分析并且只获取管道中需要的字段。
这是一个示例,通过以下方式显示explain
:
db.foo.explain().aggregate({$group:{_id:"$fieldA", count:{$sum:1}}})
{
"stages" : [
{
"$cursor" : {
"query" : {
},
"fields" : {
"fieldA" : 1,
"_id" : 0
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "snv.foo",
"indexFilterSet" : false,
"parsedQuery" : {
},
"winningPlan" : {
"stage" : "EOF"
},
"rejectedPlans" : [ ]
}
}
},
{
"$group" : {
"_id" : "$fieldA",
"count" : {
"$sum" : {
"$const" : 1
}
}
}
}
]
}
即使我没有投影,您也可以看到只有fieldA
返回到管道的其余部分。
唯一需要添加早期$project
阶段的场景是解决聚合自身依赖关系分析中的错误或限制,但应常规避免。
推荐阅读
- python - 打印简单图的功能
- javascript - Checkmarx says document.url is unsafe
- sql - 引用父别名时将外部应用转换为左连接
- ios - 如何获得本地化的字母 Swift iOS
- php - PHP exec命令不适用于ImageMagick
- python - 如何遍历数据框,添加 3 个特定行,用它们的总和替换这 3 行,然后每 57 行重复一次?
- python - 我想用python开发一个谈话程序
- javascript - 将对象的属性和值提取到新对象中
- html - 文档为空( lxml.etree.ParserError: Document is empty )
- python - 序列上的迭代器