我有以下架构:
由于这是一个非结构化数据,像MongoDB这样的Flat DB非常适合。我们正在使用MongoDB。
此数据存储各个位置的客户访问信息。假设我想知道特定日期的重复访问次数。重复访问的逻辑很简单:如果一个人今天访问了一家商店,之前曾访问过同一家商店,那么他就是该商店的重复访客。
我有一个逻辑用,我可以找出重复访客的数量:
查询:按位置ID ASC,客户ID ASC,'访问时间'ASC选择*来自架构顺序
上述查询的数据排序后,如果LocationID和客户ID匹配,我们可以比较“访问时间”前一行和下一行。如果是>的差异> 1天,重复访问。
由于此数据非常庞大,因此连接类型的查询效率非常低(即使在MongoDB中也是如此)。
现在我明白MongoDB中有map reduce框架。但是,是否可以在先前记录和当前记录之间进行比较,并根据它进行一些计算,之后可以触发map / reduce?
示例:
客户A在第3天访问商店B //在第3天重复访问该客户
客户C在第2天访问商店B //首次访问客户C,而不是重复访问
客户C在第4天访问商店B //在第4天重复访问
客户D在第5天访问商店B //首次访问,而非重复访问
重复访问的最终结果:
答案 0 :(得分: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
}