GraphQL+MongoDB+Mongoose关联查询无法获取多分类问题排查
问题:Mongoose populate无法获取关联的categories字段
我正在结合使用GraphQL、MongoDB和Mongoose,现有users和categories两个集合,代码定义如下:
Category.js
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const categorySchema = new mongoose.Schema({ title:{ type: String, required: true }, userid: { type: Schema.Types.ObjectId, ref: 'User', required: true, }, }); module.exports = mongoose.model('Category',categorySchema);
User.js
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const userSchema = new mongoose.Schema({ name:{ type: String, required: true }, email:{ type: String, required: true, unique: true }, password:{ type: String, required: true } }); module.exports = mongoose.model('User',userSchema);
Resolver.js
const User = require('../models/User'); const Category = require('../models/Category'); const resolvers = { getUsers: async () => { try { const users = await User.find().populate('categories'); return users; } catch(err){ throw new Error(err); } }, }; module.exports = resolvers;
我在categories集合中已存入带对应userid的数据,但查询用户时始终无法获取关联的categories,返回结果中无该字段。后续尝试aggregate查询及调整后的populate查询,均返回null且控制台无输出。现有集合数据已确认userid关联正确,请问我哪里操作有误?
解决方案
问题出在关联方向的处理错误:你当前的模型是Category通过userid引用User,属于反向引用,但User模型中并没有定义categories字段或对应的关联配置,所以populate('categories')无法识别这个关联关系。
方法1:通过Mongoose虚拟字段实现反向关联
修改User.js,添加虚拟字段来关联Category集合:
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const userSchema = new mongoose.Schema({ name:{ type: String, required: true }, email:{ type: String, required: true, unique: true }, password:{ type: String, required: true } }); // 定义虚拟字段categories,关联Category集合 userSchema.virtual('categories', { ref: 'Category', // 关联的模型 localField: '_id', // User模型中用于匹配的字段 foreignField: 'userid' // Category模型中对应的关联字段 }); // 确保查询结果中包含虚拟字段(转换为对象或JSON时生效) userSchema.set('toObject', { virtuals: true }); userSchema.set('toJSON', { virtuals: true }); module.exports = mongoose.model('User',userSchema);
然后保持Resolver中的代码不变,populate('categories')就能正常获取到用户对应的分类了:
const resolvers = { getUsers: async () => { try { const users = await User.find().populate('categories'); return users; } catch(err){ throw new Error(err); } }, };
方法2:手动查询关联数据(无需修改模型)
如果不想修改模型,可以在Resolver中为每个用户手动查询对应的分类:
const resolvers = { getUsers: async () => { try { const users = await User.find(); // 并行查询每个用户的分类 const usersWithCategories = await Promise.all( users.map(async user => { const categories = await Category.find({ userid: user._id }); // 将用户对象转为普通对象并添加categories字段 return { ...user.toObject(), categories }; }) ); return usersWithCategories; } catch(err){ throw new Error(err); } }, };
关键原因说明
Mongoose的populate方法默认只能处理模型中显式定义的引用字段(即带ref属性的字段),而你当前的关联是Category指向User,属于反向关联,所以需要通过虚拟字段或者手动查询来实现一对多的关联查询。
内容的提问来源于stack exchange,提问作者Mittul At TechnoBrave
相关产品推荐
相关产品推荐

