gpt4 book ai didi

MongoDB MapReduce,与 "same approach"不同的结果,我错过了什么?

转载 作者:可可西里 更新时间:2023-11-01 10:01:15 25 4
gpt4 key购买 nike

我知道我在 MongoDB 的 MapReduce 中遗漏了一些东西。我正在尝试构建标签频率集合,但我得到了不同的结果,即使看起来 mapreduce 函数是“相同的”。

示例文档(忘记值 100、45...我没有使用它们):

{
...
tags: [['Rock', 100], ['Indie Pop', 45], ...]
}

发出标量值 1:

var map = function () {
if (this.tags) {
this.tags.forEach(function (tag) {
emit(tag[0], 1); // Emit just 1
});
}
};

var reduce = function (key, vals) { // Vals should be [1, ...]
return vals.length; // Count the length of the array
};

db.tracks.mapReduce(map, reduce, { out: 'mapreduce_out' });
db.mapreduce_out.find().sort({ value: -1 }).limit(3);

输出是:

{ "_id" : "rubyrigby1", "value" : 9 }
{ "_id" : "Dom", "value" : 7 }
{ "_id" : "Feel Better", "value" : 7 }

发射一个对象{ count: 1 } :

var map = function () {
if (this.tags) {
this.tags.forEach(function (tag) {
emit(tag[0], { count: 1 }); // Emit an object
});
}
};

var reduce = function (key, vals) { // vals should be [{ count: 1 }, ...]
var count = 0;

vals.forEach(function (val) {
count += val.count; // Accumul
});

return { count: count };
};

db.tracks.mapReduce(map, reduce, { out: 'mapreduce_out' });
db.mapreduce_out.find().sort({ 'value.count': -1 }).limit(3);

结果不同并且看起来是“正确的”:

{ "_id" : "rock", "value" : { "count" : 9472 } }
{ "_id" : "pop", "value" : { "count" : 7103 } }
{ "_id" : "electronic", "value" : { "count" : 5727 } }

第一种方法有什么问题?

最佳答案

考虑一千个文档的集合,所有文档都带有标签“tagname”:

for (var i = 0; i < 1000; i++) {
db.collection.insert({tags: [['tagname']]});
}

如果我编写适当的 mapReduce,我应该得到输出 {"_id": "tagname", "count": 1000}。但是,如果我使用您的 map 和 reduce 函数,我将得到 101 而不是 1000 的计数。

原因是,MongoDB 使用中间结果重复调用您的 reduce 函数,以避免在内存中保留太大的一批结果。实际上,您可以通过在 reduce 中放置打印语句来看到这一点:

var reduce = function (key, vals) {
print(vals);
return vals.length; // Count the length of the array
};

打印输出出现在服务器日志中。使用前 100 个 1 调用 reduce 函数,并返回 100。到目前为止一切顺利。然后 MongoDB 使用第一个 reduce 的输出加上接下来的 100 个 1 再次调用它:

reduce([100, 1, 1, ..., 1]) // 100 plus 100 more 1's

现在它返回 101,因为这是数组的长度。但显然它应该返回 200,即数组的总和。因此,要获得正确的结果,请更改您的 reduce 函数:

reduce = function (key, vals) {
var sum = 0;
vals.forEach(function(val) { sum += val; });
return sum;
}

关于MongoDB MapReduce,与 "same approach"不同的结果,我错过了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16808993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com