我有以下收藏:
/* 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
我想'reduce'函数得到了一个'collection'对象:“51b9c10d91d1a3a52b0000b8”,而不是得到一个数组:[“51b9c10d91d1a3a52b0000b8”]。
为什么map reduce不会将所有内容都收集到数组中?
答案 0 :(得分: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
,因为这是如何哈尼正在分组。
您的查询确实比mapReduce更适合aggregation framework。聚合框架是本机代码实现,而不是使用JavaScript解释器。它的运行速度比mapReduce快得多:
db.collection.aggregate([
{ "$group": {
"_id": {
"questions": "$questions",
"answers": "$answers"
},
"count": { "$sum": 1 }
}}
])
所以这是更好的选择。这是后来对MongoDB的介绍,所以人们仍然倾向于考虑mapReduce,或者有早期版本的MongoDB遗留代码。但这已经存在了很长一段时间。
另请参阅operator reference了解聚合框架。