2015-07-05 24 views
0

我有一個字段集合:number,a,b,c通過在流星中分組獲得彙總

我想根據數量將收集分成三部分,併爲每個組部門分別得到a,bc的總和。

我與

function sumList(amountList) { 
    return _.reduce(amountList, function(sum, amount) { 
    return sum + amount; 
    }, -1); 
} 

// cursors 
var group1 = Groups.find({ number: { $lte: 32 } }).fetch(); 
var group2 = Groups.find({ number: { $gte: 33, $lte: 70 } }).fetch(); 
var group3 = Groups.find({ number: { $gte: 71 } }).fetch(); 

// sums for group1 
var group1SumA = sumList(_.pluck(group1, "a")); 
var group1SumB = sumList(_.pluck(group1, "b")); 
var group1SumC = sumList(_.pluck(group1, "c")); 

// sums for group2 
var group2SumA = sumList(_.pluck(group2, "a")); 
var group2SumB = sumList(_.pluck(group2, "b")); 
var group2SumC = sumList(_.pluck(group2, "c")); 

// sums for group3 
var group3SumA = sumList(_.pluck(group3 "a")); 
var group3SumB = sumList(_.pluck(group3, "b")); 
var group3SumC = sumList(_.pluck(group3, "c")); 

它可以這樣做,但我認爲代碼是非常難看。

我不知道這是否可以用一些智能映射來完成。此外,我想這可能會有不好的表現。

這些和如何優化?

回答

0

使用aggregation framework這將對$match管道運營商篩選的number場集合。然後流水線步驟將所有經過濾的輸入文檔分組,並將累加器表達式$sum應用於每個字段以獲得總和。

你的管道應該是這樣的:

var pipeline = [ 
    { 
     "$match": { "number": { "$lte": 32 } } /* group1 filter */ 
    }, 
    { 
     "$group": { 
      "_id": 0, 
      "sumA": { "$sum": "$a" }, 
      "sumB": { "$sum": "$b" }, 
      "sumC": { "$sum": "$c" } 
     } 
    } 
]; 

您可以添加meteorhacks:aggregate package實現流星聚集:

添加到您的應用

meteor add meteorhacks:aggregate 

由於這包曝光.aggregate方法在Mongo.Collection實例上,您可以調用該方法來獲取包含總和的文檔的結果數組。例如

if (Meteor.isServer) { 
    var Coll = new Mongo.Collection('collectionName'); 
    Meteor.methods({ 
     sumList: function (filter) { 
      var pipeline = [ 
       { 
        "$match": filter 
       }, 
       { 
        "$group": { 
         "_id": 0, 
         "sumA": { "$sum": "$a" }, 
         "sumB": { "$sum": "$b" }, 
         "sumC": { "$sum": "$c" } 
        } 
       } 
      ];   
      var result = Coll.aggregate(pipeline); 
      return result[0]; 
     } 
    }); 
} 

if (Meteor.isClient) { 
    // filters 
    var group1 = { "number": { "$lte": 32 } }; 
    var group2 = { "number": { "$gte": 33, "$lte": 70 } }; 
    var group3 = { "number": { "$gte": 71 } }; 

    Meteor.call('sumList', group1, callback); 
    //Meteor.call('sumList', group2, callback); 
    //Meteor.call('sumList', group3, callback); 

    function callback(err, result) { 
     console.log(result) 
    } 
} 
+0

謝謝。我試着實現它,但我得到的錯誤'異常,而調用方法'sumList'TypeError:對象[對象對象]沒有方法'fetch''。我認爲'BudgetGroups.aggregate(pipeline)'總是會返回一個遊標而不是一個對象,因爲錯誤消息指示 – Jamgreen

+0

@Jamgreen實際上不需要調用'fetch()'方法,因爲聚合方法本身返回結果數組。你可以檢查它的測試[** here **](https://github.com/meteorhacks/meteor-aggregate/blob/master/test.js)。 – chridam

+0

它在我刪除'fetch()'時起作用。如果我在方法中使用console.log(result),我會得到預期的結果,但是當我嘗試使用Meteor.call('sumList',group1,callback)返回的值時。我只是'undefined'。我也試過'Meteor.call('sumList',group1,function(err,result){return result});'' – Jamgreen