Map Reduce不产生大型数据集



我在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

从以上结果我得出结论,有记忆问题,但我不知道在哪里和为什么。请帮助。

你的流程在很多方面都有缺陷。

  1. 文本搜索不像这样工作

    您正在请求 $text 搜索查询匹配部分单词,例如

     "breaking bad s"
     "breaking bad f"
    

    在每种情况下,这里的"s"one_answers"f"都被忽略,因为它们不是一个完整的单词。所以搜索的唯一术语是"breaking"one_answers"bad"。我在这里指的是"terms""phrase"相反,就像在"breaking bad"中一样,因为您使用的语法不这样做,而只查找terms。

    它们"可能"是短语,但如果正在搜索的数据包含任何其他组合的"breaking"或"bad",则通常不会是短语。

    我不知道你认为这些计数是从哪里来的,但它肯定与附加在那里的"non-word"无关。

  2. 映射器也错了

    继上面的

    之后,由于您在这里实际匹配的是"breaking"one_answers"bad"作为单独的单词,因此仅检查这些"单词"是否存在于字符串中是有意义的。当然会,但是测试是错误的,应该这样写:

    map = function() {
        if ( /breaking|bad/.test(this.torrent_name) ) {
            emit(null,1);
        }
    };
    
  3. 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 } }
    }
);

你实际上可能只是得到一个正常的响应,告诉你它做了什么。

但是当您进一步开发它时,请注意上面所说的内容并充分阅读文档,该文档还解释了上面描述的要点。

相关内容

  • 没有找到相关文章

最新更新