【问题标题】:Rejoining Split MapReduce Arrays in Mongo在 Mongo 中重新加入拆分的 MapReduce 数组
【发布时间】:2011-12-27 08:26:02
【问题描述】:

我只是在学习 mapReduce。我在一组用户上调用了以下 map reduce 函数。

function () {

    m = function () {
            emit(this.city, {num:1, arr:this});
    }

    r = function (key, arr_values) {
            var resultArray = [];
            var count = 0;
            arr_values.forEach(function (value) {
                                    resultArray.push(value);
                                    count++;
                                });
            return {num:count, arr:resultArray};
    }

    res = db.AdsOnPage.mapReduce(m, r, {out:"ReducedCollection"});


}

这最终给了我我需要的东西——“城市”作为键,然后是该城市中的用户数组作为值。但它实际上是在数量荒谬的嵌套数组中给了我它。我认为这是由于分片而发生的?但是我如何重新加入一切?现在,结果如下所示:

{
  "city":"Chicago",
  "value" : {
    "num" : 2.0,
    "arr" : [{
        "num" : 2.0,
        "arr" : [{
            "num" : 1.0,
            "arr" : [{
                <user doc is here>
              }]
          }, {
            "num" : 1.0,
            "arr" : [{
                <user doc is here>
              }]
          }]
      }
.......
for many many arrays

为什么会这样?有什么方法可以将我的结果重新加入到一个连贯的单个数组中?

【问题讨论】:

    标签: javascript arrays mongodb mapreduce


    【解决方案1】:

    与分片无关,这与 Map / Reduce 逻辑有关。

    来自map 函数的value 需要与来自reduce 的返回具有相同的形状。

    请记住,reduce 可以运行多次。实际上,在分片的情况下,它将为每个分片运行一次,然后由发出请求的mongos 再次运行。

    你在思考跑步时会发生什么

    reduce(key, [a,b,c])

    要使 Map / Reduce 工作,输出必须与以下内容相同:

    reduce(key, [a, reduce(key, [b,c]) )

    reduce(key, [reduce(key, [a,b]), c] )

    在您的情况下,reduce(key, [b,c]) 返回一个数组,因此您会得到以下信息:

    reduce(key, [a, reduce(key, [b,c]) ) => reduce(key, [a, [b,c] ])

    注意到多余的数组了吗?这就是你要嵌套的原因。

    解决这个问题需要两个部分。

    1. 如果values 将是一个数组,那么emit 应该输出一个包含一项的数组。
    2. 当您进行此更改时,arr_values 将是一个“数组数组”。您必须正确组合它们。

    希望这可以为您指明正确的方向。有关更详细的调试方法,您可能需要查看Troubleshooting M/R 上的页面。

    【讨论】:

    • 谢谢,@盖茨。但我想真正的问题是,即使在解决了嵌套之后,我的结果也被分成多个数组返回。您说“正确组合它们”。我该怎么做?
    • reduce 方法中,arr_values 是一个值数组。每个值本身就是一个数组。所以你不能做resultArray.push(value);,你推的value是一个数组。因此,您将需要在 reduce 内再循环一个循环,该循环遍历每个值。
    【解决方案2】:

    我使用数组函数 Array.isArray(param) 和 indexOf(param) 来解决这类问题,但我在堆栈数组中推送唯一元素。

    if(Array.isArray(param)) {
        for(var i in param) {
           if(stack.indexOf(param[i]) == -1)
               arr.push(param[i]) ;
        }
    }
    else {
        if(stack.indexOf(param) == -1)
            arr.push(param) ;
    }
    

    你可以试试 Array.isArray()。

    【讨论】:

      猜你喜欢
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 2022-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      相关资源
      最近更新 更多