求用于统计存在日程冲突用户数量的MongoDB查询语句
统计MongoDB中存在日程冲突的userID数量
要搞定这个统计有日程冲突用户数量的需求,咱们可以用MongoDB的聚合框架来实现,先明确核心的冲突判断逻辑:两个日程存在重叠的条件是:A的start时间小于B的end时间,同时B的start时间小于A的end时间。另外注意示例里的start/end是字符串格式的数字,需要先转成整数再比较。
完整查询语句
db.collection.aggregate([ // 第一步:按userID分组,收集每个用户的所有日程(转换时间为整数) { $group: { _id: "$userID", schedules: { $push: { start: { $toInt: "$start" }, end: { $toInt: "$end" } } } } }, // 第二步:判断每个用户是否存在日程冲突 { $addFields: { hasConflict: { $anyElementTrue: { $map: { input: "$schedules", as: "s1", in: { $gt: [ { $size: { $filter: { input: "$schedules", as: "s2", cond: { $and: [ { $ne: ["$$s1", "$$s2"] }, // 排除和自己比较 { $lt: ["$$s1.start", "$$s2.end"] }, { $lt: ["$$s2.start", "$$s1.end"] } ] } } } }, 0 ] } } } } } }, // 第三步:筛选出有冲突的用户 { $match: { hasConflict: true } }, // 第四步:统计符合条件的用户数量 { $count: "conflictedUserCount" } ])
各步骤说明
- $group阶段:把同一个userID的所有日程聚合到一起,同时将字符串类型的start/end转为整数,避免字符串比较带来的误差(比如"10"作为字符串会比"2"小)。
- $addFields阶段:通过嵌套的聚合操作判断冲突:
- 用
$map遍历每个日程s1,对每个s1用$filter找出所有和它重叠的其他日程s2; - 如果筛选出的
s2数量大于0,说明s1存在冲突,返回true; - 最后用
$anyElementTrue判断该用户是否存在至少一组冲突的日程,结果存入hasConflict字段。
- 用
- $match阶段:只保留
hasConflict为true的用户数据。 - $count阶段:统计最终符合条件的用户总数,结果以
conflictedUserCount字段返回。
示例数据验证
针对你给出的示例数据,执行这个查询后会返回{ "conflictedUserCount": 1 },因为只有userID 123的两个日程存在重叠,userID 124的日程没有冲突。
内容的提问来源于stack exchange,提问作者Doctor White
相关产品推荐
相关产品推荐

