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

如何用MongoDB聚合管道关联两集合获取每本书所属分组

问题:获取每本书对应的所属分组(MongoDB聚合查询)

集合结构

Books集合

[
  {
    "BOOK_ID": "100",
    "BOOK_NAME": "Book 1",
    "BOOK_DESC": "abcd"
  },
  {
    "BOOK_ID": "101",
    "BOOK_NAME": "Book 2",
    "BOOK_DESC": "efgh"
  },
  {
    "BOOK_ID": "102",
    "BOOK_NAME": "Book 3",
    "BOOK_DESC": "ijkl"
  }
]

BookGroup集合

[
  {
    "GROUP_ID": "100",
    "GROUP_NAME": "G1",
    "GROUPS": [
      {
        "BOOK_ID": "100",
        "BOOK_NAME": "Book 1"
      },
      {
        "BOOK_ID": "101",
        "BOOK_NAME": "Book 2"
      }
    ]
  },
  {
    "GROUP_ID": "101",
    "GROUP_NAME": "G2",
    "GROUPS": [
      {
        "BOOK_ID": "101",
        "BOOK_NAME": "Book 2"
      }
    ]
  },
  {
    "GROUP_ID": "102",
    "GROUP_NAME": "G3",
    "GROUPS": [
      {
        "BOOK_ID": "100",
        "BOOK_NAME": "Book 1"
      },
      {
        "BOOK_ID": "102",
        "BOOK_NAME": "Book 3"
      }
    ]
  }
]

已实现的单本书查询

针对单本书(如Book 2)获取所属分组的聚合查询:

db.BookGroup.aggregate([
  { "$unwind": "$GROUPS" },
  { "$match": { "GROUPS.BOOK_NAME": "Book 2" } },
  {
    "$group": {
      "_id": null,
      "group_name": { "$push": "$GROUP_NAME" }
    }
  },
  { "$project": { "_id": false, "group_name": true } }
])

返回结果:

[
  {
    "group_name": ["G1", "G2"]
  }
]

解决方案:获取每本书的所属分组

要实现返回所有书籍及其对应分组的需求,可以使用以下聚合管道:

db.Books.aggregate([
  {
    "$lookup": {
      "from": "BookGroup",
      "let": { "bookId": "$BOOK_ID" },
      "pipeline": [
        { "$unwind": "$GROUPS" },
        { "$match": { "$expr": { "$eq": ["$GROUPS.BOOK_ID", "$$bookId"] } } },
        { "$group": { "_id": null, "groups": { "$push": "$GROUP_NAME" } } },
        { "$project": { "_id": 0, "group_name": "$groups" } }
      ],
      "as": "group_info"
    }
  },
  { "$unwind": { "path": "$group_info", "preserveNullAndEmptyArrays": true } },
  {
    "$project": {
      "BOOK_ID": 1,
      "BOOK_NAME": 1,
      "BOOK_DESC": 1,
      "group_name": { "$ifNull": ["$group_info.group_name", []] }
    }
  }
])

执行逻辑说明

  1. $lookup阶段:从Books集合出发关联BookGroup集合,通过let定义当前书籍的BOOK_ID,子管道内:
    • 用$unwind拆分GROUPS数组,将每个书籍项单独成文档;
    • 用$match筛选出与当前书籍BOOK_ID匹配的分组项;
    • 用$group将匹配到的分组名称收集为数组;
    • 用$project整理输出格式,只保留group_name字段。
  2. $unwind阶段:展开关联得到的group_info数组,preserveNullAndEmptyArrays确保无分组的书籍也能保留。
  3. $project阶段:整理最终输出结构,保留书籍原有字段,将group_name设置为关联得到的数组(无分组则返回空数组)。

期望输出结果

[
  {
    "BOOK_ID": "100",
    "BOOK_NAME": "Book 1",
    "BOOK_DESC": "abcd",
    "group_name": ["G1", "G3"]
  },
  {
    "BOOK_ID": "101",
    "BOOK_NAME": "Book 2",
    "BOOK_DESC": "efgh",
    "group_name": ["G1", "G2"]
  },
  {
    "BOOK_ID": "102",
    "BOOK_NAME": "Book 3",
    "BOOK_DESC": "ijkl",
    "group_name": ["G3"]
  }
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:47:30