如何将查询写入 $lookup、$group 和 $sum 以显示带有输入文档的输出

How to write a query to $lookup, $group and $sum to show the output with input document

我有 2 个集合 collection1 和 collection2。我想查找两个表并对数量进行分组和求和。我尝试在集合 2 中分组并使用集合 1 进行查找,但没有正确获取输出文档。请帮忙找出这个问题。

//collection 1
{
     _id: 1,
     name: Product1,
     units: 20
},
{
     _id: 2,
     name: Product2,
     units: 10
},
{
     _id: 3,
     name: Product3,
     units: 50
},
{
     _id: 4,
     name: Product4,
     units: 4
}

//collection2
{
     _id2: 1,
    inventory: 1, //foreign key
     quantity: 20,
},
{
     _id2: 2,
     inventory: 1 //foreign key
     quantity: 10
},
{
     _id2: 3,
    inventory: 1 //foreign key
     quantity: 50
},
{
     _id2: 4,
    inventory: 2 //foreign key
     quantity: 4
},
{
     _id2: 5,
     inventory: 2 //foreign key
     quantity: 45
},
{
     _id2: 6,
     inventory: 3 //foreign key
     quantity: 49
},

如何编写查询以获得像这样的 collection1 数据的输出

{
     _id1: 1,
     name: Product1,
     units: 20,
     inventoryList: [quantity: 80]
},
{
     _id1: 2,
     name: Product2,
     units: 10,
     inventoryList: [quantity: 49]
},
{
     _id1: 3,
     name: Product3,
     units: 50,
     inventoryList: [quantity: 49]
},
{
     _id1: 4,
     name: Product4,
     units: 4,
     inventoryList: [quantity: 0]
}

解决方案 #1:

db.collection1.aggregate([
    {
        $lookup: {
            from: "collection2",
            localField: "_id",
            foreignField: "inventory",
            as: "inventoryList"
        }
    },
    {
        $addFields: {
            inventoryList: {
                $reduce: {
                    input: "$inventoryList",
                    initialValue: 0,
                    in: {
                        $sum: ["$$value", "$$this.quantity"]
                    }
                }
            }
        }
    }
]);

解决方案#2:正如@turivishal 在以下评论中所建议的那样。

db.collection1.aggregate([
    {
        $lookup: {
            from: "collection2",
            localField: "_id",
            foreignField: "inventory",
            as: "inventoryList"
        }
    },
    {
        $addFields: {
            inventoryList: { $sum: "$inventoryList.quantity" }
        }
    }
]);

输出:

/* 1 */
{
    "_id" : 1,
    "name" : "Product1",
    "units" : 20,
    "inventoryList" : 80
},

/* 2 */
{
    "_id" : 2,
    "name" : "Product2",
    "units" : 10,
    "inventoryList" : 49
},

/* 3 */
{
    "_id" : 3,
    "name" : "Product3",
    "units" : 50,
    "inventoryList" : 49
},

/* 4 */
{
    "_id" : 4,
    "name" : "Product4",
    "units" : 4,
    "inventoryList" : 0
}

解决方案 3:如果您希望它完全符合您的预期输出:

db.collection1.aggregate([
    {
        $lookup: {
            from: "collection2",
            localField: "_id",
            foreignField: "inventory",
            as: "inventoryList"
        }
    },
    {
        $addFields: {
            inventoryList: [{ quantity: { $sum: "$inventoryList.quantity" } }]
        }
    }
]);

输出:

/* 1 */
{
    "_id" : 1,
    "name" : "Product1",
    "units" : 20,
    "inventoryList" : [
        {
            "quantity" : 80
        }
    ]
},

/* 2 */
{
    "_id" : 2,
    "name" : "Product2",
    "units" : 10,
    "inventoryList" : [
        {
            "quantity" : 49
        }
    ]
},

/* 3 */
{
    "_id" : 3,
    "name" : "Product3",
    "units" : 50,
    "inventoryList" : [
        {
            "quantity" : 49
        }
    ]
},

/* 4 */
{
    "_id" : 4,
    "name" : "Product4",
    "units" : 4,
    "inventoryList" : [
        {
            "quantity" : 0
        }
    ]
}

您可以尝试使用管道查找,

  • 允许传递库存id和匹配表达式条件
  • $group by null 和 sum quantity
db.col1.aggregate([
  {
    $lookup: {
      from: "col2",
      let: { inventory: "$_id" },
      pipeline: [
        {
          $match: {
            $expr: { $eq: ["$$inventory", "$inventory"] }
          }
        },
        {
          $group: {
            _id: null,
            quantity: { $sum: "$quantity" }
          }
        }
      ],
      as: "inventoryList"
    }
  }
])

Playground