1

我有一个存储在 Mongodb 上的命中集合,使用这个模式:{ userid: ... date: ... }

我想显示一个报告,计算两个日期之间的唯一访问者(具有不同用户 ID 在这些日期之间取得成功的访问者)。

输出示例:

访问者人数:...点击次数:...

该集合的大小约为 1M 条记录。

我的第一个想法是进行增量 mapreduce 以按天计算聚合值。然后在天上进行第二次 mapreduce 以输出最终结果。

问题是当在报告中选择一系列日期时,我无法计算正确的唯一身份访问者数量。

按天汇总的值示例: 第 1 天:1 位唯一身份访问者 第 2 天:2 位唯一身份访问者(2 位访问者中有 1 位在第 1 天获得成功)

这两天的独立访问者总数为 3,但整个期间只有 2 个独立访问者,而不是 3 个。

在此示例中,您有任何计算唯一访问者的高效方法吗?

4

2 回答 2

3

通过在所需日期上使用单个 map-reduce 可能更容易解决此问题。无需首先聚合一天的唯一用户(您的第一步),您可以对要检查的所有日期进行相同的聚合。通过这种方式,您可以完全避免第二步。

要将其分解为 Map 和 Reduce 部分:

地图:查找在所需时间范围内记录的所有用户标识

减少:删除所有重复的用户标识

完成此过程后,您应该留下该时间范围内的一组唯一访问者(更具体地说,唯一用户 ID)。

或者,有一种更简单的方法可以做到这一点,根本不需要 map-reduce。“distinct”命令(参见mongoDB distinct 文档)允许您选择一个字段并返回一个仅填充该字段的不同(唯一)值的数组。如果您在所需时间范围内对文档使用 distinct 命令,您将能够获得一个数组,其中包含该时期内的所有用户 ID,没有任何重复。

希望这可以帮助!

于 2012-08-30T19:53:00.137 回答
0

您可以使用 2.2 版及其聚合框架轻松完成此操作。

假设架构 {userid: " ", date: " "} 并给出两个特定日期 d1 和 d2 这是管道:

db.collection.aggregate(
[
    {
        "$match" : {
            "date" : {
                "$gte" : d1,
                "$lte" : d2
            }
        }
    },
    {
        "$group" : {
            "_id" : "$userid",
            "hits" : {
                "$sum" : 1
            }
        }
    },
    {
        "$group" : {
            "_id" : "1",
            "visitors" : {
                "$sum" : 1
            },
            "hits" : {
                "$sum" : "$hits"
            }
        }
    },
    {
        "$project" : {
            "_id" : 0,
            "visitors" : 1,
            "hits" : 1
        }
    }
]
于 2012-08-31T00:53:49.030 回答