【问题标题】:How to find sum of total value from inner array?如何从内部数组中找到总值的总和?
【发布时间】:2016-04-01 05:17:20
【问题描述】:

{ 
    "_id" : ObjectId("56fb04fd2e6bb8bc059287c9"), 
    "BillNo" : "Bill_001", 
    "DateP" : "12-12-2015", 
    "Type" : "Cash", 
    "Items" : [
        {
            "id" : NumberInt(1), 
            "ItemName" : "cement", 
            "Qty" : "100", 
            "Rate" : "10", 
            "Total" : "1000"
        }, 
        {
            "id" : NumberInt(2), 
            "ItemName" : "steel", 
            "Qty" : "10", 
            "Rate" : "50", 
            "Total" : "500"
        }, 
        {
            "id" : NumberInt(3), 
            "ItemName" : "sand", 
            "Qty" : "1", 
            "Rate" : "1500", 
            "Total" : "1500"
        }
    ]
}
{ 
    "_id" : ObjectId("56fb05382e6bb8bc059287ca"), 
    "BillNo" : "Bill_002", 
    "DateP" : "12-10-2015", 
    "Type" : "Cash", 
    "Items" : [
        {
            "id" : NumberInt(1), 
            "ItemName" : "Paint", 
            "Qty" : "50", 
            "Rate" : "100", 
            "Total" : "5000"
        }, 
        {
            "id" : NumberInt(2), 
            "ItemName" : "Brush", 
            "Qty" : "5", 
            "Rate" : "10", 
            "Total" : "50"
        }
    ]
}

在上面的集合中,将所有购买细节存储在主文档中,并将其项目细节存储为主项目的内部数组。我需要使用 mongodb 得到如下结果;如何从 mongodb 中的内部数组中查找总数。

Bill_001     1500
Bill_002     5050

【问题讨论】:

  • 你所有的字符串值。您应该修复它们,因为您不能真正将字符串添加在一起。
  • 结果会像 Bill_001 -> 3000, Bill_002 -> 5050
  • 如果改成int那么mongo shell会怎么样?

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

理想情况下,在 MongoDB 中,您可以使用 $map$sum 作为 $group 累加器,并且它是添加所提供数组成员的新角色:

db.collection.aggregate({
   { "$group": {
       "_id": "$BillNo",
       "Total": {
           "$sum": {
               "$sum": {
                  "$map": {
                     "input": "$Items",
                     "as": "item",
                     "in": "$$item.Total"
                  }
               }
           }
       }
   }}
})

或者只是每个文档:

db.collection.aggregate({
   { "$group": {
       "_id": "$_id",
       "BillNo": { "$first": "$BillNo" },
       "DateP": { "$first" "$DateP" },
       "Type": { "$first": "$Type" }
       "Total": {
           "$sum": {
               "$sum": {
                  "$map": {
                     "input": "$Items",
                     "as": "item",
                     "in": "$$item.Total"
                  }
               }
           }
       }
   }}
})

使用$first 的另一个累加器。当然,你真的可以只用 $project 使用 MongoDB 3.2:

db.collection.aggregate({
   { "$project": {
       "BillNo": 1,
       "DateP": 1,
       "Type": 1,
       "Total": {
           "$sum": {
              "$map": {
                 "input": "$Items",
                 "as": "item",
                 "in": "$$item.Total"
              }
           }
       }
   }}
})

在旧版本中,您仍然需要先在阵列上使用$unwind

db.collection.aggregate([
    { "$unwind": "$Items" },
    { "$group": {
       "_id": "$BillNo",
       "Total": {
           "$sum": "$Items.Total"
       }
    }}
])

或者,如果您只添加每个文档:

db.collection.aggregate([
    { "$unwind": "$Items" },
    { "$group": {
       "_id": "_id",
       "BillNo": { "$first": "$BillNo" },
       "DateP": { "$first": "$DateP" },
       "Type": { "$first": "$Type" },
       "Total": {
           "$sum": "$Items.Total"
       }
    }}
])

当然,只有在您实际将字符串固定为数值时。

理想情况下,您可以这样修复它:

var ops = [];

db.collection.find().forEach(function(doc) {
    doc.Items.forEach(function(item) {
        ops.push({
            "updateOne": {
                "filter": { "_id": doc._id, "Items.id": item.id },
                "update": {
                    "$set": {
                        "Items.$.Qty": parseInt(item.Qty),
                        "Items.$.Rate": parseInt(item.Rate),
                        "Items.$Total": parseInt(item.Total)
                    }
                }
            }        
        });

        // Send batch of updates
        if ( ops.length == 1000 ) {
            db.collection.bulkWrite(ops);
            ops = [];
        }
    })
});

// Clear any unprocessed updates
if ( ops.length > 0 ) {
    db.collection.bulkWrite(ops);
}

【讨论】:

  • 谢谢.. 工作正常。如果我想显示 BillNo、Date、Type.. 等以及“Total”,那么它将如何显示。我正在使用 $unwind 方法。请回复这个也
  • @Pradeep 这不是你的问题。欢迎使用 stackoverflow,您可以在此处一次提出一个问题,当您有其他问题时,请 Ask Another Question。您要求“累积”"BillNo" 的值,因此这意味着 "Type" 等值当然会在每个文档中发生变化,并且不属于分组的一部分。您可以使用其他accumulators,但这不是您的问题的一部分。
猜你喜欢
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多