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
相关产品推荐
相关产品推荐

