如何通过Mongoose聚合lookup获取关联集合数据?
Mongoose聚合管道lookup关联User集合返回空数组,但populate能正常获取数据
问题描述
使用Mongoose的aggregate聚合管道查询Course数据时,通过lookup关联User集合后返回的user数组为空,但使用populate可以正常获取关联的用户数据。
Lookup代码
const course = await mongoose.model('Course').aggregate() .match({ _id: new mongoose.Types.ObjectId(id) }) .lookup({ from: 'User', foreignField: '_id', localField: 'userId', as: 'user' })
Course Schema
const CourseSchema = new Schema({ title: String, userId: { type: mongoose.Types.ObjectId, ref: 'User' }, }, { strict: false });
预期输出
{ "course": [ { "_id": "64b000c085e9b1aec5975249", "title": "test", "userId": "64affc47d81a4bfba92b5540", "user": [], // 此处应存在数据但为空 } ] }
可正常运行的populate代码
const course = await mongoose.model('Course') .find({ _id: new mongoose.Types.ObjectId(id) }) .populate('userId').exec();
解决方案
问题核心在于lookup的from参数配置错误:
- Mongoose默认会将模型名转换为小写复数形式作为数据库集合名,比如
User模型对应的实际集合名是users,而非User。 populate依赖Schema中的ref字段关联模型,Mongoose会自动处理集合名转换;但aggregate的lookup是直接与MongoDB交互,必须指定数据库中实际存在的集合名。
修复后的代码
方式1:直接指定正确的集合名(小写复数)
const course = await mongoose.model('Course').aggregate() .match({ _id: new mongoose.Types.ObjectId(id) }) .lookup({ from: 'users', // 修改为小写复数的集合名 foreignField: '_id', localField: 'userId', as: 'user' })
方式2:通过模型动态获取集合名(更稳妥,避免硬编码错误)
const UserModel = mongoose.model('User'); const course = await mongoose.model('Course').aggregate() .match({ _id: new mongoose.Types.ObjectId(id) }) .lookup({ from: UserModel.collection.name, // 动态获取集合名 foreignField: '_id', localField: 'userId', as: 'user' })
验证集合名的方法
可以通过MongoDB命令行确认实际集合名:
show collections
或者在代码中打印User模型的集合名:
console.log(mongoose.model('User').collection.name); // 输出users
内容的提问来源于stack exchange,提问作者kittu
相关产品推荐
相关产品推荐

