【问题标题】:Map/Reduce task in MongoDB: Aggregation of nested objectsMongoDB 中的 Map/Reduce 任务:嵌套对象的聚合
【发布时间】:2012-09-14 10:35:22
【问题描述】:

我有一个集合,假设内容如下:

{
    "_id":ObjectId("5051c4778ec2487f7c000001"),
    "user_id":"978956784678",
    "likes":{
        "data":[
            {
                "name":"Store 1",
                "category":"Retail and consumer merchandise",
                "id":"354412263434",
                "created_time":"2012-09-07T11:36:05+0000"
            },
            {
                "name":"Store 2",
                "category":"Retail and consumer merchandise",
                "id":"293088074081904",
                "created_time":"2012-08-13T20:06:49+0000"
            }
        ],
        "paging":{
            "next":"https://test.com/next"
        }
    }
}

我正在尝试在 MongoDB 中构建 Map/Reduce 或聚合,以提供以下输出(示意性地):

user_id、类别、“点赞数”

不知何故,我找不到合适的解决方案...到目前为止,我得到的是喜欢的类别的总聚合,但不是每个 user_id:

db.runCommand({ 
mapreduce: "likes",
map: function() { 
    this.likes.data.forEach(
       function(z){
            emit( z.category , { count : 1 } );
        }
    );
},
reduce: function(key, values) {
    var total = 0;
    for ( var i=0; i<values.length; i++ )
        total += values[i].count;
    return { count : total };
},
out: 'result3',
verbose: true
});

谁能给我一个提示?非常感谢您的帮助!

托比

【问题讨论】:

  • 你得到什么输出?
  • 结果是 { "_id" : "零售和消费品", "value" : { "count" : 2 } }
  • 这个emit( this.user_id , { count : 1 } );怎么样?

标签: json mongodb mapreduce


【解决方案1】:

如果您想使用 MR 来统计每个用户的点赞数,您可以发出 user_id 和 category 作为用于在 reduce 中对文档进行分组的键:

map: function() {
    var u = this.user_id; 
    this.likes.data.forEach(
       function(z){
            emit( {category: z.category, user: u} , { count : 1 } );
        }
    );
}

【讨论】:

  • 这很好用!我用它来收集产品评论的平均评分。但是您必须确保您的数据集包含(在示例中)具有价值的喜欢对象!
【解决方案2】:

如果可能的话,我会推荐使用新的聚合框架,它是 MongoDB 2.2 版的最新稳定版本。聚合框架是用 C++ 而不是 Javascript 编写的,并且对于许多聚合命令应该有更好的性能。

下面的 aggregate() 计算每个类别、每个用户的点赞数。如果这不是所需的输出,请告诉我。

命令:

    db.collection.aggregate(
        { $unwind : "$likes.data" }, 
        { $group : 
           {
             _id: {user: "$user_id", category: "$likes.data.category"}, 
             count: {$sum:1}
           }
        }
   );

结果:

{
    "result" : [
        {
            "_id" : {
                "user" : "978956784678",
                "category" : "Retail and consumer merchandise"
            },
            "count" : 2
        }
    ],
    "ok" : 1
}

【讨论】:

  • 珍娜,非常感谢您的回复。在这两种解决方案中,计算都是正确的。我一直在努力以我喜欢的方式格式化输出:{ "results" : [ { "user" : "100003938243508", "categories : [ { "category" : "Retail and consumer merchandise", "count" : 2 } ] } ] }
  • 嗨 Tobi,您是否希望每个用户都有一个列出所有类别的文档,即 { user: x, categories: [{category: y, count: z}, {category: l, count : j}, ...] ?或者结果是否可以为每个用户提供多个文档?
  • 嗨,Jenna,我希望为每个用户提供一组文档,就像您的选项一样。提前非常感谢!
  • 嗨,托比,对不起-我不确定这是否可能;但是,如果您找到解决方案,请告诉我们。
猜你喜欢
  • 2021-02-13
  • 2022-01-22
  • 1970-01-01
  • 2015-03-10
  • 2018-09-10
  • 2011-07-14
  • 2021-08-13
  • 2020-01-24
  • 2020-04-23
相关资源
最近更新 更多