0

我有以下架构:

  • 客户编号
  • 地点名称
  • 参观时间
  • 购买的//这是一个列表

由于这是一个非结构化数据,因此像 MongoDB 这样的 Flat DB 将是天作之合。我们正在使用 MongoDB。

该数据将客户访问信息存储在各个位置。假设我想找出某一天的重复访问次数。重复访问的逻辑很简单:如果一个人今天访问过一家商店,并且之前访问过同一家商店,那么他就是该商店的重复访问者。

我有一个逻辑,我可以使用它找出重复访问者的数量:

查询:Select * From Schema order by Location ID ASC, Client ID ASC, 'Time of Visit' ASC

对上述查询的数据进行排序后,如果 LocationID 和 Client ID 匹配,我们可以比较“访问时间”的前一行和下一行。如果差异 > 1 天,则重复访问。

由于这些数据非常庞大,连接类型的查询将非常低效(即使在 MongoDB 中是可能的)。

现在我知道 MongoDB 中有 map reduce 框架。但是,是否可以在之前和当前记录之间进行比较,并在此基础上进行一些计算,之后可以触发 map/reduce?

例子 :

  • 客户 A 在第 1 天访问商店 B // 没有重复访问
  • 客户 A 在第 1 天再次访问商店 B // 仍然没有重复访问
  • 客户 A 在第 2 天访问商店 B // 在第 2 天重复访问此客户 A
  • 客户 A 在第 2 天访问商店 B // 已计为第 2 天的重复访问
  • 客户 A 在第 3 天访问商店 B // 在第 3 天重复访问该客户

  • 客户 C 在第 2 天访问商店 B // 客户 C​​ 第一次访问,而不是重复访问

  • 客户 C 在第 2 天再次访问商店 B // 第一天访问,而不是重复访问
  • 客户 C 在第 3 天访问 B 商店 // 在第 3 天重复访问
  • 客户 C 在第 4 天访问商店 B // 在第 4 天重复访问

  • 客户 D 在第 5 天访问 B 商店 // 第一次访问,而不是重复访问

重复访问的最终输出:

  • B 店,第 1 天:0 次重复访问
  • B 店,第 2 天:2 次重复访问
  • B 店,第 3 天:2 次重复访问
  • B 店,第 4 天:1 次重复访问
  • B 店,第 5 天:0 次重复访问
4

1 回答 1

0

如果您在关系数据库中执行此操作,您将不会逐行比较访问,而是使用聚合查询来查找重复访问(使用 SELECT ... GROUP BY),因此您应该在 MongoDB 中以相同的方式执行此操作。

首先,您需要汇总每个客户每天每个商店的访问量:

group1 = { "$group" : {
        "_id" : {
            "c" : "$clientId",
            "l" : "$location",
            "day" : {
                "y" : {
                    "$year" : "$tov"
                },
                "m" : {
                    "$month" : "$tov"
                },
                "d" : {
                    "$dayOfMonth" : "$tov"
                }
            }
        },
        "visits" : {
            "$sum" : 1
        }
    }
};

编辑因为您只想重复 DAYS 接下来您将按客户、按商店分组并计算该客户访问该商店有多少不同的 DAYS:

group2 = {"$group" : 
    {"_id" : {
        "c" : "$_id.c",
        "s" : "$_id.l"
    },
    "totalDays" : {
        "$sum" : 1
    }
} };

然后,您只想包含上述记录,其中同一客户在多天内多次访问同一商店:

match = { "$match" : { "totalDays" : { "$gt" : 1 } } };

这是一个示例数据集以及使用上述管道操作聚合的结果:

> db.visits.find({},{_id:0,purchases:0}).sort({location:1, clientId:1, tov:1})
{ "clientId" : 1, "location" : "l1", "tov" : ISODate("2013-01-01T20:00:00Z") }
{ "clientId" : 1, "location" : "l1", "tov" : ISODate("2013-01-01T21:00:00Z") }
{ "clientId" : 1, "location" : "l1", "tov" : ISODate("2013-01-03T20:00:00Z") }
{ "clientId" : 2, "location" : "l1", "tov" : ISODate("2013-01-01T21:00:00Z") }
{ "clientId" : 3, "location" : "l1", "tov" : ISODate("2013-01-01T21:00:00Z") }
{ "clientId" : 3, "location" : "l1", "tov" : ISODate("2013-01-02T21:00:00Z") }
{ "clientId" : 1, "location" : "l2", "tov" : ISODate("2013-01-01T23:00:00Z") }
{ "clientId" : 3, "location" : "l2", "tov" : ISODate("2013-01-02T21:00:00Z") }
{ "clientId" : 3, "location" : "l2", "tov" : ISODate("2013-01-02T21:00:00Z") }
{ "clientId" : 1, "location" : "l3", "tov" : ISODate("2013-01-03T20:00:00Z") }
{ "clientId" : 2, "location" : "l3", "tov" : ISODate("2013-01-04T20:00:00Z") }
{ "clientId" : 4, "location" : "l3", "tov" : ISODate("2013-01-04T20:00:00Z") }
{ "clientId" : 4, "location" : "l3", "tov" : ISODate("2013-01-04T21:00:00Z") }
{ "clientId" : 4, "location" : "l3", "tov" : ISODate("2013-01-04T22:00:00Z") }

> db.visits.aggregate(group1, group2, match)
{
    "result" : [
    {
        "_id" : {
            "c" : 3,
            "s" : "l1"
        },
        "totalDays" : 2
    },
    {
        "_id" : {
            "c" : 1,
            "s" : "l1"
        },
        "totalDays" : 2
    }
    ],
    "ok" : 1
}
于 2013-05-13T17:00:26.333 回答