MongoDB聚合:按司机分组行程并在$project验证乘客为User类型
解决MongoDB聚合中校验子文档类型+ID匹配的问题
没问题,我帮你搞定这个需求!你之前的思路是对的,但确实缺少了类型校验的环节——毕竟content数组里混着User、Cargo等不同类型的项,光匹配ID会出现误判。下面直接给你可行的实现方案:
核心思路
在$project(或$group)阶段,通过$filter精准筛选content中同时满足类型为User和ID匹配指定乘客的子文档,再通过判断筛选结果是否为空,得到最终的traveled布尔值。
完整聚合管道示例
假设你的行程集合名为trips,字段结构大概是:
{ _id: ObjectId("行程ID"), companyId: ObjectId("公司ID"), busDriverId: ObjectId("司机ID"), departureTime: ISODate("出发时间"), content: [ { type: "User", item: ObjectId("乘客ID") }, { type: "Cargo", item: ObjectId("货物ID") } // ...其他类型项 ] }
方案1:按司机分组,返回每个司机的所有行程+乘客参与状态
db.trips.aggregate([ // 第一步:先筛选目标公司的所有行程 { $match: { companyId: ObjectId("替换成你的公司ID") } }, // 第二步:按巴士司机ID分组,聚合该司机的所有行程 { $group: { _id: "$busDriverId", trips: { $push: "$$ROOT" } // 把司机的所有行程存入数组 } }, // 第三步:处理每个行程,生成乘客参与状态 { $project: { driverId: "$_id", trips: { $map: { input: "$trips", as: "trip", in: { // 保留你需要的行程基础字段 tripId: "$$trip._id", departureTime: "$$trip.departureTime", // 核心逻辑:校验乘客是否以User类型参与 traveled: { $ne: [ { $filter: { input: "$$trip.content", as: "item", cond: { $and: [ { $eq: ["$$item.type", "User"] }, // 必须是User类型 { $eq: ["$$item.item", ObjectId("替换成指定乘客ID")] } // 匹配乘客ID ] } } }, [] // 如果过滤结果不是空数组,说明乘客参与了 ] } } } }, _id: 0 // 隐藏默认的_id字段 } } ])
方案2:按司机分组,直接统计乘客参与的行程数量
如果不需要返回每个行程的细节,只想统计每个司机下该乘客参与的行程数,可以简化成:
db.trips.aggregate([ { $match: { companyId: ObjectId("替换成你的公司ID") } }, { $group: { _id: "$busDriverId", totalTrips: { $sum: 1 }, // 司机总行程数 passengerTraveledCount: { $sum: { $cond: [ // 判断条件:是否存在符合要求的User项 { $ne: [ { $filter: { input: "$content", as: "item", cond: { $and: [ { $eq: ["$$item.type", "User"] }, { $eq: ["$$item.item", ObjectId("替换成指定乘客ID")] } ] } } }, [] ] }, 1, // 符合条件加1 0 // 不符合加0 ] } } } }, { $project: { driverId: "$_id", totalTrips: 1, passengerTraveledCount: 1, hasPassengerTrips: { $gt: ["$passengerTraveledCount", 0] }, // 是否有乘客参与的行程 _id: 0 } } ])
关键逻辑解释
$filter+$and:精准锁定content中类型为User且ID匹配的子文档,避免了只匹配ID带来的误判(比如Cargo的ID刚好和乘客ID重复的情况)$ne+空数组:判断筛选结果是否为空,转换成布尔值表示乘客是否参与该行程$cond+$sum:在分组阶段直接统计符合条件的行程数量,适合只需要统计数据的场景
内容的提问来源于stack exchange,提问作者kajan
相关产品推荐
相关产品推荐

