MongoDB如何用嵌套$lookup关联users、bookHistory、books三集合查询
解决方案
你需要实现嵌套关联查询,这里提供两种常用实现方式:
方式1:原生MongoDB聚合管道(推荐,适配你当前写的pipeline逻辑)
MongoDB 3.6及以上版本支持$lookup嵌套管道,可以直接在关联bookHistory的同时完成内层books集合的关联,调整后的pipeline如下:
const pipeline = [ { $match: query }, { $project: projection }, { $lookup: { from: 'bookHistory', let: { userUid: '$uid' }, pipeline: [ // 匹配对应用户的借阅记录 { $match: { $expr: { $eq: ['$uid', '$$userUid'] } } }, // 内层关联books集合,填充bookDetails { $lookup: { from: 'books', localField: 'bookId', foreignField: '_id', as: 'bookDetails' } }, // 因为单条借阅记录对应唯一一本书,将bookDetails数组转成对象 { $unwind: '$bookDetails' }, // 可选:如果不需要返回bookHistory的多余字段,可在这里加$project过滤 { $project: { tookOn: 0, dueOn: 0, addedOn: 0 } } ], as: 'bookHistory' } } ];
方式2:Mongoose 深populate(如果你用Mongoose ODM操作数据库)
如果你的项目用Mongoose,且已经在Schema中定义了关联关系,可以更简单的实现嵌套填充:
- 先确认Schema定义:
// BookHistory Schema const bookHistorySchema = new mongoose.Schema({ bookId: { type: String, ref: 'Books' }, // 其他字段省略 }) // User Schema const userSchema = new mongoose.Schema({ uid: String, // 其他字段省略 })
- 查询语句:
const userList = await User.find(query) .select(projection) .populate({ path: 'bookHistory', populate: { path: 'bookId', as: 'bookDetails' } })
两种方式返回的结构都和你要求的格式完全一致。
内容的提问来源于stack exchange,提问作者Haris George
相关产品推荐
相关产品推荐

