2015-10-17 82 views
2

我已經在mongo中使用了很多聚合,我知道在分組計數等方面的性能優勢。但是,在這兩種方法中,mongo在計算所有文檔的性能方面有任何差異收集?:MongoDB Count()與Aggregation

collection.aggregate([{ $ 匹配:{} },{ $組:{ _id:空, 計數:{$總和:1}} }]) ;

collection.find({}).count() 

更新:第二種情況: 比方說,我們有這樣的樣本數據:

{_id: 1, type: 'one', value: true} 
{_id: 2, type: 'two', value: false} 
{_id: 4, type: 'five', value: false} 

隨着aggregate()

var _ids = ['id1', 'id2', 'id3']; 
var counted = Collections.mail.aggregate([ 
    { 
    '$match': { 
     _id: { 
     '$in': _ids 
     }, 
     value: false 
    } 
    }, { 
    '$group': { 
     _id: "$type", 
     count: { 
     '$sum': 1 
     } 
    } 
    } 
]); 

隨着count()

var counted = {}; 
var type = 'two'; 
for (i = 0, len = _ids.length; i < len; i++) { 
    counted[_ids[i]] = Collections.mail.find({ 
    _id: _ids[i], value: false, type: type 
    }).count(); 
} 
+0

爲什麼不試試看看? – JohnnyHK

+0

@JohnnyHK試過''collection.aggregate()'似乎有點快,但不確定,100K的速度測試幾乎一樣。我希望看到社區的經驗。 –

回答

6

.count()要快得多。你可以通過調用

// Note the missing parentheses at the end 
db.collection.count 

返回光標的長度看執行。默認查詢(如果調用count()而沒有查詢文檔),這又被實現爲返回_id_索引iirc的長度。

但是,聚合會讀取每個文檔並對其進行處理。這隻能在與.count()相同的數量級上執行一半,只能處理大約100K的文檔(根據您的RAM進行分配)。

下面的功能被應用於收集一些12M條目:

function checkSpeed(col,iterations){ 

    // Get the collection 
    var collectionUnderTest = db[col]; 

    // The collection we are writing our stats to 
    var stats = db[col+'STATS'] 

    // remove old stats 
    stats.remove({}) 

    // Prevent allocation in loop 
    var start = new Date().getTime() 
    var duration = new Date().getTime() 

    print("Counting with count()") 
    for (var i = 1; i <= iterations; i++){ 
    start = new Date().getTime(); 
    var result = collectionUnderTest.count() 
    duration = new Date().getTime() - start 
    stats.insert({"type":"count","pass":i,"duration":duration,"count":result}) 
    } 

    print("Counting with aggregation") 
    for(var j = 1; j <= iterations; j++){ 
    start = new Date().getTime() 
    var doc = collectionUnderTest.aggregate([{ $group:{_id: null, count:{ $sum: 1 } } }]) 
    duration = new Date().getTime() - start 
    stats.insert({"type":"aggregation", "pass":j, "duration": duration,"count":doc.count}) 
    } 

    var averages = stats.aggregate([ 
    {$group:{_id:"$type","average":{"$avg":"$duration"}}} 
    ]) 

    return averages 
} 

並返回:

{ "_id" : "aggregation", "average" : 43828.8 } 
{ "_id" : "count", "average" : 0.6 } 

,單位爲毫秒。

hth

+0

謝謝你的回覆。您能否就我的更新(第二種情況)給出您的意見? –

+0

@itsme No.首先缺乏基本的禮貌,其次是因爲我不會支持濫用MongoDB作爲RDBMS。 –