在GraphQL操作中使用嵌套参数

时间:2020-04-28 01:50:36

标签: graphql

我有一个类似的架构:

scalar Date

schema {
  query: Query
}

type Query {
  user(id: ID!): User
  messages(userId: ID!): [ChatMessage!]!
}

type User {
  id: ID!
  username: String!
  email: String!
}

type ChatMessage {
  id: ID!
  content: String!
  time: Date!
  user: User!
}

我想进行一个操作,以便为用户获取所有消息,但是由于UserChatMessage位于单独的数据库表中,因此我需要执行两个查询(一个查询要获取ChatMessages和一个获得User的对象),所以我认为我应该像这样建模:

query findMessagesForUser($userId: ID!) {
  messages(userId: $userId) {
    id
    content
    user(id: $userId) {
      username
      email
    }
  }
}

这将在架构上返回解析错误:

GraphQLDocumentError:“ ChatMessage.user”字段上的未知参数“ id”。

那么,如何将$userId参数传递给ChatMessage.user的解析器?

1 个答案:

答案 0 :(得分:1)

在您的模式中,您已经在Query.user方法上定义了一个id输入。在查询中,您尝试向Message.user属性提供一个ID,但是尚未在架构中定义此输入。

如果您想在ChatMessage.user上接受一个I​​D,则需要将其定义为:

type ChatMessage {
  id: ID!
  content: String!
  time: Date!
  user(id: ID!): User
}

但是,以这种方式构造模式(至少对我来说)并没有任何意义,我假设每封邮件只有一个用户(作者)。

如@xadm所示,您在ChatMessage级别解析的对象将作为第一个参数传递到用户解析器中。

即使您没有在架构中公开ChatMessage.userId(没关系),也可能仍将其加载到后端(ChatMessage表中的外键值)并在对象上进行设置用于解析ChatMessage。

这样,您将使用父ChatMessage对象参数的userId属性(延迟)加载(延迟)查询中包含的用户IF(请记住,您无需通过架构公开ChatMessage.userId,它只是在用于解析ChatMessage的对象。

我会考虑更像这样建模(将过滤器输入用作其他人为的示例):

type Query {
  user(id: ID!): User
  messages(filter: MessageFilter): [ChatMessage!]!
}

type MessageFilter {
  search: String
  paging: PagingFilter 
}

type PagingFilter {
  after: ID!
  pageSize: Int!
}

type User {
  id: ID!
  username: String!
  email: String!
  messages(filter: MessageFilter): [ChatMessage!]!
}

在解析器图中,您可以连接相同的功能来解析用户级别和查询级别的消息。唯一的区别是您在查询级别将没有userId。

如果消费者想查看/搜索所有用户的消息,则使用顶级查询消息方法。

{
  messages({search: 'graphql'}) {
   id,
   content,
   time
  }
}

如果消费者想查看/搜索一个用户的消息,请通过顶级“查询用户”方法进入消息。

{
  user(id: 3) {
    messages({search: 'graphql'}) {
     id,
     content,
     time
    }
  }
}

该过滤器示例是人为设计的,但可以提供用于加载消息的基本分页。

apollographql.com/docs/graphql-tools/解析器