如何在MongoDB中用IN子句聚合统计用户最近N条URL
实现每个用户最近N条访问记录的URL聚合统计
这问题我熟!要完成你想要的统计需求——只针对每个用户最近N条访问记录里的URL做聚合,咱们可以用MongoDB的聚合管道来一步步搞定。下面直接上方案:
核心思路
先把每个用户的访问记录按时间倒序排序,提取出每个用户最近的N条记录,再把这些记录展开后,对URL进行分组统计次数。
聚合查询代码(以N=2为例)
db.mycollection.aggregate([ // 第一步:按用户分组,同时把每个用户的访问记录按时间倒序排列,取前2条 { $sort: { user: 1, time: -1 } // 先按user分组排序,再按time倒序(最新的在前) }, { $group: { _id: "$user", recentUrls: { $push: { url: "$url", time: "$time" } } // 把每个用户的记录按排序后的顺序存入数组 } }, { $project: { recentUrls: { $slice: ["$recentUrls", 2] } // 截取数组的前2条,也就是最近的2条记录 } }, // 第二步:把每个用户的最近N条记录展开成单个文档 { $unwind: "$recentUrls" }, // 第三步:对URL进行分组统计出现次数 { $group: { _id: "$recentUrls.url", count: { $sum: 1 } // 统计每个URL的出现次数 } }, // 可选:把结果字段名改得更直观 { $project: { url: "$_id", count: 1, _id: 0 } } ])
代码解释
- $sort阶段:先按
user升序排列,再按time降序排列,这样每个用户的记录都是最新的排在最前面。 - $group阶段:按
user分组,用$push把每个用户的所有访问记录(按排序后的顺序)存入recentUrls数组。 - $project阶段:用
$slice截取recentUrls数组的前N条(这里是2),只保留每个用户最近的N条记录。 - $unwind阶段:把每个用户的
recentUrls数组拆分成单个文档,方便后续统计。 - 最后两个$group和$project阶段:按URL分组统计次数,并把结果字段调整成更易读的格式。
针对你提供的样本数据的输出结果
假设你的样本数据是:
{ "url" : "a1", "user" : "b1", "time" : ISODate("2017-12-25T00:45:22.148Z") } { "url" : "a2", "user" : "b2", "time" : ISODate("2017-12-24T22:45:22.148Z") } { "url" : "a3", "user" : "b1", "time" : ISODate("2017-12-24T21:45:22.148Z") }
运行上述查询(N=2)后,会得到:
{ "count" : 1, "url" : "a1" } { "count" : 1, "url" : "a2" } { "count" : 1, "url" : "a3" }
因为b1的最近2条是a1和a3,b2的最近2条只有a2,三个URL各出现一次。
如果要调整N的值,只需要把$slice里的2改成你想要的数字就行啦!
内容的提问来源于stack exchange,提问作者proximator
相关产品推荐
相关产品推荐

