0

我有一个名为“事件”的集合,如下所示:

{
        "_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-reduce可以吗?

4

2 回答 2

1

由于您的用户名与集合分开存储,因此events无论如何您都需要进行两次传递。我建议使用聚合框架,然后在第二遍中将其转换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 }
    } }
);
于 2012-11-22T18:47:58.410 回答
0

对于您声明的用例,您的架构似乎构造不佳。

我建议重新考虑它并将用户名非规范化到事件集合中。

我假设用户字段是一个数组,因为多个用户可以产生每个事件 - 在这种情况下,它仍然是一个数组,但每个元素将有两个字段 - _id 就像现在一样加上代表用户名称的名称。这是相对“安全”的,因为用户名不会经常更改(如果有的话)。

拥有该架构后,您可以选择使用 MapReduce(发出 {user name, event type} 作为键),或者您可以使用聚合框架(在 2.1+ 版本中)@slee 在他的回答中描述的方式。

于 2012-11-22T20:35:41.360 回答