首页 > 解决方案 > 在 MongoDB 中聚合、分组、计算和投影数据

问题描述

{ _id : 5f206f44e51c8026b2222f74 , order : 1 , type : purchased , amount : 1000 }
{ _id : 5f207065e51c8026b2222f75 , order : 1 , type : processed , productType : good , amount : 700 }
{ _id : 5f20716fe51c8026b2222f77 , order : 1 , type : processed , productType : small , amount : 100 }
{ _id : 5f2071b5e51c8026b2222f78 , order : 1 , type : processed , productType : shrinked , amount : 100 }
{ _id : 5f2073a5abd40426b2650033 , order : 1 , type : processed , productType : waste , amount : 100 }
{ _id : 5f207220e51c8026b2222f79 , order : 1 , type : shipped , amount : 500 }

业务逻辑:产品(按顺序)被购买、处理(获得几个“productType”)并发货。

预期:按订单、类型、产品类型、总和金额分组并计算余数。

预期输出:

{
    order: 1,
    purchased: 1000,
    processed: 1000,
    productTypes: {
        good: 700,
        small: 100,
        shrinked: 100,
        waste: 100
    },
    shipped: 500,
    productBalance: 500
}

到目前为止,我设法按订单和类型对项目进行分组:

询问:

{
    $group: {
          _id: {
                    "order": "$order",
                    "type": "$type"
                },
          logs: { $push: "$$ROOT" },
          totalAmount: { $sum: "$amount" }
    }
}

{
    $group: {
          _id: "$_id.order",
          types: {
              $push: { 
                type: "$_id.type", 
                totalAmount: "$totalAmount", 
                logs: "$logs"
              } 
          }
    }
}

查询图片(指南针)

结果:

{
    order: 1,
    types: [
        { 
            type: "purchased",
            totalAmount: 1000,
            logs: [ ... ]
        },
        { 
            type: "processed",
            totalAmount: 1000,
            logs: [ 
                {
                    type:"processed"
                    productType:"small"
                    amount:100
                },
             ... ]
        },
    ]
}

标签: mongodbaggregate

解决方案


[{$group: {
  _id: {
    order: '$order',
    type: '$type'
  },
 logs:{
   $push:{
     productType:{$ifNull:["$productType","removeElement"]},
     amount:{
       $sum:"$amount"
     }
   }
 },
 total:{
   $sum:"$amount"
 }
}}, {$project: {
  order:"$_id.order",
  type:"$_id.type",
  total:1,
  productType:{
    "$arrayToObject": {
      "$map": {
        "input": "$logs",
        "in": {
          "k": "$$this.productType",
          "v": "$$this.amount"
        }
      }
    }
  }
}}, {$project: {
  "productType.removeElement":0
}}, {$group: {
  _id: "$order",
  typeAmount: {
    $push: {
      type:"$type",
      amount:"$total"
    }
  },
  productType:{
    $push:"$productType"
  }
}}, {$project: {
  order:"$_id",
  typeAmount:{
    "$arrayToObject": {
      "$map": {
        "input": "$typeAmount",
        "in": {
          "k": "$$this.type",
          "v": "$$this.amount"
        }
      }
    }

    },
  productType:{
    $filter:{
      input:"$productType",
      cond:{
        $ne:["$$this",{}]
      }
    }
  },
  _id:0
}}, {$replaceRoot: {
  newRoot: {
    "$mergeObjects": ["$typeAmount","$$ROOT"]
  }

    }}, {$project: {
  typeAmount:0

  }}]

工作Mongo 游乐场。该问题不包括如何计算 productBalance。希望,不会有问题。productType是一个数组,如果它只能有一个您可以使用的对象,$arrayElemAt或者只是$unwind("$productType")将其作为对象


推荐阅读