如何使用mongodb中两个集合的聚合计算利润?

如何使用mongodb中两个集合的聚合计算利润?,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我有两个系列,订单和产品类型 产品类型: { "_id" : 609d79de5909592f2635c64e, "name" : "T-Shirt", "subType" : "Round Neck", "__v" : 0, "size" : "XXL", "sell

我有两个系列,订单和产品类型

产品类型:

{ 
    "_id" : 609d79de5909592f2635c64e, 
    "name" : "T-Shirt", 
    "subType" : "Round Neck", 
    "__v" : 0, 
    "size" : "XXL", 
    "sellingPrice" : 320, 
    "createdAt" : ISODate("2021-05-18T05:22:00.695+0000"), 
    "actualPrice" : 200, 
    "updatedAt" : ISODate("2021-05-25T12:11:50.986+0000")
},
{ 
    "_id" : 609d79de5909592f2635c64d, 
    "name" : "T-Shirt", 
    "subType" : "V Neck", 
    "__v" : 0, 
    "size" : "XXL", 
    "sellingPrice" : 290, 
    "createdAt" : ISODate("2021-05-18T05:22:00.695+0000"), 
    "actualPrice" : 200, 
    "updatedAt" : ISODate("2021-05-25T12:11:50.986+0000")
}
订单:

{ 
    "_id" : "60a63e369cf3a806c0209bd8", 
    "items" : [
        {
            "type" : "609d79de5909592f2635c64e", 
            "quantity" : 1, 
            "sellingPrice" : 320
        }, 
        {
            "type" : "609d79de5909592f2635c64d", 
            "quantity" : 2, 
            "sellingPrice" : 290
        }
    ], 
    "orderId" : "ORD101", 
    "from" : "Abc", 
    "to" : "xyz", 
    "createdAt" : ISODate("2021-05-20T10:47:18.920+0000"), 
    "__v" : 0, 
    "tracking" : "12345678"
}
我想计算每个订单的总利润,如下所示:

{orderId: "ORD101", createdAt: ISODate("2021-05-18T05:22:00.695+0000"), profit: 300}
我不知道如何加入这两个集合来计算利润

但我在node中尝试了如下操作:

Order.aggregate([{
        $unwind: '$items'
    }, {
        $project: {
            orderId:1,
            quantity: "$items.quantity",
            sellingPrice: {
                $multiply: [
                    {"$ifNull": ["$items.quantity", 0]},
                    {"$ifNull": ["$items.price", 0]}
                ]
            },
            type: '$items.type'
        }
        }])
    .exec(function(err, transactions) {
        //console.log(transactions);
        ProductType.populate(transactions,{path: 'type',  select: 'actualPrice' }, function(err, populatedTransactions) {
            //res.json(populatedTransactions);
            var items = [];
            var totalProfit = 0;
            if(populatedTransactions){
                populatedTransactions.forEach( order => {
                    if( order.quantity != undefined && order.sellingPrice != undefined && order.sellingPrice > 0){
                        let profit = order.sellingPrice - (order.quantity * order.type.actualPrice);
                        totalProfit = totalProfit + profit;
                        items.push({ orderId: order.orderId, profit: profit });
                    }
                })
                res.status(200).json({data: items, totalProfit: totalProfit});
            }
        });
    });
这条路对吗

这里我在数组中使用
$unwind
,然后填充producttypes集合以获得实际价格,然后进行计算以获得利润。

  • $project
    显示必填字段
  • $unwind
    解构
    数组
  • $lookup
    productTypes
    集合
  • 计算利润
    • $arrayElemAt
      从项目
      实际价格
      结果中获取第一个元素
    • $subtract
      sellingPrice
      by
      actualPrice
    • $multiply
      以上结果与
      数量
  • $group
    按订单
    \u id
    并获取所需字段和金额
    利润

感谢您的快速回复和解决方案。但问题是在游戏环境中,它工作正常,但在我的系统中$lookup的“item”是空数组,这是我的mongo版本的问题吗?以下是我的mongo版本详细信息MongoDB shell版本4.4.5构建信息:{“版本”:“4.4.5”,“gitVersion”:“ff5cb77101b052fa02da43b8538093486cf9b3f7”,“模块”:[],“分配器”:“系统”,“环境”:{“distarch”:“x86_64”,“目标_arch”:“x86_64”}不,这不是mongo版本问题,您能否确认订单中的
项。type
字段是字符串类型还是对象id类型?它是objectId“items”:[{“type”:objectId(“609D79DE590952F2635C64D”),“quantity”:numberprint(0),“price”:numberprint(0)}]好的,如果它是objectid,我看不出有任何问题。非常感谢@turivishal,错误来自我这边,我重命名了一个字段,现在它给出了正确的结果。非常感谢您的快速解决方案。
Order.aggregate([
  {
    $project: {
      orderId: 1,
      createdAt: 1,
      items: 1
    }
  },
  { $unwind: "$items" },
  {
    $lookup: {
      from: "productTypes", // replace your actual collection name
      localField: "items.type",
      foreignField: "_id",
      as: "item"
    }
  },
  {
    $addFields: {
      profit: {
        $multiply: [
          {
            $subtract: [
              "$items.sellingPrice",
              { $arrayElemAt: ["$item.actualPrice", 0] }
            ]
          },
          "$items.quantity"
        ]
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      orderId: { $first: "$orderId" },
      createdAt: { $first: "$createdAt" },
      profit: { $sum: "$profit" }
    }
  }
])