我有一个名为“events”的集合,如下所示:
{
"_id" : ObjectId("4fd89f8d3cbec825d7000001"),
"type" : "lms_course_view",
"datetime" : ISODate("2011-12-23T12:55:00Z"),
"user" : [
{
"_id" : ObjectId("4fd89f8d3cbec825d7000000")
}
]
}
另一个名为“用户”,如下:
{
"_id" : ObjectId("4fd89f8d3cbec825d7000000"),
"name" : "02ad1046f",
(...)
}
我正在尝试计算每个用户生成每种事件类型的次数。我正在尝试使用map-reduce,但我不知道如何创建一个迭代事件的map函数,同时发出用户的名字(存储在不同的集合中)。
有任何线索吗?是否可以使用map-reduce?
答案 0 :(得分:1)
由于您的用户名与events
集合分开存储,因此您无论如何都需要进行两次传递。我建议您使用Aggregation Framework,然后在第二次传递中将user["_id"]
转换为user["name"]
。聚合框架代码可能类似于:
db.events.aggregate(
{ $unwind: "$user" }, // breaks apart user array into separate documents
{ $group: {
_id: { user: "$user._id", type: "$type" }
count: { $sum: 1 }
} }
);
答案 1 :(得分:0)
您的架构似乎很难为您所陈述的用例构建。
我建议重新考虑它并将用户名非规范化为事件集合。
我假设用户字段是一个数组,因为多个用户可以生成每个事件 - 在这种情况下它仍然是一个数组,但每个元素都有两个字段 - 像现在这样的_id加上代表名称的名称用户。这是相对“安全的”,因为用户名不经常更改(如果有的话)。
一旦你有了这个模式,你可以选择使用MapReduce(发出{用户名,事件类型}作为密钥),或者你可以像@slee在他的答案中描述的那样使用聚合框架(2.1+版本)。