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

如何在MongoDB中关联多集合查询指定员工的服务及对应分类

问题解答

MongoDB完全支持关联超过2个集合的查询,通过聚合管道的$lookup即可实现,你现有查询的问题主要出在3个细节上:

  • 第一个$lookup的from参数写错:你的服务集合名称是services,你写的是service,导致关联不到服务数据
  • 数据类型不匹配:services集合里的service_category_id是字符串类型,service_category的_id是ObjectId类型,类型不一致导致第二个$lookup关联失败
  • 后续结构重组逻辑不符合预期,缺少分组和字段映射步骤

调整后的完整查询语句

db.staff_services.aggregate([
  // 第一步:筛选指定员工的服务关联记录
  {
    "$match": {
      "staffs.id": ObjectId("STAFF-A")
    }
  },
  // 第二步:关联services集合
  {
    $lookup: {
      from: "services",
      localField: "service_id",
      foreignField: "_id",
      as: "service_info"
    }
  },
  // 拆分数组,每个服务单独成一条文档
  { $unwind: "$service_info" },
  // 第三步:转换service_category_id为ObjectId类型,解决类型不匹配问题
  {
    $addFields: {
      "service_info.service_category_id": {
        $toObjectId: "$service_info.service_category_id"
      }
    }
  },
  // 第四步:关联服务分类集合
  {
    $lookup: {
      from: "service_category",
      localField: "service_info.service_category_id",
      foreignField: "_id",
      as: "category_info"
    }
  },
  { $unwind: "$category_info" },
  // 第五步:按分类分组,把同分类的服务归到一起
  {
    $group: {
      _id: "$category_info._id",
      category_name: { $first: "$category_info.name" },
      services: {
        $push: {
          id: "$service_info._id",
          name: "$service_info.name"
        }
      }
    }
  },
  // 第六步:重组分类的字段格式
  {
    $project: {
      _id: 0,
      id: "$_id",
      name: "$category_name",
      services: 1
    }
  },
  // 第七步:最后组装成你要的输出结构
  {
    $group: {
      _id: null,
      category: { $push: "$$ROOT" },
      staff_id: { $first: ObjectId("STAFF-A") }
    }
  },
  {
    $project: {
      _id: 0,
      staff_id: 1,
      category: 1
    }
  }
])

如果你实际存储中services集合的service_category_id本身就是ObjectId类型,直接去掉第三步的类型转换$addFields阶段即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 22:36:03