简体   繁体   English

在 GraphQL 操作中使用嵌套的 arguments

[英]Using nested arguments in GraphQL operations

I have a schema like so:我有一个这样的架构:

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!
}

And I want to make an operation where you can get all messages for a user, but since User and ChatMessage are in separate database tables I would need to perform two queries (one to get the ChatMessages and one to get the User ), so I thought I should model it like so:我想进行一个操作,您可以在其中获取用户的所有消息,但由于UserChatMessage在单独的数据库表中,我需要执行两个查询(一个获取ChatMessages ,一个获取User ),所以我以为我应该像这样 model :

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

This returns a parse error on the schema:这会在架构上返回解析错误:

GraphQLDocumentError: Unknown argument "id" on field "ChatMessage.user". GraphQLDocumentError:字段“ChatMessage.user”上的未知参数“id”。

So, how do I get the $userId argument passed to the resolver for ChatMessage.user ?那么,如何将$userId参数传递给ChatMessage.user的解析器?

In your schema, you've defined an id input on your Query.user method.在您的架构中,您已经在 Query.user 方法上定义了一个 id 输入。 In your query, you are trying to supply an id to the Message.user property, however you haven't defined this input in your schema.在您的查询中,您尝试为 Message.user 属性提供一个 id,但是您尚未在架构中定义此输入。

If you wanted to accept an id on ChatMessage.user, you'd need to define it as:如果您想接受 ChatMessage.user 上的 id,您需要将其定义为:

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

However, it wouldn't really make sense (at least to me) to construct a schema this way, I assume there's only one user (author) per message.但是,以这种方式构建模式并没有真正意义(至少对我而言),我假设每条消息只有一个用户(作者)。

As indicated by @xadm, the object you resolved at the ChatMessage level will be passed into the user resolver as the first argument.如@xadm 所示,您在 ChatMessage 级别解析的 object 将作为第一个参数传递给用户解析器。

Even if you're not exposing ChatMessage.userId in the schema (that's fine), you'd still probably load this up in your back- end (the foreign key value in the ChatMessage table) and set this on the object used to resolve ChatMessage.即使您没有在架构中公开 ChatMessage.userId(这很好),您仍然可能会在后端加载它(ChatMessage 表中的外键值)并将其设置在用于解析的 object聊天消息。

This way, you'll (lazy) load user IF that's included in the query, using the userId property of the parent ChatMessage object argument (remember you don't need to expose ChatMessage.userId via the schema, it's just on the object you use to resolve ChatMessage).这样,您将(延迟)加载包含在查询中的用户 IF,使用父 ChatMessage object 参数的 userId 属性(请记住,您不需要通过模式公开 ChatMessage.userId,它只是在 object 上用于解析 ChatMessage)。

I'd consider modelling more like this (filter input used as an additional contrived example):我会考虑更像这样的建模(过滤器输入用作额外的人为示例):

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!]!
}

In your resolver map, you can wire up the same function to resolve messages at the User level and at the Query level.在您的解析器 map 中,您可以连接相同的 function 以在用户级别和查询级别解析消息。 The only difference is you wouldn't have a userId at the Query level.唯一的区别是您不会在 Query 级别拥有 userId。

If consumers want to view/search messages from all users, they use the top level Query messages method.如果消费者想要查看/搜索来自所有用户的消息,他们使用顶级查询消息方法。

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

If the consumer wants to view/search one user's messages, go through the top level Query users method into messages.如果消费者想要查看/搜索一个用户的消息,go 通过顶级Query users 方法进入消息。

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

The filter example is contrived, but could provide basic paging for loading of messages.过滤器示例是人为设计的,但可以为消息的加载提供基本的分页。

apollographql.com/docs/graphql-tools/resolvers apollographql.com/docs/graphql-tools/resolvers

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM