AWS AppSync: передать аргументы от родительского распознавателя детям
В 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 передавать аргументы всем запросам в рамках одного и того же запроса?
1 ответ
Можно передать аргументы от родителя к ребенку через ответ. Позволь мне объяснить...
AppSync имеет несколько контейнеров внутри $context
:
- аргументы
- копить
- источник
arguments
а также stash
всегда очищаются перед вызовом дочернего распознавателя, как видно из этих журналов Cloudwatch:
В самом конце родительского исполнения - arguments
а также stash
данные присутствуют.
{
"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
}
а потом в самом начале детского резольвера - arguments
а также stash
всегда пустые
{
"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))
в шаблон отображения запроса дочернего резольвера. Он попытается получить требуемый идентификатор из аргументов и затем вернется к предыдущему результату.
Обходной путь 2 - добавьте аргумент в родительский ответ
Измените шаблон ответа родительского распознавателя, включив в него аргументы:
{
"items": $utils.toJson($context.result.items),
"device": "${ctx.args.device}"
}
и затем получить его в шаблоне запроса дочернего элемента так же, как в первом обходном пути.
Для достижения доступности для всех связанных преобразователей (вложенных или связанных с объектами коллекции) для меня было отличное решение 2 (tnx Max Voskob для такого хорошего ответа), но только для дочерних преобразователей. В другом случае, когда мне нужно было разрешить сущности из запроса коллекции (содержит другие поля, кроме сущности), свойство, добавленное в шаблон сопоставления ответов, больше не было доступно. Итак, моим решением было настроить его на запрос заголовков:
##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)
Это делает родительский аргумент доступным везде, где он мне нужен, между связанными преобразователями. В вашем случае это будет "устройство" и какое-то значение по умолчанию или без этой части, если она не нужна.
Добавьте это в шаблон сопоставления ответов 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
Просто в детстве используйте $ctx.source.id
где id
это параметр, на который вам нужна ссылка от родителя.
Вы должны найти
consistentRead
в
$context.info.variables
($context.info.variables.consistentRead
):https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html#aws-appsync-resolver-context-reference-info.
Вам не нужно передавать аргументы в подзапрос. Основываясь на своей схеме и сценарии использования, я думаю, что вы можете настроить свою схему, как показано ниже, чтобы иметь связь между Author
а также Book
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 с Author.bookID
в качестве первичного ключа и Author.id
в качестве ключа сортировки
- Создать таблицу Book с Book.id
в качестве первичного ключа
Затем вы должны прикрепить резольвер для Book.author
И вот решатель для 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
вы получите список авторов с таким же идентификатором книги, как показано ниже