我当前正在编写POC GraphQL服务器。但是,客户端UI需要的是瞬态字段(不是数据库模型的一部分),并且是动态形成或查询的。例如:可以喜欢Post
,所以我想在graphQL中放置一个标记isLiked: Boolean
。根据呼叫者的不同,如果喜欢true
,则该标志为Post
,否则为false
。
但是,这感觉不对,因为严格来讲,它不是Post类型的一部分,而是UI耦合的一种形式(我们想用GraphQL解决的问题)。我也觉得有一种更好的方法可以提供Like
作为类型(例如,它也有一个date
)。在类型中定义基本上是子查询的依赖于调用方的字段,这是一个好主意吗?
答案 0 :(得分:2)
GraphQL has some limitations, and I don't think it's wrong to add special-case fields to the schema to work around these limitations, particularly if they represent some query some actual application will make (and frequently).
Conversely, since a caller always specifies which specific fields they want out of an object, adding extra fields shouldn't really cost you anything in terms of performance or database queries. So: do both!
scalar DateTime
interface Node { id: ID! }
type Like implements Node {
id: ID!
post: Post!
date: DateTime!
}
type Post implements Node {
id: ID!
title: String!
date: DateTime!
likes: [Like!]!
hasLike: Bool!
}
If you don't do this then the client's only choice is to query for specific like objects and pick some field out of them. If you add limit-type parameters to the field you can minimize the cost, but it still feels a little awkward
query PostSummary($id: ID!) {
node(id: $id) {
... on Post {
title
date
likes(limit: 1) { id }
}
}
}
If this is a real use case for your application, just adding the hasLike
field seems like a more reasonable API, even if it's somewhat "specialized to the UI".
答案 1 :(得分:1)
我同意David的回答,但是只是为了提供不同的观点,对于将用户特定的字段排除在其他类型之外的字段中,您需要说些什么。还有另一种可用的替代方法,即将此类字段移到用户或查看器查询中,该查询已返回特定于登录用户的数据。例如,您可以拥有
type User {
id: ID!
username: String!
likedPosts: [Post!]!
# or better yet
likedPostIds: [ID!]!
}
当然,这种方法的缺点是您的客户必须足够“聪明”,才能使用上面的内容来推导该帖子是否被喜欢,这增加了前端的复杂性。
好处是,如果您执行注销或切换用户,则只需重新获取一个查询-您就不必浪费整个缓存,因为它已经包含了特定于用户的数据,现在必须重新获得。
这种方法也可以帮助提高性能。任何关系字段,无论是否特定于用户,都将产生额外费用。使用这种方法,您的登录查询可能会and肿且速度较慢,但是任何后续查询都将更快。随着数据的增长,无论在广度还是深度上,这些性能提升都将是巨大的。