我是MongoDB和Map-Reduce的新手,我无法找到问题的解决方案。
我有多个文档存储了“user_id”和一组不同的项目。 user_id不是唯一的。我想要一个集合,我可以看到用户使用某个项目的次数。
文件如下:
db.items.find()
{"items": ["abc", "def", ghi], "user_id": 328252955}
{"items": ["klm"], "user_id": 328250000}
{"items": ["abc", ghi], "user_id": 328252955}
我想要这样的事情:
{ "_id" : { "user_id" : 328252955},
"value" : [{"items": "abc", "count" : 2},{"items": "ghi", "count" : 2},{"items": "def", "count" : 1}]
}
{ "_id" : { "user_id" : 328250000},
"value" : [{"items": "klm", "count" : 1}]
}
但是我能想到的最好的解决方案并不是那样的,因为如果用户使用多种项目,文档会有另一种结构。
看起来像这样:
{ "_id" : { "user_id" : 328252955 },
"value" : {
"preferences" : [[{"items": "abc", "count" : 2},{"items": "ghi", "count" : 2},{"items": "def", "count" : 1}]]
}
}
{ "_id" : { "user_id" : 328250000},
"value" : {"items": "klm", "count" : 1}
}
DEF
为此,我将user_id和items映射到一个键,并将“count:1”作为值发出。 结果文档如下所示:
db.items_01.find()
{ "_id" : { "user_id" : 328250000, "items" : [ "klm" ] }, "value" : { "count" : 1 } }
{ "_id" : { "user_id" : 328252955, "items" : [ "abc" ] }, "value" : { "count" : 2 } }
{ "_id" : { "user_id" : 328252955, "items" : [ "ghi" ] }, "value" : { "count" : 2 } }
{ "_id" : { "user_id" : 328252955, "items" : [ "def" ] }, "value" : { "count" : 1 } }
Map-Reduce:
map = function() {
if (this.items == null){
return;
}
for(var i in this.items){
key = { user_id: this.user_id, items: this.items[i] };
value = { count: 1 };
emit(key, value);
}
}
function reduce(key, values) {
var cnt = 0;
for (var i = 0; i < values.length; i++) {
cnt += 1;
}
return { count: cnt };
}
db.items.mapReduce(map, reduce, "items_01")
为了获得上面显示的最终输出,我使用了另一个Map-Reduce函数,其中我使用user_id作为键,使用“items”和“count”作为值。
Map-Reduce:
map = function() {
key = { user_id: this._id.user_id };
value = {items: this._id.items, count: this.value.count};
emit(key, value);
}
reduce = function(key, values) {
return {preferences:[values]};
}
db.items_01.mapReduce(map, reduce, "items_01_01")
我知道我无法返回values数组。但我还能做些什么呢?
感谢您的帮助。非常感谢。我已经花了好几天时间,我仍在努力寻找最佳解决方案。
答案 0 :(得分:0)
您应该可以执行以下操作:
db.items.aggregate(
{$project: { items: 1, user_id: 1}},
{$unwind: "$items"},
{ $group:
{ _id: { user_id: "$user_id", item: "$items" },
count: { $sum: 1 }
}
})
选择/缩小将在聚合中使用的字段:
{$project: { items: 1, user_id: 1}}
这会展开items
数组。这意味着对于items
数组中的每个项目,管道将具有一个不同的文档,其中包含在第一步中投影的字段:
{$unwind: "$items"},
结果:
{
"_id" : ObjectId("52dbed562c3f37cf53664faf"),
"items" : "abc",
"user_id" : 328252955
},
{
"_id" : ObjectId("52dbed562c3f37cf53664faf"),
"items" : "def",
"user_id" : 328252955
}, // ETC...
然后,最后$group
和user_id
上的item
分组(我已使用语法item: "$items"
将其重命名为项目)。对于每个不同的分组值,使用1
的{{1}}将count
添加到名为$sum
的新字段中。
1
使用您的示例数据会导致类似:
{ $group:
{ _id: { user_id: "$user_id", item: "$items" },
count: { $sum: 1 }
}
}