GraphQL中定义的与呼叫者相关的字段在哪里

时间:2018-12-19 11:06:59

标签: graphql

我当前正在编写POC GraphQL服务器。但是,客户端UI需要的是瞬态字段(不是数据库模型的一部分),并且是动态形成或查询的。例如:可以喜欢Post,所以我想在graphQL中放置一个标记isLiked: Boolean。根据呼叫者的不同,如果喜欢true,则该标志为Post,否则为false。 但是,这感觉不对,因为严格来讲,它不是Post类型的一部分,而是UI耦合的一种形式(我们想用GraphQL解决的问题)。我也觉得有一种更好的方法可以提供Like作为类型(例如,它也有一个date)。在类型中定义基本上是子查询的依赖于调用方的字段,这是一个好主意吗?

2 个答案:

答案 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肿且速度较慢,但​​是任何后续查询都将更快。随着数据的增长,无论在广度还是深度上,这些性能提升都将是巨大的。