我在map reduce中面临问题,每当预期的结果数据集很大时,它就不会返回任何东西,它适用于像4万个文档这样的小数据集。以下是代码和问题理解。看,我用了这个代码
search = "breaking bad f"
var emit = function(a,b){
print(a);
}
map = function() {
if(this.torrent_name.indexOf(search) > -1){
emit(this._id, this.torrent_name);
}
}
reduce = function(key,values){
return values;
}
res = db.torrents.mapReduce(map,reduce,{out: { inline: 1 },query:{$text:{$search:search}},scope:{search:search},sort:{'seeders':-1}})
printjson(res);
现在这个作业的结果是:
{
"results" : [ ],
"timeMillis" : 503,
"counts" : {
"input" : 39859,
"emit" : 0,
"reduce" : 0,
"output" : 0
},
"ok" : 1
}
这是有意义的,因为map reduce的输入与下面查询
的答案相同db.torrents.find({$text:{$search:"breaking bad f"}}).count()
output => 39859
现在主要的问题来了,当我改变搜索字符串在mapreduce工作为"breaking bad s",结果显示为
{
"results" : [ ],
"timeMillis" : 329,
"counts" : {
"input" : 0,
"emit" : 0,
"reduce" : 0,
"output" : 0
},
"ok" : 1
}
不产生任何结果,因为map reduce的输入不等于下面查询的答案
db.torrents.find({$text:{$search:"breaking bad s"}}).count()
output => 71484
从以上结果我得出结论,有记忆问题,但我不知道在哪里和为什么。请帮助。
你的流程在很多方面都有缺陷。
-
文本搜索不像这样工作
您正在请求
$text
搜索查询匹配部分单词,例如"breaking bad s" "breaking bad f"
在每种情况下,这里的"s"one_answers"f"都被忽略,因为它们不是一个完整的单词。所以搜索的唯一术语是"breaking"one_answers"bad"。我在这里指的是"terms"与"phrase"相反,就像在"breaking bad"中一样,因为您使用的语法不这样做,而只查找terms。
它们"可能"是短语,但如果正在搜索的数据包含任何其他组合的"breaking"或"bad",则通常不会是短语。
我不知道你认为这些计数是从哪里来的,但它肯定与附加在那里的"non-word"无关。
-
映射器也错了
继上面的之后,由于您在这里实际匹配的是"breaking"one_answers"bad"作为单独的单词,因此仅检查这些"单词"是否存在于字符串中是有意义的。当然会,但是测试是错误的,应该这样写:
map = function() { if ( /breaking|bad/.test(this.torrent_name) ) { emit(null,1); } };
-
Reducer也是错误的
更重要的是,除了先前的"发出"失败之外,根本不会调用减速器。对于
mapReduce
的想法是,所有"共同"的_id
值被发送到减速机"还原"为单个值,然后返回。你写这个的方式,你只是试图传递
values
,这实际上是一个数组。如果减速器已经触发,那么这会产生一个"大"错误,因为您只能返回一个"单个"值。事实上,这就是为什么它被称为"reduce"阶段,因为你想要将分组数据"reduce"到一个单一的公共点。我们再把它改写成符合逻辑的:
var reduce = function(key,values) { return Array.sum(values); };
这里还要注意,从映射器发出的数据的"输出"必须与从reducer"输出"的数据具有相同的结构和类型。
这是因为为了处理"大数据",mapReduce不会"一次"处理相同的分组键,而是在小的"块"中处理。因此,从减速器"出来"的数据最终可能会作为进一步减少的值之一返回"进来"。
最后如果你运行这个:
res = db.torrents.mapReduce(
map,
reduce,
{
"out": { "inline": 1 },
"query": { "$text":{ "$search" :search } }
}
);
你实际上可能只是得到一个正常的响应,告诉你它做了什么。
但是当您进一步开发它时,请注意上面所说的内容并充分阅读文档,该文档还解释了上面描述的要点。