如何编写MongoDB查询获取近7天周边每分钟浏览量Top10商品
前置准备
请先提前创建索引优化查询性能:
- Pin集合创建2dsphere地理位置索引:
db.Pin.createIndex({"latlong": "2dsphere"}) - mostLovedPins集合创建pin和date的复合索引:
db.mostLovedPins.createIndex({"pin": 1, "date": 1})
需求1:统计特定经纬度半径范围内商品近7天总浏览量
需要替换的参数:
[<目标经度>, <目标纬度>]:替换为你要查询的中心点经纬度,注意MongoDB地理位置坐标格式为经度在前、纬度在后<半径数值(单位:米)>:替换为你要查询的半径范围,比如查询5公里内填5000
// 计算7天前的起始日期 const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); db.Pin.aggregate([ // 筛选指定经纬度半径范围内、已发布且审核通过的商品 { $geoNear: { near: { type: "Point", coordinates: [<目标经度>, <目标纬度>] }, distanceField: "distance", maxDistance: <半径数值(单位:米)>, spherical: true, query: { is_published: true, is_approved_by_admin: true } } }, // 关联mostLovedPins集合,匹配对应商品近7天的浏览记录 { $lookup: { from: "mostLovedPins", let: { pinId: "$_id" }, pipeline: [ { $match: { $expr: { $eq: ["$pin", "$$pinId"] }, date: { $gte: sevenDaysAgo } } }, { $group: { _id: null, totalView: { $sum: "$view_count" } } } ], as: "viewStats" } }, // 格式化输出字段,无浏览记录的商品总浏览量默认设为0 { $addFields: { totalViewCount: { $ifNull: [{ $first: "$viewStats.totalView" }, 0] } } }, // 可选:按总浏览量降序排序 { $sort: { totalViewCount: -1 } }, // 可选:移除不需要的冗余字段 { $unset: ["viewStats", "_cls"] } ])
需求2:提取近7天内每分钟浏览量最高的前10个商品
统计逻辑为:近7天总浏览量 ÷ 近7天总分钟数(72460=10080)得到每分钟平均浏览量,排序后取前10,你也可以根据实际业务调整统计逻辑。如果需要限制在指定经纬度范围内,可以打开代码中注释的地理位置筛选条件,半径换算方式为实际半径(公里)/ 6378.1,比如5公里就是5/6378.1。
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); const totalMinutes = 7 * 24 * 60; db.mostLovedPins.aggregate([ // 筛选近7天的浏览记录 { $match: { date: { $gte: sevenDaysAgo } } }, // 按商品ID分组,统计单商品总浏览量 { $group: { _id: "$pin", totalView: { $sum: "$view_count" } } }, // 关联Pin集合,过滤已发布、审核通过的有效商品 { $lookup: { from: "Pin", let: { pinId: "$_id" }, pipeline: [ { $match: { $expr: { $eq: ["$_id", "$$pinId"] }, is_published: true, is_approved_by_admin: true, // 可选:开启后可限制仅查询指定经纬度范围内的商品 // latlong: { // $geoWithin: { // $centerSphere: [[<目标经度>, <目标纬度>], <半径(单位:弧度)>] // } // } } } ], as: "pinInfo" } }, // 过滤掉不存在的无效商品记录 { $match: { pinInfo: { $ne: [] } } }, // 计算每分钟平均浏览量,格式化商品信息 { $addFields: { viewPerMinute: { $divide: ["$totalView", totalMinutes] }, pinInfo: { $first: "$pinInfo" } } }, // 按每分钟浏览量降序排序 { $sort: { viewPerMinute: -1 } }, // 取前10条结果 { $limit: 10 }, // 可选:格式化最终输出字段 { $project: { _id: 0, pinId: "$_id", title: "$pinInfo.title", description: "$pinInfo.description", totalView: 1, viewPerMinute: 1 } } ])
内容的提问来源于stack exchange,提问作者Nitesh Kumar
相关产品推荐
相关产品推荐

