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

MongoDB关联集合:按ISBN查询书籍并关联章节笔记

MongoDB 关联书籍章节与笔记的解决方案

先明确集合结构示例

books 集合结构

{
  "_id": ObjectId("60d21b4667d0d8992e610c85"),
  "isbn": "978-1234567890",
  "title": "MongoDB实战指南",
  "chapters": [
    {
      "r_id": "ch_001",
      "pagenr": 5,
      "title": "初识MongoDB"
    },
    {
      "r_id": "ch_002",
      "pagenr": 20,
      "title": "聚合框架详解"
    }
  ]
}

notes 集合结构

{
  "_id": ObjectId("60d21b8967d0d8992e610c86"),
  "r_id": "ch_001",
  "content": "文档型数据库的核心优势是灵活的数据模型",
  "createdAt": ISODate("2024-05-20T10:30:00Z")
},
{
  "_id": ObjectId("60d21b9a67d0d8992e610c87"),
  "r_id": "ch_001",
  "content": "$lookup 是关联集合的关键操作符",
  "createdAt": ISODate("2024-05-20T10:35:00Z")
}

需求1:查询单本书籍,为每个章节添加对应笔记数量

核心逻辑:先拆分章节数组,逐个关联笔记并统计数量,最后重组数组并按页码排序。

db.books.aggregate([
  // 1. 按ISBN筛选目标书籍
  { $match: { isbn: "978-1234567890" } },
  // 2. 拆分章节数组,实现逐个章节关联
  { $unwind: "$chapters" },
  // 3. 关联notes集合,统计当前章节的笔记数量
  {
    $lookup: {
      from: "notes",
      let: { chapter_r_id: "$chapters.r_id" },
      pipeline: [
        { $match: { $expr: { $eq: ["$r_id", "$$chapter_r_id"] } } },
        { $count: "note_count" }
      ],
      as: "note_stats"
    }
  },
  // 4. 处理空笔记场景,没有笔记时数量设为0
  {
    $addFields: {
      "chapters.note_count": {
        $ifNull: [{ $arrayElemAt: ["$note_stats.note_count", 0] }, 0]
      }
    }
  },
  // 5. 重新组合章节数组,并按pagenr升序排序
  {
    $group: {
      _id: "$_id",
      isbn: { $first: "$isbn" },
      title: { $first: "$title" },
      chapters: { $push: "$chapters" }
    }
  },
  {
    $addFields: {
      chapters: { $sortArray: { input: "$chapters", sortBy: { pagenr: 1 } } }
    }
  }
])

需求2:查询单本书籍,为每个章节添加所有笔记内容

核心逻辑:同样先拆分章节数组,关联后直接获取对应笔记,再重组排序。

db.books.aggregate([
  // 1. 按ISBN筛选目标书籍
  { $match: { isbn: "978-1234567890" } },
  // 2. 拆分章节数组
  { $unwind: "$chapters" },
  // 3. 直接关联对应章节的所有笔记
  {
    $lookup: {
      from: "notes",
      localField: "chapters.r_id",
      foreignField: "r_id",
      as: "chapters.notes"
    }
  },
  // 4. 重组章节数组并按页码排序
  {
    $group: {
      _id: "$_id",
      isbn: { $first: "$isbn" },
      title: { $first: "$title" },
      chapters: { $push: "$chapters" }
    }
  },
  {
    $addFields: {
      chapters: { $sortArray: { input: "$chapters", sortBy: { pagenr: 1 } } }
    }
  }
])

为什么之前的$lookup没匹配成功?

普通的$lookup是基于整个文档的字段关联,而你的章节是嵌套数组,直接关联会拿整个books文档的字段去匹配notes,而非数组里每个章节的r_id。必须先通过$unwind拆分章节数组,让每个章节成为独立文档片段,再进行关联,最后重新组合数组才能得到正确结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:05:09