2014-05-21 40 views
0

我有以下系列:Mongoose mapReduce:減少返回對象或數組?

/* 0 */ 
{ 
    "clientID" : ObjectId("51b9c10d91d1a3a52b0000b8"), 
    "_id" : ObjectId("532b4f1cb3d2eacb1300002b"), 
    "answers" : [], 
    "questions" : [] 
} 

/* 1 */ 
{ 
    "clientID" : ObjectId("51b9c10d91d1a3a52b0000b8"), 
    "_id" : ObjectId("532b6b9eb3d2eacb1300002c"), 
    "answers" : [ 
     "1", 
     "8" 
    ], 
    "questions" : [ 
     "1", 
     "2", 
     "3" 
    ] 
} 

/* 2 */ 
{ 
    "clientID" : ObjectId("51b9c10d91d1a3a52b0000b8"), 
    "_id" : ObjectId("532b6baeb3d2eacb1300002d"), 
    "answers" : [ 
     "1", 
     "8" 
    ], 
    "questions" : [ 
     "1", 
     "2", 
     "3" 
    ] 
} 

/* 3 */ 
{ 
    "clientID" : ObjectId("5335f9d864e2b1290c00012e"), 
    "_id" : ObjectId("533b828146ca43634000002d"), 
    "answers" : [ 
     "ORANGE" 
    ], 
    "questions" : [ 
     "Color" 
    ] 
} 

/* 4 */ 
{ 
    "clientID" : ObjectId("5335f9d864e2b1290c00012e"), 
    "_id" : ObjectId("5351be327b539a4d1a00002b"), 
    "answers" : [ 
     "ORANGE" 
    ], 
    "questions" : [ 
     "Color" 
    ] 
} 

/* 5 */ 
{ 
    "clientID" : ObjectId("5335f9d864e2b1290c00012e"), 
    "_id" : ObjectId("5351be5ec89d717d1a00002b"), 
    "answers" : [ 
     "ORANGE" 
    ], 
    "questions" : [ 
     "Color" 
    ] 
} 

我運行下面的代碼,以找到(問題,答案)組合出現了多少次集合中:

o.map= function(){ 
    emit({"questions" : this.questions, "answers" :this.answers },this.clientID) 
}; 

o.reduce = function(answers, collection){ 
    return collection.length; 
}; 

logSearchDB.mapReduce(o,function (err, results) { 
    results.sort(function(a, b){return b.value-a.value}); 
    for (var i = 0; i < results.length; i++) { 
     console.log(JSON.stringify(results[i])) 
    }; 

}) 

的輸出是:

{"_id":{"questions":[],"answers":[]},"value":"51b9c10d91d1a3a52b0000b8"} 
{"_id":{"questions":["Color"],"answers":["ORANGE"]},"value":3} 
{"_id":{"questions":["1","2","3"],"answers":["1","8"]},"value":2} 

我預計第一行將有「值」:1

我想'減少'功能得到'集合'對象:「51b9c10d91d1a3a52b0000b8」,而不是獲取數組:「[」51b9c10d91d1a3a52b0000b8「]。

爲什麼地圖縮小不會將所有內容都收集到數組中?

回答

1

爲什麼你只是一個普通的值在第一行是因爲只有一個發生的關鍵值的原因。這通常是mapReduce的工作方式,至少是在原始論文中指定的方式。

所以,當只有一個鍵時,reduce函數並不會被調用。要解決這一點,你使用地圖中的finalize功能降低:

var finalize = function(key,value) { 
    if (typeof(value) != "number") 
     value = 1; 

    return value; 
}; 

db.collection.mapReduce(
    mapper, 
    reducer, 
    { 
     "finalize": finalize, 
     "out": { "inline": 1 } 
    } 
); 

運行在所有的輸出,並認爲當值被看作是不nunber,作爲clientID你發光,那麼該值設置爲1,因爲這就是分組中的hany。

真的,您的查詢比mapReduce更適合aggregation framework。與使用JavaScript解釋器相反,聚合框架是本機代碼實現。它的運行速度比mapReduce快得多:

db.collection.aggregate([ 
    { "$group": { 
     "_id": { 
      "questions": "$questions", 
      "answers": "$answers" 
     }, 
     "count": { "$sum": 1 } 
    }} 
]) 

所以這是更好的選擇。這是MongoDB的後續介紹,所以人們仍然傾向於用mapReduce來思考,否則就會有早期版本的MongoDB的遺留代碼。但是這已經存在了很長一段時間了。

另請參閱operator reference瞭解彙總框架。