AWS AppSync:将参数从父级解析器传递给子级

jos*_*our 6 graphql aws-appsync appsync-apollo-client

在AWS AppSync中,似乎不会将在主查询上发送的参数转发给所有子解析器。

type Query {
  article(id: String!, consistentRead: Boolean): Article
  book(id: String!, consistentRead: Boolean): Book
}

type Article {
  title: String!
  id: String!
}

type Book {
  articleIds: [String]!
  articles: [Article]!
  id: String!
}
Run Code Online (Sandbox Code Playgroud)

当我打电话时:

query GetBook {
  book(id: 123, consistentRead: true) {
    articles {
      title
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

获取书的第一个查询在中接收consistentRead参数$context.arguments,但随后的检索文章的查询则没有。($context.arguments为空)

我也尝试过articles(consistentRead: Boolean): [Article]!里面book但是没有运气。

有谁知道在AppSync中是否可以将参数传递给同一请求的所有查询?

max*_*max 7

可以通过响应将参数从父级传递到子级。让我解释 ...

AppSync内部有几个容器$context

  • 论点
  • 资源

arguments并且stash在调用子解析器之前总是被清除,从这些Cloudwatch日志可以明显看出:

在父执行的最后 - argumentsstash数据都存在。

{
    "errors": [],
    "mappingTemplateType": "After Mapping",
    "path": "[getLatestDeviceState]",
    "resolverArn": "arn:aws:appsync:us-east-1:xxx:apis/yyy/types/Query/fields/getLatestDeviceState",
    "context": {
        "arguments": {
            "device": "ddddd"
        },
        "prev": {
            "result": {
                "items": [
                    {
                        "version": "849",
                        "device": "ddddd",
                        "timestamp": "2019-01-29T12:18:34.504+13:00"
                    }
                ]
            }
        },
        "stash": {"testKey": "testValue"},
        "outErrors": []
    },
    "fieldInError": false
}
Run Code Online (Sandbox Code Playgroud)

然后在开始的时候孩子解析器的 - argumentsstash总是空白。

{
"errors": [],
"mappingTemplateType": "Before Mapping",
"path": "[getLatestDeviceState, media]",
"resolverArn": "arn:aws:appsync:us-east-1:yyy:apis/xxx/types/DeviceStatePRODConnection/fields/media",
"context": {
    "arguments": {},
    "source": {
        "items": [
            {
                "version": "849",
                "device": "ddddd",
                "timestamp": "2019-01-29T12:18:34.504+13:00"
            }
        ]
    },
    "stash": {},
    "outErrors": []
},
"fieldInError": false
}
Run Code Online (Sandbox Code Playgroud)

解决方法1-从先前的结果中获取参数。

在上面的示例中,device始终存在于父解析器的响应中,因此我插入了

#set($device = $util.defaultIfNullOrBlank($ctx.args.device, $ctx.source.items[0].device))
Run Code Online (Sandbox Code Playgroud)

进入子解析器请求映射模板。它将尝试从参数中获取所需的ID,然后回退到先前的结果。

解决方法2-将参数添加到父响应中

修改您的父解析器响应模板以包含以下参数:

{
    "items": $utils.toJson($context.result.items),
    "device": "${ctx.args.device}"
}
Run Code Online (Sandbox Code Playgroud)

然后以与第一种解决方法相同的方式在子级的请求映射模板中检索它。


小智 5

要在所有相关解析器(嵌套或与集合实体相关的)中实现可用性对我来说很好解决方法 2(tnx Max对于这样一个好的答案)但仅适用于子解析器。在另一种情况下,当我需要从集合查询(包含除实体之外的其他字段)中解析实体时,添加到响应映射模板的属性不再可用。所以我的解决方案是将其设置为请求标头:

##Set parent query profile parameter to headers to achieve availability accross related resolvers.
#set( $headers = $context.request.headers )
$util.qr($headers.put("profile", $util.defaultIfNullOrBlank($context.args.profile, "default")))
Run Code Online (Sandbox Code Playgroud)

并从您的嵌套/其他请求映射模板中读取此值:

#set($profile = $ctx.request.headers.profile)
Run Code Online (Sandbox Code Playgroud)

这使得父参数在相关解析器之间我需要的任何地方都可用。在您的情况下,它将是“设备”和一些默认值,如果不需要,则没有该部分。