要解决Apollo Server无法对Mongoose中子对象中的虚拟属性进行序列化的问题,可以使用自定义解析函数(Custom Resolvers)来手动处理。
首先,确保你的Mongoose模型中的子对象定义了虚拟属性。例如,假设你有一个User
模型,其中包含一个posts
虚拟属性,该属性引用了Post
模型。
const mongoose = require('mongoose');
const postSchema = mongoose.Schema({
title: String,
content: String
});
const userSchema = mongoose.Schema({
name: String,
posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }]
});
userSchema.virtual('postCount').get(function() {
return this.posts.length;
});
const User = mongoose.model('User', userSchema);
const Post = mongoose.model('Post', postSchema);
module.exports = { User, Post };
接下来,在Apollo Server的解析器中,使用lean()
方法来获取Mongoose查询结果的纯JavaScript对象(而不是Mongoose文档对象)。然后,手动处理子对象中的虚拟属性。
以下是一个示例解析器的代码:
const { ApolloServer, gql } = require('apollo-server');
const { User, Post } = require('./models');
const typeDefs = gql`
type User {
name: String
posts: [Post]
postCount: Int
}
type Post {
title: String
content: String
}
type Query {
user(id: ID!): User
}
`;
const resolvers = {
Query: {
user: async (parent, { id }) => {
const user = await User.findById(id).populate('posts');
const userObj = user.toObject(); // 将Mongoose文档转换为纯JavaScript对象
userObj.postCount = user.postCount; // 手动添加虚拟属性
return userObj;
}
},
User: {
posts: (user) => user.posts
}
};
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
console.log(`Server running at ${url}`);
});
在上面的代码中,我们先使用findById()
方法获取用户对象,然后使用populate()
方法填充posts
属性。接下来,使用toObject()
方法将Mongoose文档对象转换为纯JavaScript对象。最后,手动添加虚拟属性postCount
。
这样,Apollo Server就能够正确地序列化子对象中的虚拟属性了。