MongoDB中按日期分组统计数组元素重复次数的查询方法
MongoDB多时间维度热门标签统计方案
核心实现逻辑基于MongoDB聚合管道能力,先按时间范围过滤文档,再拆分标签数组、统计标签出现频次、按频次排序后输出热门标签列表,以下是具体实现代码(假设集合名为posts):
1. 分维度单独查询
最近1小时热门标签
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000); db.posts.aggregate([ // 过滤时间范围内的文档 { $match: { created_at: { $gte: oneHourAgo } } }, // 拆分tags数组为单标签文档 { $unwind: "$tags" }, // 按标签分组统计出现次数 { $group: { _id: "$tags", count: { $sum: 1 } } }, // 按出现次数倒序排序 { $sort: { count: -1 } }, // 取前3个热门标签,可按需调整数值 { $limit: 3 }, // 拼接为标签数组 { $group: { _id: null, hotTags: { $push: "$_id" } } }, // 调整输出格式 { $project: { _id: 0, "最近1小时热门标签": "$hotTags" } } ])
最近5小时热门标签
const fiveHoursAgo = new Date(Date.now() - 5 * 60 * 60 * 1000); db.posts.aggregate([ { $match: { created_at: { $gte: fiveHoursAgo } } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 3 }, { $group: { _id: null, hotTags: { $push: "$_id" } } }, { $project: { _id: 0, "最近5小时热门标签": "$hotTags" } } ])
今日热门标签
// 取当日0点作为起始时间 const todayStart = new Date(); todayStart.setHours(0, 0, 0, 0); db.posts.aggregate([ { $match: { created_at: { $gte: todayStart } } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 3 }, { $group: { _id: null, hotTags: { $push: "$_id" } } }, { $project: { _id: 0, "今日热门标签": "$hotTags" } } ])
本月热门标签
// 取当月1日0点作为起始时间 const monthStart = new Date(); monthStart.setDate(1); monthStart.setHours(0, 0, 0, 0); db.posts.aggregate([ { $match: { created_at: { $gte: monthStart } } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 3 }, { $group: { _id: null, hotTags: { $push: "$_id" } } }, { $project: { _id: 0, "本月热门标签": "$hotTags" } } ])
2. 一次性返回所有维度结果
使用$facet阶段可在一次查询中完成所有维度统计,减少数据库请求次数:
const now = Date.now(); const oneHourAgo = new Date(now - 60 * 60 * 1000); const fiveHoursAgo = new Date(now - 5 * 60 * 60 * 1000); const todayStart = new Date(); todayStart.setHours(0, 0, 0, 0); const monthStart = new Date(); monthStart.setDate(1); monthStart.setHours(0, 0, 0, 0); db.posts.aggregate([ { $facet: { "最近1小时热门标签": [ { $match: { created_at: { $gte: oneHourAgo } } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 3 }, { $group: { _id: null, tags: { $push: "$_id" } } }, { $project: { _id: 0, tags: 1 } } ], "最近5小时热门标签": [ { $match: { created_at: { $gte: fiveHoursAgo } } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 3 }, { $group: { _id: null, tags: { $push: "$_id" } } }, { $project: { _id: 0, tags: 1 } } ], "今日热门标签": [ { $match: { created_at: { $gte: todayStart } } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 3 }, { $group: { _id: null, tags: { $push: "$_id" } } }, { $project: { _id: 0, tags: 1 } } ], "本月热门标签": [ { $match: { created_at: { $gte: monthStart } } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 3 }, { $group: { _id: null, tags: { $push: "$_id" } } }, { $project: { _id: 0, tags: 1 } } ] } }, // 调整输出格式匹配需求 { $project: { "最近1小时热门标签": { $arrayElemAt: ["$最近1小时热门标签.tags", 0] }, "最近5小时热门标签": { $arrayElemAt: ["$最近5小时热门标签.tags", 0] }, "今日热门标签": { $arrayElemAt: ["$今日热门标签.tags", 0] }, "本月热门标签": { $arrayElemAt: ["$本月热门标签.tags", 0] } } } ])
输出结果示例:
{ "最近1小时热门标签" : ["PHP", "database", "mongodb"], "最近5小时热门标签" : ["database", "PHP", "NoSQL"], "今日热门标签" : ["PHP", "database", "NoSQL"], "本月热门标签" : ["PHP", "database", "NoSQL"] }
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

