Apollo Server中Mongoose与GraphQL Schema关联:createUser报错求助
问题:创建User时出现ObjectId转换错误
错误场景
Mongoose Schema定义:
const userSchema = new Schema({ uid: { type: String, required: true, unique: true, }, name: { type: String, required: true, }, dept: { type: Schema.Types.ObjectId, ref: 'Dept', required: true, }, }); const deptSchema = new Schema({ did: { type: String, required: true, unique: true, }, name: { type: String, required: true, }, }); const User = model('User', userSchema); const Dept = model('Dept', deptSchema); export { User, Dept };
GraphQL Schema定义:
type User { uid: String! name: String! dept: Dept! } type Dept { did: String! name: String! } input DeptInput { did: String!, name: String! } type Mutation { createUser(uid: String!, name: String!, dept: DeptInput): User }
createUser Resolver原代码:
Mutation: { createUser: async(_, { uid, name, dept }) => { try { // Create the new user const newUser = new User({ uid, name, dept: { did: dept.did, name: dept.name } }); await newUser.save(); return newUser; } catch (error) { throw new Error('Failed to create user'); } } }
执行GraphQL突变请求:
mutation { createUser(uid: "5", name: "osama alatraqchi", dept: {did: "1", name: "CS"}) { name uid dept {did name} } }
收到错误:
"Failed to create user: Cast to ObjectId failed for value \"1\" (type string) at path \"_id\" for model \"Dept\""
错误原因
User Schema中的dept字段类型是Schema.Types.ObjectId,它存储的是关联Dept文档的_id值,而非整个Dept对象。原Resolver中直接传入{ did: dept.did, name: dept.name },Mongoose会尝试将这个对象转换为ObjectId,导致类型转换失败。
解决方案
分两种业务场景处理:
场景1:Dept已存在,根据did查找后关联
如果传入的dept.did对应的部门已经存在,先通过did查询Dept文档,获取其_id再关联到User的dept字段:
Mutation: { createUser: async(_, { uid, name, dept }) => { try { // 根据did查找已存在的部门 const existingDept = await Dept.findOne({ did: dept.did }); if (!existingDept) { throw new Error('Dept not found'); } // 创建User并关联部门的_id const newUser = new User({ uid, name, dept: existingDept._id }); await newUser.save(); // 关联查询返回完整的部门信息 await newUser.populate('dept'); return newUser; } catch (error) { throw new Error(`Failed to create user: ${error.message}`); } } }
场景2:需要同时创建Dept和User
如果传入的部门不存在,先创建Dept文档,再将其_id关联到User:
Mutation: { createUser: async(_, { uid, name, dept }) => { try { // 查找已存在的部门,不存在则创建 let targetDept = await Dept.findOne({ did: dept.did }); if (!targetDept) { targetDept = await Dept.create(dept); } // 创建User并关联部门的_id const newUser = new User({ uid, name, dept: targetDept._id }); await newUser.save(); // 关联查询返回完整的部门信息 await newUser.populate('dept'); return newUser; } catch (error) { throw new Error(`Failed to create user: ${error.message}`); } } }
关键说明
- 必须确保User的
dept字段存储的是Dept文档的_id,而非自定义的did或完整对象 - 使用
populate('dept')可以在返回User时自动关联查询Dept的完整信息,匹配GraphQL返回结构要求
内容的提问来源于stack exchange,提问作者Osama Mohammed
相关产品推荐
相关产品推荐

