Reproduction in Mongo Playground

我有一个聚合管道,它包含一个$lookup阶段,然后是$match阶段,然后是$group阶段.

奇怪的是(至少对我来说),$match阶段输出一个文档(可以通过临时删除$group阶段来看到),而$group阶段之后输出零个文档.如果$group阶段有任何输入文档,我希望它始终至少有一个输出文档.为什么这里不是这样呢?

上面的Mongo操场链接重现了有问题的行为.

下面是不输出任何文档的聚合管道:

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
      }
    }
  }
]);

这是删除了小组赛阶段后的相同管道.它返回一个文档.

db.orders.aggregate([
  {
    "$lookup": {
      "from": "products",
      "localField": "products.0.productId",
      "foreignField": "_id",
      "as": "firstProduct"
    }
  },
  {
    "$match": {
      "firstProduct.0.name": "Apron"
    }
  }
]);

以下是这orders个Collection 中的内容:

[
  {
    "products": [
      {
        "productId": {
          "$oid": "00000001f1438712ca040fca"
        }
      }
    ]
  }
]

以下是这products个Collection 中的内容:

[
  {
    "name": "Apron",
    "_id": {
      "$oid": "00000001f1438712ca040fca"
    }
  }
]

MongoDB版本为6.0.4.我在4.4.19中也try 了,行为是相同的.

推荐答案

我可以在v5.0.2上看到相同的行为 当我看着解释计划时,每当你有小组赛阶段在筹备中,就会增加投影阶段.

"winningPlan" : {
    "stage" : "PROJECTION_DEFAULT",
    "transformBy" : {
        "firstProduct" : 1,
        "products.0.productId" : 1,
        "_id" : 0
    },
    "inputStage" : {
        "stage" : "COLLSCAN",
        "direction" : "forward"
    }
}

您可以通过在聚合查询中添加此阶段来重新创建问题.

db.orders.aggregate([
  {
    "$lookup": {
      "from": "products",
      "localField": "products.0.productId",
      "foreignField": "_id",
      "as": "firstProduct"
    }
  },
  {
    "$project": {
       "firstProduct" : 1,
       "products.0.productId" : 1,
       "_id" : 0
    }
  }
])

结果

{
    "products" : [ 
        {}
    ],
    "firstProduct" : []
}

我认为,指定0指数,是在暗地里搅乱一些乐观情绪.移除索引后,它的工作情况与预期一致.

db.orders.aggregate([
  {
    "$lookup": {
      "from": "products",
      "localField": "products.productId",
      "foreignField": "_id",
      "as": "firstProduct"
    }
  },
  {
    "$match": {
      "firstProduct.name": "Apron"
    }
  },
  {
    "$group": {
      "_id": null,
      "numOrders": {$sum: 1}
    }
  }
]);

Mongodb相关问答推荐

执行聚合以消除重复并获得唯一计数

mongoDB中数组中的聚合和元素

如何 db.getUser() 使用 go mongo-driver

MongoDB - 使用许多嵌套对象更新嵌套数组

Mongoose - $project 嵌套的对象数组到数组的根级别

MongoDB:如何将所有文档合并到聚合管道中的单个文档中

Mongoose 架构引用和未定义类型ObjectID

Meteor 如何接收对 MongoDB 查询结果的更新?

无法连接到mongolab主机

用 Redis 查询?

MongoDB 中 cursor.count() 和 cursor.size() 之间的区别

mongodb - 查找具有最接近整数值的文档

带有 jQ​​uery Ajax/JSON 前端的 MongoDB 或 CouchDB 中间件

MongoDB 中的所有列

插入违反唯一索引的 MongoDB 文档时如何捕获错误?

PyMongo 中的警告消息:count is deprecated

MongoTemplate upsert - 从 pojo 进行更新的简单方法(哪个用户已编辑)?

MongoDB:聚合框架: $match between fields

mongoose — 判断 ObjectId 是否存在于数组中

全局初始化失败:BadValue Invalid or no user locale set.请确保正确设置 LANG 和/或 LC_* 环境变量