【问题标题】:mongodb mapreduce - build an array or object in the reduce?mongodb mapreduce - 在reduce 中构建一个数组或对象?
【发布时间】:2011-01-04 22:11:52
【问题描述】:

原始收藏:

{ 
"_id" : ObjectId('xxxxxxxxxxxxxxxx'),
  "userId" : ObjectId('yyyyyyyyyyyyyyyy'),
  "urlId" : ObjectId('zzzzzzzzzzzzzzzzzz')
},
{ 
  "_id" : ObjectId('uuuuuuuuuuuuuuuuuu'),
  "userId" : ObjectId('aaaaaaaaaaaaaaaa'),
  "urlId" : ObjectId('zzzzzzzzzzzzzzzzzz')
}

发射:

emit(this.urlId, {userId: this.userId, visitCount: this.visitCount});

减少:

function(key, values) {
    var visitCount = 0;
    var userVC = new Array();
    values.forEach(function(doc) {


NOT SURE WHAT TO PUT HERE TO ACHIEVE DESIRED OUTPUT COLLECTION


    });
    return {urlId: key, userVC: userVC};
};

期望的 MR 输出集合:

{
   "_id" : ObjectId('zzzzzzzzzzzzzzzzzzzz'),
   "value" : {
       "urlId" : ObjectId('zzzzzzzzzzzzzzzzzzzz'),
       "userVC" : {
              ObjectId('yyyyyyyyyyyyyyyy') : <total visit count for this userId on this urlId>,
              ObjectId('aaaaaaaaaaaaaaaa') : <total visit count for this userId on this urlId>
       }
}

【问题讨论】:

    标签: mongodb mapreduce


    【解决方案1】:

    您想知道每个用户访问您网站上各个网址的次数吗?我想你会想以不同的方式解决这个问题。

    发送网址/用户访问次数:

    emit( { urlId: this.urlId, userId: this.userId }, { count: 1 } );
    

    用 reduce 计算它们:

    r = function( key , values ){
        var total = 0;
        for ( var i=0; i<values.length; i++ )
            total += values[i].count;
        return { count : total };
    };
    

    如果你真的想要你所说的期望输出,你可以在 finalize 步骤中做到这一点。但我认为它不能很好地扩展到 N 个用户。

    这里是一个不完全满足您既定目标的链接,但我发现在尝试了解这些 mongodb mapreduce 函数如何工作时非常有用:

    http://cookbook.mongodb.org/patterns/unique_items_map_reduce/

    【讨论】:

    • 第二个 map-reduce 操作可用于将具有用户和 url 键的集合转换为具有用户键和计数数组值的集合。
    • 由于您要分配一个来计数,因此对( var i=0; i&lt;values.length; i++ ) total += values[i].count; 执行此操作等效于total = values.length;
    • 不是这样@Danielo515。我们在 map 中分配计数 1,但 reduce 可以以任意顺序发生多次,将 map 中的发出值与子集中先前减少的值混合。换句话说,在reduce函数内部,计数并不总是1。
    【解决方案2】:

    对于其他试图在 reduce 函数中解决此问题的人:

    function reduce(key, values) {
      const result = {
        list: [],
        ...
      };
    
      // keep track of reduced records to avoid duplicate list entries
      const processed = {
        list: [],
        ...
      };
    
      values.forEach((value, index) => {
        if (value.listItem && value.listItem.length > 0) {
    
          // our value is an array as MongoDB needs to be strongly typed (same as reduced type)
          if (processed.list.indexOf(value.listItem[0].key) === -1) {
            result.list = result.list.concat(value.listItem);
          }
    
        }
        ...
      });
    
      return result;
    }
    

    reduce 函数在 MongoDB 的上下文中运行,因此您需要了解支持的函数中的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-23
      • 2012-06-16
      • 1970-01-01
      • 2014-05-02
      • 1970-01-01
      • 2013-11-27
      • 1970-01-01
      • 2021-12-07
      相关资源
      最近更新 更多