使用 Relay 设置分页非常容易,但是有一个小细节我不清楚。
我的代码中的两个相关部分都标有注释,其他代码用于附加上下文。
const postType = new GraphQLObjectType({
name: 'Post',
fields: () => ({
id: globalIdField('Post'),
title: {
type: GraphQLString
},
}),
interfaces: [nodeInterface],
})
const userType = new GraphQLObjectType({
name: 'User',
fields: () => ({
id: globalIdField('User'),
email: {
type: GraphQLString
},
posts: {
type: postConnection,
args: connectionArgs,
resolve: async (user, args) => {
// getUserPosts() is in next code block -> it gets the data from db
// I pass args (e.g "first", "after" etc) and user id (to get only user posts)
const posts = await getUserPosts(args, user._id)
return connectionFromArray(posts, args)
}
},
}),
interfaces: [nodeInterface],
})
const {connectionType: postConnection} =
connectionDefinitions({name: 'Post', nodeType: postType})
exports.getUserPosts = async (args, userId) => {
try {
// using MongoDB and Mongoose but question is relevant with every db
// .limit() -> how many posts to return
const posts = await Post.find({author: userId}).limit(args.first).exec()
return posts
} catch (err) {
return err
}
}
我困惑的原因:
- 如果我传递参数并在 db 查询中使用它来
first
限制返回的结果,hasNextPage
总是. 这是有效的,但它会破坏(如果你使用)false
hasNextPage
hasPreviousPage
last
- 如果我不传递
first
参数并且不在数据库查询中使用它来限制返回的结果,hasNextPage
则按预期工作,但它将返回我查询的所有项目(可能是数千个)- 即使数据库在同一台机器上(对于更大的应用程序而言并非如此),这似乎非常、非常、非常低效和糟糕。请证明我错了!
- 据我所知,GraphQL 没有任何服务器端缓存,因此没有必要返回所有结果(即使有,用户也不会浏览 100% 的内容)
这里的逻辑是什么?
我想到的一种解决方案是增加+1
value first
in getUserPosts
,它将检索一个多余的项目并且hasNextPage
可能会起作用。但这感觉就像是一种黑客行为,并且总是有多余的物品被退回——如果有很多connections
和请求,它会相对快速地增长。
我们是否期望像那样破解它?是否期望返回所有结果?
还是我误解了数据库和 GrahpQL / Relay 之间的整个关系?
如果我使用FB DataLoader和 Redis 会怎样?这会改变这个逻辑吗?