2016-11-10 73 views
-1

我的收藏JSON单汇总查询多个组

[ 
    { 
     "_id" : 0, 
     "finalAmount":40, 
     "payment":[ 
     { 
      "_id":0, 
      "cash":20 
     }, 
     { 
      "_id":1, 
      "card":20 
     } 
     ] 
    }, 
    { 
     "_id" : 1, 
     "finalAmount":80, 
     "payment":[ 
     { 
      "_id":0, 
      "cash":60 
     }, 
     { 
      "_id":1, 
      "card":20 
     } 
     ] 
    }, 
    { 
     "_id" : 2, 
     "finalAmount":80, 
     "payment":[ 
     { 
      "_id":0, 
      "cash":80 
     } 
     ] 
    } 
] 

我想有amountcashcard组明智使用聚合框架。谁能帮忙?

请考虑我_idObjectId用于演示目的,我已经给了0和1。我使用节点JS和MongoDB的,我想在短短的一个查询的预期输出如下:

预期输出:

{ 
    "cash":160, 
    "card":40, 
    "total":200, 
    "count":3 
} 

回答

2

你可以尝试运行下面的聚集管道,虽然可能有一些性能损失或由于您最初的管道尝试组中的所有集合中克文件潜力aggregation pipeline limits巨大的数据集等文件总数和金额以及将所有文档推送到临时列表,这可能会影响管道的性能。

尽管如此,下面的溶液将产生从给定的样品给定的期望的输出:

collection.aggregate([ 
    { 
     "$group": { 
      "_id": null, 
      "count": { "$sum": 1 }, 
      "doc": { "$push": "$$ROOT" }, 
      "total": { "$sum": "$finalAmount" } 
     } 
    }, 
    { "$unwind": "$doc" }, 
    { "$unwind": "$doc.payment" }, 
    { 
     "$group": { 
      "_id": null, 
      "count": { "$first": "$count" }, 
      "total": { "$first": "$total" },    
      "cash": { "$sum": "$doc.payment.cash" }, 
      "card": { "$sum": "$doc.payment.card" } 
     } 
    } 
], function(err, result) { 
    console.log(result); 
}); 
0

当在大的数据集运行,这个问题可能更适合,更快速与地图来解决减少操作,因为结果是一个singel聚合结果。

var map = function map(){ 
    var cash = 0; 
    var card = 0; 

    for (i in this.payment){ 

     if(this.payment[i].hasOwnProperty('cash')){ 
      cash += this.payment[i]['cash'] 
     } 
     if(this.payment[i].hasOwnProperty('card')){ 
      card += this.payment[i]['card'] 
     } 
    } 

    var doc = { 
     'cash': cash, 
     'card': card, 
    }; 
    emit(null, doc);  
}; 

var reduce = function(key, values){ 

    var total_cash = 0; 
    var total_card = 0; 
    var total = 0; 

    for (i in values){ 
     total_cash += values[i]['cash'] 
     total_card += values[i]['card'] 
    } 

    var result = { 
     'cash': total_cash, 
     'card': total_card, 
     'total': total_cash+ total_card, 
     'count': values.length 
    }; 

    return result 
}; 


db.runCommand({"mapReduce":"test", map:map, reduce:reduce, out:{replace:"test2"}}) 

结果:

db.test2.find().pretty() 
    { 
     "_id" : null, 
     "value" : { 
      "cash" : 160, 
      "card" : 40, 
      "total" : 200, 
      "count" : 3 
     } 
    }