如何在Node.js中用MongoDB聚合$lookup关联整型字段获取图书信息?
实现MongoDB聚合关联获取图书名称和作者信息
没问题,我来帮你搞定这个跨集合关联查询的需求!根据你给出的集合结构,我们可以通过MongoDB的$lookup聚合操作完成两次关联,最终拿到对应的bookName和author信息。
关联逻辑梳理
- 你的起始文档(假设所在集合叫
userBorrowRecords)的_id就是books集合的主键_id(图书ID),第一步先关联books集合拿到对应的isbn。 - 拿到
isbn后,再关联bookDetails集合(因为bookDetails的_id就是ISBN编号),就能取出我们需要的图书名称和作者信息。
Node.js代码实现(原生MongoDB驱动)
下面是完整的代码示例,记得替换成你自己的数据库名称和集合名称:
const { MongoClient } = require('mongodb'); async function fetchBookAuthorAndName() { // 替换成你的MongoDB连接字符串 const mongoUri = 'mongodb://localhost:27017'; const client = new MongoClient(mongoUri); try { await client.connect(); const db = client.db('your_database_name'); // 替换成你的数据库名 const borrowRecordsCollection = db.collection('userBorrowRecords'); // 替换成起始文档所在的集合名 // 聚合管道 const aggregationPipeline = [ // 可选:如果只查特定图书ID,加上$match过滤,提升性能 { $match: { _id: 10001 } }, // 第一次关联:从books集合获取对应图书的ISBN { $lookup: { from: 'books', localField: '_id', foreignField: '_id', as: 'book_metadata' } }, // 展开关联结果数组(因为$lookup返回的是数组,即使只有一条匹配) { $unwind: '$book_metadata' }, // 第二次关联:通过ISBN从bookDetails集合获取图书详情 { $lookup: { from: 'bookDetails', localField: 'book_metadata.isbn', foreignField: '_id', as: 'book_details' } }, // 展开图书详情数组 { $unwind: '$book_details' }, // 筛选并整理返回字段 { $project: { _id: 1, // 保留图书ID uid: 1, loginType: 1, bookName: '$book_details.bookName', author: '$book_details.author' } } ]; // 执行聚合查询 const result = await borrowRecordsCollection.aggregate(aggregationPipeline).toArray(); console.log('查询结果:', result); return result; } catch (err) { console.error('查询出错:', err); } finally { // 关闭连接 await client.close(); } } // 调用函数 fetchBookAuthorAndName();
关键步骤解释
$match:可选阶段,用来提前过滤出目标文档,避免全集合关联,大幅提升查询效率。$lookup:MongoDB的左连接操作,通过指定当前集合的字段(localField)和目标集合的匹配字段(foreignField),将关联结果存入as指定的数组字段中。$unwind:将$lookup返回的数组字段展开为单个文档,方便后续的字段访问和二次关联。$project:自定义返回的字段结构,只保留我们需要的信息,减少数据传输量。
如果使用Mongoose的实现
如果你用Mongoose来操作MongoDB,代码结构类似,只是通过Model来执行聚合:
const mongoose = require('mongoose'); // 定义各个集合的Schema const UserBorrowRecordSchema = new mongoose.Schema({ _id: Number, uid: Number, loginType: String }); const BookSchema = new mongoose.Schema({ _id: Number, issued: Boolean, isbn: Number, issuedIds: [Number] }); const BookDetailsSchema = new mongoose.Schema({ _id: Number, quantity: Number, available: Number, tags: [String], bookIds: [Number], bookName: String, author: String }); // 创建Model const UserBorrowRecord = mongoose.model('UserBorrowRecord', UserBorrowRecordSchema, 'userBorrowRecords'); const Book = mongoose.model('Book', BookSchema, 'books'); const BookDetails = mongoose.model('BookDetails', BookDetailsSchema, 'bookDetails'); async function getBookInfo() { try { // 连接数据库 await mongoose.connect('mongodb://localhost:27017/your_database_name'); const result = await UserBorrowRecord.aggregate([ { $match: { _id: 10001 } }, { $lookup: { from: Book.collection.name, localField: '_id', foreignField: '_id', as: 'book_metadata' } }, { $unwind: '$book_metadata' }, { $lookup: { from: BookDetails.collection.name, localField: 'book_metadata.isbn', foreignField: '_id', as: 'book_details' } }, { $unwind: '$book_details' }, { $project: { _id: 1, uid: 1, loginType: 1, bookName: '$book_details.bookName', author: '$book_details.author' } } ]).exec(); console.log('查询结果:', result); return result; } catch (err) { console.error('查询出错:', err); } finally { await mongoose.disconnect(); } } getBookInfo();
内容的提问来源于stack exchange,提问作者Chhatrasal Singh Bundela
相关产品推荐
相关产品推荐

