基于嵌套字段的过滤器从 apollo-server 返回数据

Jon*_*dle 7 apollo reactjs graphql apollo-server

是否可以为 apollo 中基于嵌套字段过滤器的查询返回数据?例如:

询问:

Users($filter: String!) {
  user(filter: $filter) { 
    id, 
    name, 
    address(filter: $filter) { 
       street, 
       city, 
       country
    } 
  } 
}
Run Code Online (Sandbox Code Playgroud)

类型定义:

Query: {
   users(filter: String): [User]!
}

User: {
    id: ID!,
    name: String!,
    address: Address
}

Address: {
    street: String!,
    city: String!,
    country: String!
}
Run Code Online (Sandbox Code Playgroud)

阿波罗解析器:

const resolverMap = {
  Query: {
    User(obj, args, context, info) {
      // query api for User info (not including address)
      // the final results of the query should only return users with the 
      // specific address (for example if the filter is country: England, only 
      // return users that live in England.
    },
  },
  Address: {
    address: (obj, args, context, info) {
      // query another api for address based on parent (User) Id
    },
  },
}
Run Code Online (Sandbox Code Playgroud)

使用该查询,我只希望为居住在特定国家/地区(例如英格兰)的用户返回结果。由于此过滤器适用于嵌套类型 [address],因此是否可以使用此查询而不必首先查询地址?

Jen*_*ens 0

最简洁的答案是不。

过滤用户是user查询的责任,而不是子级的责任。您正在尝试拆分实际上是单个查询的查询(按地址过滤用户)。

如果您想修改用户查询本身的结果,您应该addressuser查询本身添加一个参数,以便它可以按地址过滤用户。

像这样的东西:

Users($filter: String!) {
  user(filter: $filter, addressFilter: $addressFilter) { 
    id, 
    name, 
    address { 
       street, 
       city, 
       country
    } 
  } 
}
Run Code Online (Sandbox Code Playgroud)

然后解析器看起来像这样:

const resolverMap = {
  Query: {
    User(obj, args, context, info) {
      // query both API for User info (not including address)
      // and API for user addresses using $filter and $addressFilter
      // Then match results from both API and discard users with invalid
      // addresses

      // For example if the filter is country: England, only 
      // return users that live in England with their address
    },
  },
  Address: {
    address: (obj, args, context, info) {
      // you don't need this resolver unless you want to somehow
      // change or format the addresses previously returned
    },
  },
}
Run Code Online (Sandbox Code Playgroud)

如果您仍然想让它按照您最初预期的方式工作,您可能会找到一种方法来破解它并使其工作。您也许能够从user解析器参数访问整个查询对象,也许可以在上下文中注入内容以使其在解析器中可用,但即使您设法做到这一点,您也会破坏 GraphQL 语义。

user查询负责返回用户列表。返回后,子解析器无法再次更改用户列表本身,只能更改子对象。

address查询完成后,每个用户都会调用解析器一次,user但它与修改查询结果无关user。地址解析器应该只更改地址本身,而不是父地址。address不是列表,因此使用它来过滤它没有意义,但您可以使用解析器address以特定方式格式化每个地址。