如何在嵌套查询的解析器函数中传递根参数? [英] How to pass root parameters in the resolver function of a nested query?

查看:20
本文介绍了如何在嵌套查询的解析器函数中传递根参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下性质的查询

Category1(name: $cat1){类别 2(第二个名称:$cat2){第二个名字}}

我的架构是这样的:

const Query = new GraphQLObjectType({name: '查询',字段:{类别 1:{类型:新 GraphQLList(Category1Type),参数:{名称},解决:resolveCategory1}}})

然后将 Category1Type 定义为:

const Category1Type = new GraphQLObjectType({name: '类别 1',描述:'<>',字段:() =>({名称:{ 类型:GraphQLString },类别 2:{类型:新 GraphQLList(CategoryType2),参数:{第二个名字},解决:resolveCategory2}})});

为简单起见,假设 category2 是这样的:

const Category2Type = new GraphQLObjectType({name: '类别 2',描述:'<>',字段:() =>({名称:{ 类型:GraphQLString },})});

现在我想通过过滤选项获取 Category1 下的所有 Category2 项目,如下所示:

Category1(name: $name){姓名类别2(名称:$名称){姓名}}

我的解析器定义如下:

 # Category1 解析器函数 cat1resolve (root, args) {返回 SELECT * from data WHERE category1_name = args.name}# Category2 解析器函数 cat2Resolve(根,参数){返回 SELECT * from data WHERE category1_name = rootargs.name and categort2_name = args.secondName }

现在的问题是 cat2Resolve 的解析器"无法看到或接收 rootargs.name 来让我进行这种过滤.

解决方案

resolve 函数签名包含 4 个参数.来自 Apollo 的 docs:

<块引用>

  1. obj:包含从父字段的解析器返回的结果的对象,或者,在顶级查询字段的情况下,从服务器配置传递的 rootValue.这个论点使GraphQL 查询的嵌套性质.
  2. args:带有传入查询字段的参数的对象.例如,如果使用 author(name: "Ada") 调用该字段,args 对象将是:{ "name": "Ada" }.
  3. context:这是一个特定查询中所有解析器共享的对象,用于包含每个请求的状态,包括身份验证信息、数据加载器实例和其他任何内容解决查询时应该考虑到这一点.如果你是使用 Apollo Server,阅读有关如何在设置中设置上下文的信息文档.
  4. info:该参数只应在高级情况下使用,但它包含有关查询执行状态的信息,包括字段名称、从根到字段的路径等.这只是GraphQL.js 源代码中记录.

注意:这些文档适用于 graphql-tools 的 makeExecutableSchema(我强烈推荐),但同样适用于普通的旧 GraphQL.JS.

这里的关键点是特定字段的解析器通常与其他解析器做什么或传递给它们的信息无关.它传递了它自己的父字段值、它自己的参数、上下文并期望使用它.

但是,有一种使用 info 参数的解决方法.传递给 info 的对象很大,解析起来可能很复杂,但实际上包含有关所请求查询本身的所有信息.有一些库可以帮助解析它,但您可能想要打印整个内容以进行控制台和浏览(这很酷!).

使用类似 lodash 的 get 之类的东西,我们可以这样做:

const category1id = get(info, 'operation.selectionSet.selections[0].arguments[0].value.value')

并在您的查询中使用该值.上述内容非常脆弱,因为它假设您的请求仅包含一个查询,并且您在 Category1 字段上只有一个参数.在实践中,您可能希望使用 Array.find 并按名称查找字段/参数,但这应该为您提供一个起点.

I have a query of the following nature

Category1(name: $cat1){
   Category2(secondName: $cat2){
      secondName
    }}

My schema is like so:

const Query = new GraphQLObjectType({
name: 'Query',
fields: {
    Category1: {
        type: new GraphQLList(Category1Type),
        args: { name },
        resolve: resolveCategory1
    }}
})

And then the Category1Type is defined as:

const Category1Type = new GraphQLObjectType({
    name: 'Category1',
    description: '<>',
    fields: () => ({
        name: { type: GraphQLString },
        category2: {
            type: new GraphQLList(CategoryType2),
            args: { secondName },
            resolve: resolveCategory2
        }
    })
});

For simplicity sake, assume category2 is like so:

const Category2Type = new GraphQLObjectType({
    name: 'Category2',
    description: '<>',
    fields: () => ({
        name: { type: GraphQLString },
    })
});

Now I want to fetch all Category2 items under Category1 with option to filter, like so:

Category1(name: $name){
   name
   category2(name: $name){
      name 
}}

My resolvers are defined like so:

    # Category1 resolver
    function cat1resolve (root, args) {
return SELECT * from data WHERE category1_name = args.name
}

    # Category2 resolver
    function cat2Resolve (root, args) {
return SELECT * from data WHERE category1_name = rootargs.name and categort2_name = args.secondName }

Now the problem is that the 'resolver' for cat2Resolve is not able to see or receive the rootargs.name for me to do this kind of filtering.

解决方案

The resolve function signature includes 4 parameters. From Apollo's docs:

  1. obj: The object that contains the result returned from the resolver on the parent field, or, in the case of a top-level Query field, the rootValue passed from the server configuration. This argument enables the nested nature of GraphQL queries.
  2. args: An object with the arguments passed into the field in the query. For example, if the field was called with author(name: "Ada"), the args object would be: { "name": "Ada" }.
  3. context: This is an object shared by all resolvers in a particular query, and is used to contain per-request state, including authentication information, dataloader instances, and anything else that should be taken into account when resolving the query. If you’re using Apollo Server, read about how to set the context in the setup documentation.
  4. info: This argument should only be used in advanced cases, but it contains information about the execution state of the query, including the field name, path to the field from the root, and more. It’s only documented in the GraphQL.js source code.

Note: These docs are for graphql-tools' makeExecutableSchema (which I highly recommend) but the same applies to plain old GraphQL.JS.

The key point here is that a resolver for a particular field is generally agnostic to what other resolvers do or what information is passed to them. It's handed its own parent field value, its own arguments, the context and expected to work with that.

However, there is a workaround utilizing the info parameter. The object passed to info is huge and can be complicated to parse, but contains virtually all the information about the requested query itself. There are libraries out to help with parsing it, but you may want to print the whole thing to console and poke around (it's pretty cool!).

Using something like lodash's get, we can then do:

const category1id = get(info, 'operation.selectionSet.selections[0].arguments[0].value.value')

and utilize that value inside your query. The above is pretty fragile, since it assumes your request only contains the one query, and you only have one argument on the Category1 field. In practice, you'd probably want to utilize Array.find and look up the fields/arguments by name, but this should give you a starting point.

这篇关于如何在嵌套查询的解析器函数中传递根参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆