Mongodb mapreduce optimization

Mongodb mapreduce optimization

本文关键字:optimization mapreduce Mongodb      更新时间:2023-09-26

我有一个存储在Mongodb上的点击集合,使用这个模式:{userid:。。。日期:。。。}

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

输出示例:

访问者数量:。。。点击次数:。。。

该集合的大小约为100万条记录。

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

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

按天计算的合计值示例:第1天:1位独特访客第2天:2个独特的访客(2个访客中的1个在第1天就成功了)

两天的唯一访客总数为3,但整个期间只有2名唯一访客,而不是3名。

在这个例子中,你有任何计算独特访客的性能方法吗?

通过在所需日期上使用单个映射减少,这个问题可能更容易解决。您可以对要检查的所有日期进行相同的聚合,而不是首先聚合一天的唯一用户(第一步)。这样你就可以完全避免第二步。

将其分解为地图和减少部分:

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

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

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

或者,还有一种更简单的方法可以做到这一点,根本不需要地图缩减。"distinct"命令(请参阅mongoDB distinct文档)允许您选择一个字段,并返回一个只填充该字段的distinct(唯一)值的数组。如果在所需的时间范围内对文档使用distinct命令,您将能够获得一个数组,该数组包含该期间的所有用户ID,并且没有任何重复。

希望这能有所帮助!

使用版本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
        }
    }
]