You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
    }
  }
])

关键逻辑解释

  1. $filter+$and:精准锁定content中类型为User且ID匹配的子文档,避免了只匹配ID带来的误判(比如Cargo的ID刚好和乘客ID重复的情况)
  2. $ne+空数组:判断筛选结果是否为空,转换成布尔值表示乘客是否参与该行程
  3. $cond+$sum:在分组阶段直接统计符合条件的行程数量,适合只需要统计数据的场景

内容的提问来源于stack exchange,提问作者kajan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:29:45