【问题标题】:Use $multiply on nested fields in aggregation in MongoDB在 MongoDB 聚合中的嵌套字段上使用 $multiply
【发布时间】:2016-01-01 12:57:36
【问题描述】:

我正在尝试在 MongoDB 中进行聚合。

我收藏了一些物品。每个项目都有一个数组rowsrows 中的每个对象都有quantityprice 字段。

我想将quantityprice相乘,但不知道如何正确指定字段。

我试过了

const pipeline = [
  {
    $group: {
      _id: {
        number: '$number',
      },
      total: {
        $sum: {
          $multiply: [
            '$rows.quantity',
            '$rows.price'
          ]
        }
      },
    }
  }
];

但它说$multiply 只支持数字类型而不支持数组。

所以它似乎不明白$rows.quantity是数组中每个对象中的数字类型字段quantity

我想我可能应该使用$each 或其他东西来遍历数组中的对象。

来自Using multiply aggregation with MongoDB 我看到我正确指定了字段;然而,在那个例子中它是一个嵌套对象而不是一个数组,所以也许我必须使用https://docs.mongodb.org/v3.0/reference/operator/aggregation/unwind/

示例文档

{
  number: 2,
  rows: [
    {
      quantity: 10,
      price: 312
    },
    {
      quantity: 10,
      price: 312
    },
    {
      quantity: 10,
      price: 312
    },
  ]
}

【问题讨论】:

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

使用.aggregate() 方法。

从版本 3.2 开始,您可以在 $project 阶段使用 $sum 累加器运算符来计算并返回 quantity * price 数组的总和。当然,要获取数组,您需要使用 $map 运算符。 $ifNull 运算符计算“数量”和“价格”的值,如果它们的计算结果为空值,则返回 0。管道中的最后一个阶段是 $group 阶段,您可以在其中按“数字”对文档进行分组,并返回每个组的“总数”。

db.collection.aggregate([
    { "$project": { 
        "number": 1,  
        "total": { 
            "$sum": { 
                "$map": { 
                    "input": "$rows", 
                    "as": "row", 
                    "in": { "$multiply": [ 
                        { "$ifNull": [ "$$row.quantity", 0 ] }, 
                        { "$ifNull": [ "$$row.price", 0 ] } 
                    ]} 
                }
            }
        }
    }},
    { "$group": { 
        "_id": "$number", 
        "total": { "$sum": "$total" } 
    }}
])

如果您不在 3.2 版上,则需要使用 $unwind 运算符在 $project 阶段之前对“行”数组进行非规范化。

db.collection.aggregate([
    { "$unwind": "$rows" }, 
    { "$project": { 
        "number": 1,  
        "value": { "$multiply": [
            { "$ifNull": [ "$rows.quantity", 0 ] }, 
            { "$ifNull": [ "$rows.price", 0 ] } 
        ]}
    }}, 
    { "$group": { 
        "_id": "$number", 
        "total": { "$sum": "$value" } 
    }}
])

【讨论】:

  • 谢谢!如果未设置数量或价格,似乎会出现一些错误。我可以做些什么来确保数量和价格始终被评估为数字(即,如果未设置,则将它们视为零)?还是应该跳过数量或价格为零的行,因为它们无论如何都不会添加到总数中?
  • @Jamgreen 如果缺少“数量”或价格,您需要使用$ifNull 运算符返回0。我已经更新了答案。如果有帮助,请随时接受答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-18
  • 2023-04-03
  • 2017-09-13
相关资源
最近更新 更多