2016-11-10 7 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グループを持っていると思います。誰も助けることができますか?

予想される出力:私はノードのJsとのMongoDBを使用していますが、次のように私はちょうど1クエリで期待される出力をしたい0と1を与えているよう

デモの目的のためにObjectIdとしての私の_idをご検討ください。あなたは、いくつかのパフォーマンスの低下や、巨大なデータセットを持つ可能性aggregation pipeline limitsがあるかもしれませんが、gのグループにあなたの最初のパイプラインが試行するために、コレクション内のすべてのドキュメントを、次の集約パイプラインを実行してみてください可能性が

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

答えて

2

全体の文書数と金額、およびすべての文書を一時的なリストにプッシュすると、パイプラインのパフォーマンスに影響を与える可能性があります。

それにもかかわらず、次のソリューションは、与えられたサンプルから与えられた所望の出力が得られます:大きなデータセット上で実行している場合、この問題は操作を減らすマップを解決するために、より速く、より適切であるかもしれない

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

を、結果は1つの集計結果であるためです。

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 
     } 
    }