Node+GraphQL项目存关联数据到MongoDB时ID序列化报错排查
Apollo GraphQL关联Mongoose ObjectId时ID序列化错误
我在Node项目里用Apollo开发简易博客的GraphQL API,后台用Mongoose存MongoDB。保存Post数据时触发以下错误:
"GraphQLError: ID cannot represent value: { type: "Buffer", data: [Array] }", "at GraphQLScalarType.serialize (/Users/name/projects/graphtime/node_modules/graphql/type/scalars.js:301:11)"
推测问题出在Post关联Author的插入环节,想知道是Schema定义有误,还是GraphiEditor的查询方式有问题。
数据库Schema
import mongoose from "mongoose"; const authorSchema = new mongoose.Schema({ name: { type: String, required: true }, avatar: { type: String }, }); export const Author = mongoose.model('Author', authorSchema); const postSchema = new mongoose.Schema({ title: { type: String, required: true }, authors: [ { type: mongoose.Schema.Types.ObjectId, ref: 'Author' } ] }); export const Post = mongoose.model('Post', postSchema);
GraphQL Schema
type Post { id: ID! title: String authors: [Author] } type Author { id: ID! name: String avatar: String } type Mutation { addPost( title: String!, authors: [ID!], ): Post }
GraphQL Resolver
const resolvers = { Mutation: { addPost: (_, args, context) => { const newPost = new Post({ title: args.title, authors: args.authors, }); return newPost.save(); }, }, };
执行的查询语句(数据库已存在ID为63babc44e18d174016b03433的Author)
mutation { addPost( title: "New Post", authors: ["63babc44e18d174016b03433"], ) { title authors { id name } } }
解决方案
问题出在Resolver未正确关联查询Author数据:
当addPost保存Post后,返回的authors字段是Mongoose的ObjectId数组,而非实际的Author文档。GraphQL的ID标量无法直接序列化ObjectId对象(其内部包含Buffer结构),因此触发报错。
修复方式有两种:
- 在Mutation中直接关联查询
修改addPost的Resolver,保存后调用populate方法拉取关联的Author数据:
const resolvers = { Mutation: { addPost: (_, args, context) => { const newPost = new Post({ title: args.title, authors: args.authors, }); // 保存后populate关联的authors return newPost.save().then(post => post.populate('authors')); }, }, };
- 为Post类型添加authors字段解析器
在Resolver中新增Post类型的解析逻辑,自动查询关联的Author:
const resolvers = { Post: { // 解析Post的authors字段,根据ObjectId查询对应的Author文档 authors: (parent) => Author.find({ _id: { $in: parent.authors } }) }, Mutation: { addPost: (_, args, context) => { const newPost = new Post({ title: args.title, authors: args.authors, }); return newPost.save(); }, }, };
两种方式都能让GraphQL拿到完整的Author文档,从而正确序列化id字段。
内容的提问来源于stack exchange,提问作者kar
相关产品推荐
相关产品推荐

