Aur*_*ast 5 mongodb aggregation-framework
我有一个聚合管道,其中包含一个$lookup阶段,然后是一个$match阶段,然后是一个$group阶段。
奇怪的是(无论如何对我来说),虽然$match阶段输出一个文档(可以通过暂时删除$group阶段来看到),但$group它之后的阶段输出零个文档。如果一个$group阶段有任何输入文档,我希望它始终至少有一个输出文档。为什么这里的情况不是这样呢?
上面的 Mongo Playground 链接重现了相关行为。
这是输出零文档的聚合管道:
db.orders.aggregate([
{
"$lookup": {
"from": "products",
"localField": "products.0.productId",
"foreignField": "_id",
"as": "firstProduct"
}
},
{
"$match": {
"firstProduct.0.name": "Apron"
}
},
{
"$group": {
"_id": null,
"numOrders": {
$sum: 1
}
}
}
]);
Run Code Online (Sandbox Code Playgroud)
这是删除了小组赛阶段的相同流程。它返回一份文档。
db.orders.aggregate([
{
"$lookup": {
"from": "products",
"localField": "products.0.productId",
"foreignField": "_id",
"as": "firstProduct"
}
},
{
"$match": {
"firstProduct.0.name": "Apron"
}
}
]);
Run Code Online (Sandbox Code Playgroud)
以下是合集内容orders:
[
{
"products": [
{
"productId": {
"$oid": "00000001f1438712ca040fca"
}
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
以下是合集内容products:
[
{
"name": "Apron",
"_id": {
"$oid": "00000001f1438712ca040fca"
}
}
]
Run Code Online (Sandbox Code Playgroud)
MongoDB 版本是 6.0.4。我也在 4.4.19 中尝试过,行为是相同的。
我可以在 v5.0.2 上看到相同的行为,当我查看解释计划时,只要管道中存在小组阶段,就会添加投影阶段。
"winningPlan" : {
"stage" : "PROJECTION_DEFAULT",
"transformBy" : {
"firstProduct" : 1,
"products.0.productId" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "COLLSCAN",
"direction" : "forward"
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过在聚合查询中添加此阶段来重新创建问题。
db.orders.aggregate([
{
"$lookup": {
"from": "products",
"localField": "products.0.productId",
"foreignField": "_id",
"as": "firstProduct"
}
},
{
"$project": {
"firstProduct" : 1,
"products.0.productId" : 1,
"_id" : 0
}
}
])
Run Code Online (Sandbox Code Playgroud)
结果
{
"products" : [
{}
],
"firstProduct" : []
}
Run Code Online (Sandbox Code Playgroud)
我认为,指定 0 索引会扰乱底层的一些优化。删除索引后,它按预期工作。
db.orders.aggregate([
{
"$lookup": {
"from": "products",
"localField": "products.productId",
"foreignField": "_id",
"as": "firstProduct"
}
},
{
"$match": {
"firstProduct.name": "Apron"
}
},
{
"$group": {
"_id": null,
"numOrders": {$sum: 1}
}
}
]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
95 次 |
| 最近记录: |