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

时间:2018-09-26 07:14:14

标签: 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!
}

当我打电话时:

query GetBook {
  book(id: 123, consistentRead: true) {
    articles {
      title
    }
  }
}

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

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

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

6 个答案:

答案 0 :(得分:5)

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

AppSync在$context中有几个容器:

  • 参数
  • 隐藏
从以下Cloudwatch日志中可以明显看出,在调用子解析器之前,始终会清除

argumentsstash

父级执行的最后-出现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
}

,然后在子解析器的开头 -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
}

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

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

#set($device = $util.defaultIfNullOrBlank($ctx.args.device, $ctx.source.items[0].device))

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

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

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

{
    "items": $utils.toJson($context.result.items),
    "device": "${ctx.args.device}"
}

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

答案 1 :(得分:1)

对我来说,要在所有相关解析器(嵌套的或与集合实体相关的)中实现可用性很好,解决方法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")))

并从嵌套/其他请求映射模板中读取以下值:

#set($profile = $ctx.request.headers.profile)

这使得在相关解析器之间需要的任何位置都可以使用父参数。在您的情况下,它将是“设备”和一些默认值,或者在不需要时不包含该部分。

答案 2 :(得分:0)

您不需要将参数传递给子查询。根据您的架构和用例,我认为您可以像下面那样调整您的架构,以在AuthorBook之间建立关系

type Author {
    # parent's id
    bookID: ID!
    # author id
    id: ID!
    name: String!
}

type Book {
    id: ID!
    title: String!
    author: [Author]!
}

type Mutation {
    insertAuthor(bookID: ID!, id: ID!, name: String!): Author
    insertBook(id: ID!, title: String!): Book
}

type Query {
    getBook(id: ID!): Book
}

-使用Author.bookID作为主键和Author.id作为排序键创建表Author
 -以Book.id作为主键创建表格Book

然后,您必须为Book.author附加解析器

enter image description here

这是insertAuthor突变的解析器

{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        "bookID" : $util.dynamodb.toDynamoDBJson($ctx.args.bookID),
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    },
    "attributeValues" : {
        "name" : $util.dynamodb.toDynamoDBJson($ctx.args.name)
    }
}

当您查询getBook时,您将获得与下面的书号相同的作者列表

enter image description here

答案 3 :(得分:0)

仅在子级中使用$ ctx.source。 id ,其中 id 是您需要从父级引用的参数。

答案 4 :(得分:0)

将此添加到BookQuery响应映射模板

#set( $book = $ctx.result )
#set($Articles = []);
#foreach($article in $book.articles)
    #set( $newArticle = $article )
    $util.qr($newArticle.put("bookID", $book.id))
    $util.qr($Articles.add($newArticle))
#end
$util.qr($book.put("articles", $Articles))
$util.toJson($book)

现在,每篇文章都将具有bookID

答案 5 :(得分:0)

您应该能够在consistentRead$context.info.variables)中找到$context.info.variables.consistentReadhttps://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html#aws-appsync-resolver-context-reference-info