首页 文章

MongoDb在同一记录中的字段和嵌套数组字段上聚合

提问于
浏览
1

我有一个集合 . 我试图得到记录中字段的总和/计数 . 我还需要记录中嵌套数组字段的总和/计数 . 我正在使用MongoDB 3.0.0和Jongo .

Please find my record below:

db.events.insert([{“eventId”:“a21sda2s-711f-12e6-8bcf-p1ff819aer3o”,
“orgName”:“ORG1”,
“eventName”:“EVA2”,
“eventCost”:5000,
“出价”:[{
“vendorName”:“v1”,
“bidStatus”:“接受”,
“bidAmount”:4400
},{
“vendorName”:“v2”,
“bidStatus”:“处理”,
“bidAmount”:4900
},{
“vendorName”:“v3”,
“bidStatus”:“被拒绝”,
“bidAmount”:“3000”
}]},{
“eventId”:“4427f318-7699-11e5-8bcf-feff819cdc9f”,
“orgName”:“ORG1”,
“eventName”:“EVA3”,
“eventCost”:1000,
“出价”:[{
“vendorName”:“v1”,
“bidStatus”:“被拒绝”,
“bidAmount”:800
},{
“vendorName”:“v2”,
“bidStatus”:“处理”,
“bidAmount”:900
},{
“vendorName”:“v3”,
“bidStatus”:“处理”,
“bidAmount”:990
}]}])

我需要$ eventCount和$ eventCost来汇总$ eventCost字段 . 我通过汇总$ bids.bidAmount字段获得$ acceptedCount和$ acceptedAmount(条件为$ bids.bidStatus)

The result I need would be in form:

[
{
"_id" : "EVA2",
"eventCount" : 2,
"eventCost" : 10000,
"acceptedCount" : 2,
"acceptedAmount" : 7400 },
{ 
"_id" : "EVA3",
"eventCount" : 1,
"eventCost" : 1000 ,
 "acceptedCount" : 0,
"acceptedAmount" : 0 },
}]

我无法在单个查询中获得结果 . 现在我创建两个查询A和查询B(参见下文)并将它们合并到我的Java代码中 . 我在查询B中使用$ unwind运算符 .

有没有办法在单个查询中实现相同的结果 . 我觉得我需要的是一种方法来将bid []数组传递到下游,用于管道中的下一个操作 .

我尝试了$ push运算符,但我无法想象,这是一种将整个bid []数组推向下游的方法 .

我不想改变我的记录结构,但如果有一些本质上错误的东西,我可以尝试一下 . 感谢你的帮助 .

我的解决方案

Query A:

db.events.aggregate([
    {$group: {
        _id: "$eventName",
        eventCount:     {$sum: 1}, // Get count of all events
        eventCost: {$sum: "$eventCost"} // Get sum of costs
    } }
])

Query B:

db.events.aggregate([
    {$unwind: "$bids" },
    {$group: {
        _id: "$eventName",
        // Get Count of Bids that have been accepted
        acceptedCount:{ $sum:{$cond: [{$eq: ["$bids.bidStatus","ACCEPTED"]} ,1,0] } } ,
        // Get Sum of Amounts that have been accepted
        acceptedAmount:{$sum:{$cond: [{$eq: ["$bids.bidStatus","ACCEPTED"]} ,"$bids.bidAmount",0]

    } } } }  
])

在Java代码中加入Query A和QueryB .

What I need:

单个DB操作来完成相同的操作

1 回答

  • 1

    解开数组的问题是如果你在进行初始分组之前尝试解开这些数据,它会弄乱你的分组事件的计数,因为每个文档数组中的项目数将影响计数和与失格文档的总和 .

    如果对您的数据大小很实用,那么使用$push来简单地创建和"array"的"arrays"并没有错,当然您只需在每个分组文档上处理$unwind两次:

    db.events.aggregate([
        { "$group": {
            "_id": "$eventName",
            "eventCount": { "$sum": 1 },
            "eventCost": { "$sum": "$eventCost" },
            "bids": { "$push": "$bids" }
        }},
        { "$unwind": "$bids" },
        { "$unwind": "$bids" },
        { "$group": {
            "_id": "$_id",
            "eventCount": { "$first": "$eventCount" },
            "eventCost": { "$first": "$eventCost" },
            "acceptedCount":{
                "$sum":{
                    "$cond": [
                        { "$eq": [ "$bids.bidStatus","ACCEPTED" ] },
                        1,
                        0
                    ]
                }
            },
            "acceptedCost":{
                "$sum":{
                    "$cond": [
                        { "$eq": [ "$bids.bidStatus","ACCEPTED" ] },
                        "$bids.bidAmount",
                        0
                    ]
                }
            }
        }}
    ])
    

    可能更好的替代方法是首先总结每个文档中的“已接受”值,然后在每个“事件”之后对这些值求和:

    db.events.aggregate([
        { "$unwind": "$bids" },
        { "$group": {
            "_id": "$_id",
            "eventName": { "$first": "$eventName" },
            "eventCost": { "$first": "$eventCost" },
            "acceptedCount":{
                "$sum":{
                    "$cond": [
                        { "$eq": [ "$bids.bidStatus","ACCEPTED" ] },
                        1,
                        0
                    ]
                }
            },
            "acceptedCost":{
                "$sum":{
                    "$cond": [
                        { "$eq": [ "$bids.bidStatus","ACCEPTED" ] },
                        "$bids.bidAmount",
                        0
                    ]
                }
            }
        }},
        { "$group": {
            "_id": "$eventName",
            "eventCount": { "$sum": 1 },
            "eventCost": { "$sum": "$eventCost" },
            "acceptedCount": { "$sum": "$acceptedCount" },
            "acceptedCost": { "$sum": "$acceptedCost" }
        }}
    ])
    

    通过这种方式,每个数组都会减少到您需要收集的值,这使得后者更容易实现.1353323 .

    这些是几种方法,后者是更好的选择,但如果你实际上能够并行处理两个查询并以智能方式组合它们,那么你正在做的那样运行两个查询将是我推荐的方法 . 最棒的表演 .

相关问题