2016-11-10 149 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 
     } 
    }