阿波罗服务器:向嵌套解析器传递参数[英] Apollo Server: pass arguments to nested resolvers

本文是小编为大家收集整理的关于阿波罗服务器:向嵌套解析器传递参数的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我的GraphQl查询看起来像这样:

{
    p1: property(someArgs: "some_value") {
        id
        nestedField {
            id
            moreNestedField {
                id
            }
        }
    }
}

在服务器端,我正在使用阿波罗服务器. 我有一个用于property的解析器,还有其他用于nestedField和moreNestedField的解析器. 我需要在嵌套解析器上检索someArgs的值. 我尝试使用解析器上可用的context来执行此操作:

property: (_, {someArgs}, ctx) => {
    ctx.someArgs = someArgs;

    // Do something
}

但是,由于上下文在所有解析器之间共享,因此这不起作用,因此,如果我在查询上有多个property,则上下文值将不好.

我还尝试使用嵌套解析器上info上可用的path.我可以上升到property字段,但我在这里没有参数...

我还尝试在info上添加一些数据,但在嵌套解析器上没有共享.

在所有解析器上添加参数不是一个选择

有什么想法?

谢谢!

推荐答案

参数可以使用当前返回的值传递给子解析器.

将从响应中删除其他数据.

我将"借"丹尼尔的代码,但没有特定的参数 - 将ARG降低为参考(合适的/清洁器/更可读的更多ARGS):

function propertyResolver (parent, args) {
  const property = await getProperty()
  property.propertyArgs = args
  return property
}

// if this level args required in deeper resolvers
function nestedPropertyResolver (parent, args) {
  const nestedProperty = await getNestedProperty()
  nestedProperty.propertyArgs = parent.propertyArgs
  nestedProperty.nestedPropertyArgs = args
  return nestedProperty
}

function moreNestedPropertyResolver (parent) {
  // do something with parent.propertyArgs.someArgs
}

正如丹尼尔斯所说,该方法的功能有限.您可以chain结果并在儿童解析器中有条件地做出某些条件.您将有父母和被过滤的孩子...未使用子女条件过滤父母(例如在SQL ...中...和...和...在联合表上),可以在父级解析器中完成.<<<<<<<<<<

其他推荐答案

请在此处查看有关如何通过参数的答案: https://stackoverflow.com/a/a/63300135/11497165

要简化它,您可以使用args定义字段类型:

在您的类型定义

type Query{
  getCar(color: String): Car
  ... other queries
}

type Car{
  door(color: String): Door // <-- added args
  id: ID
  previousOwner(offset: Int, limit: Int): Owner // <-- added args
  ...
}

然后,在您的客户端查询中(来自Apollo客户端或您的GQL查询):

query getCar(carId:'123'){
  door(color:'grey') // <-- add variable
  id
  previousOwner(offset: 3) // <-- added variable
  ... other queries
}

您应该能够在子解析器参数中访问颜色:

在您的解析器中:

Car{
  door(root,args,context){
   const color = args.color // <-- access your arguments here
  }
  previousOwner(root,args,context){
   const offset = args.offset // <-- access your arguments here
   const limit = args.limit // <-- access your arguments here
  }
  ...others
}

为您的示例:

就像这个

{
    p1: property(someArgs: "some_value") { // <-- added variable
        id
        nestedField(someArgs: "some_value") { // <-- added variable
            id
            moreNestedField(offset: 5) {
                id
            }
        }
    }
}

其他推荐答案

您可以这样通过父字段传递值:

function propertyResolver (parent, { someArgs }) {
  const property = await getProperty()
  property.someArgs = someArgs
  return property
}

function nestedPropertyResolver ({ someArgs }) {
  const nestedProperty = await getNestedProperty()
  nestedProperty.someArgs = someArgs
  return nestedProperty
}

function moreNestedPropertyResolver ({ someArgs }) {
  // do something with someArgs
}

请注意,虽然这起作用,但它也可能首先指出了您的模式设计的根本问题.根据您如何解决这些字段(从数据库中获取它们,向另一个API提出请求等),最好完全采用另一种方法 - 例如,通过急切地将所有内容加载到根架上的所有方法.但是,没有更多的上下文,很难提出任何其他建议.

本文地址:https://www.itbaoku.cn/post/1938155.html

问题描述

My GraphQL query looks like this:

{
    p1: property(someArgs: "some_value") {
        id
        nestedField {
            id
            moreNestedField {
                id
            }
        }
    }
}

On the server side, I'm using Apollo Server. I have a resolver for the property and other resolvers for nestedField and moreNestedField. I need to retrieve the value of someArgs on my nested resolvers. I tried to do this using the context available on the resolver:

property: (_, {someArgs}, ctx) => {
    ctx.someArgs = someArgs;

    // Do something
}

But this won't work as the context is shared among all resolvers, thus if I have multiple propertyon my query, the context value won't be good.

I also tried to use the path available on info on my nested resolvers. I'm able to go up to the property field but I don't have the arguments here...

I also tried to add some data on info but it's not shared on nested resolvers.

Adding arguments on all resolvers is not an option as it would make query very bloated and cumbersome to write, I don't want that.

Any thoughts?

Thanks!

推荐答案

Params can be passed down to child resolvers using the currently returned value. Additional data will be removed from the response later.

I'll 'borrow' Daniel's code, but without specific params - pass args down as reference (suitable/cleaner/more readable for more args):

function propertyResolver (parent, args) {
  const property = await getProperty()
  property.propertyArgs = args
  return property
}

// if this level args required in deeper resolvers
function nestedPropertyResolver (parent, args) {
  const nestedProperty = await getNestedProperty()
  nestedProperty.propertyArgs = parent.propertyArgs
  nestedProperty.nestedPropertyArgs = args
  return nestedProperty
}

function moreNestedPropertyResolver (parent) {
  // do something with parent.propertyArgs.someArgs
}

As Daniels stated this method has limited functionality. You can chain results and make something conditionally in child resolver. You'll have parent and filtered children ... not filtered parent using child condition (like in SQL ... WHERE ... AND ... AND ... on joined tables), this can be done in parent resolver.

其他推荐答案

Please check this answer here on how to pass the arguments: https://stackoverflow.com/a/63300135/11497165

To simplify it, you can define your field type with args:

In your Type Definition

type Query{
  getCar(color: String): Car
  ... other queries
}

type Car{
  door(color: String): Door // <-- added args
  id: ID
  previousOwner(offset: Int, limit: Int): Owner // <-- added args
  ...
}

then, in your client query (from apollo client or your gql query):

query getCar(carId:'123'){
  door(color:'grey') // <-- add variable
  id
  previousOwner(offset: 3) // <-- added variable
  ... other queries
}

You should be able to access color in your child resolver arguments:

In your resolver:

Car{
  door(root,args,context){
   const color = args.color // <-- access your arguments here
  }
  previousOwner(root,args,context){
   const offset = args.offset // <-- access your arguments here
   const limit = args.limit // <-- access your arguments here
  }
  ...others
}

For your example:

it will be like this

{
    p1: property(someArgs: "some_value") { // <-- added variable
        id
        nestedField(someArgs: "some_value") { // <-- added variable
            id
            moreNestedField(offset: 5) {
                id
            }
        }
    }
}

其他推荐答案

You can pass the value through the parent field like this:

function propertyResolver (parent, { someArgs }) {
  const property = await getProperty()
  property.someArgs = someArgs
  return property
}

function nestedPropertyResolver ({ someArgs }) {
  const nestedProperty = await getNestedProperty()
  nestedProperty.someArgs = someArgs
  return nestedProperty
}

function moreNestedPropertyResolver ({ someArgs }) {
  // do something with someArgs
}

Note that while this works, it may also point to an underlying issue with your schema design in the first place. Depending on how you're resolving these fields (getting them from a database, making requests to another API, etc.), it may be preferable to take a different approach altogether -- for example, by eager loading everything inside the root resolver. Without more context, though, it's hard to make any additional recommendations.