【问题标题】:How to get requested fields inside GraphQL resolver?如何在 GraphQL 解析器中获取请求的字段?
【发布时间】:2018-06-08 20:15:13
【问题描述】:

我正在使用graphql-tools。收到 GraphQL 查询后,我使用 ElasticSearch 执行搜索并返回数据。

但是,通常请求的查询只包含少数可能的字段,而不是全部。我只想将请求的字段传递给 ElasticSearch。 首先,我需要获取请求的字段。

我已经可以将整个查询作为字符串获取。例如,在解析器中,

const resolvers = {
  Query: {
    async user(p, args, context) {
      //can print  query as following
      console.log(context.query)                
    }
    .....
  }
}

它打印为

query User { user(id:"111") { id  name address } }

有没有办法以类似的格式获取请求的字段

{ id:"",  name:"", address:"" }

【问题讨论】:

标签: graphql graphql-js


【解决方案1】:

在 graphql-js 中,解析器公开了第四个参数,称为解析信息。此字段包含有关该字段的更多信息。

来自GraphQL docs GraphQLObjectType config 参数类型定义:

// See below about resolver functions.
type GraphQLFieldResolveFn = (
  source?: any,
  args?: {[argName: string]: any},
  context?: any,
  info?: GraphQLResolveInfo
) => any

type GraphQLResolveInfo = {
  fieldName: string,
  fieldNodes: Array<Field>,
  returnType: GraphQLOutputType,
  parentType: GraphQLCompositeType,
  schema: GraphQLSchema,
  fragments: { [fragmentName: string]: FragmentDefinition },
  rootValue: any,
  operation: OperationDefinition,
  variableValues: { [variableName: string]: any },
}

fieldNodes 字段中,您可以搜索您的字段并获取特定字段的selectionSet。从这里开始变得棘手,因为selections 可以是正常的字段选择、片段或内联片段。您必须将它们全部合并才能知道在一个字段上选择的所有字段。

【讨论】:

  • 我没有看到这样的论点。我正在使用“graphql-tools”。
【解决方案2】:

有一个info 对象作为解析器中的第四个参数传递。此参数包含您要查找的信息。

使用graphql-fields 的库来帮助您解析graphql 查询数据会很有帮助:

const graphqlFields = require('graphql-fields');

const resolvers = {
  Query: {
    async user(_, args, context, info) {
      const topLevelFields = graphqlFields(info);
      console.log(Object.keys(topLevelFields)); // ['id', 'name', 'address']
    },
};

【讨论】:

  • 我想把graphqlFields方法放到graphql中间件可以减少重复代码。
  • 请注意graphql-fields 的作者建议以后使用graphql-parse-resolve-info
【解决方案3】:

对于graphql-java,您可以通过使用myGetUsersResolverMethod(... DataFetchingEnvironment env) 扩展字段参数来做同样的事情。

  • 将为您注入此 DataFetchingEnvironment,您可以遍历此 DataFetchingEnvironment 对象以获取 graph/查询的任何部分。

  • 此对象可让您更多地了解正在获取的内容以及已提供的参数。

例子:

    public List<User> getUsers(final UsersFilter filter, DataFetchingEnvironment env) {

    DataFetchingFieldSelectionSet selectionSet = env.getSelectionSet();
    selectionSet.getFields(); // <---List of selected fields
    selectionSet.getArguments(); // <--- Similarly but MAP
    ...

    }

实际上,您可能是在暗示提前获取数据。以上内容应该让您对请求的字段有足够的了解,您可以从那里获取它来手动定制下游调用。但是您也可以通过using the data fetchersBuilding efficient data fetchers by looking ahead 寻找更有效的方法来做到这一点

【讨论】:

    猜你喜欢
    • 2021-05-02
    • 2017-04-02
    • 2017-05-10
    • 2018-06-16
    • 2021-02-08
    • 2020-10-07
    • 1970-01-01
    • 2018-10-04
    相关资源
    最近更新 更多