首页 > 解决方案 > 如何使用 mongodb 中两个集合的聚合计算利润?

问题描述

我有两个集合,订单和产品类型

产品类型:

{ 
    "_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}

我不知道如何加入这两个集合来计算利润。

但是我在节点中尝试了类似下面的东西:

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 集合填充以获得实际价格,然后进行计算以获得利润。

标签: mongodbaggregation-framework

解决方案


  • $project显示必填字段
  • $unwind解构items数组
  • $lookupproductTypes收藏
  • 计算利润
    • $arrayElemAt从项目actualPrice结果中获取第一个元素
    • $subtract sellingPrice经过actualPrice
    • $multiply以上结果与quantity
  • $group按订单_id并获取必填字段和总和profit
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" }
    }
  }
])

操场


推荐阅读