MongoDB中的Map/Reduce任务:嵌套对象的聚合

3

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

{
    "_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或聚合,以给出以下输出(原理图):

用户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
});

有人能给我一个提示吗?非常感谢帮助! 托比

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

2

如果您想使用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 } );
        }
    );
}

这个非常好用!我用它来收集产品评论的评分平均值。但是你必须确保你的数据集包括(在本例中)带有值的 likes 对象! - DJ.

1
如果可能的话,我建议使用新的聚合框架,它是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
}

Jenna,非常感谢你的回复。在这两个解决方案中,计算都是正确的。我仍然在努力以我所期望的方式格式化输出: `{ "results" : [ { "user" : "100003938243508", "categories : [ { "category" : "Retail and consumer merchandise", "count" : 2 } ] } ] }` - Tobi
嗨Tobi,你想让每个用户都有一个列出所有类别的单个文档吗?例如 { user: x, categories: [{category: y, count: z}, {category: l, count: j}, ...] }?还是结果可以为每个用户有多个文档? - Jenna
嗨Jenna,我更喜欢每个用户都有一个单独的文件作为结果,就像你提出的第一种选择。非常感谢你提前的帮助! - Tobi
嗨Tobi,很抱歉-我不确定这是否可能;但是,如果您找到解决方案,请告诉我们。 - Jenna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接