У меня есть необязательное поле String, Примечания, которое иногда бывает пустым. Если он пуст, я хочу вставить нулевой, в противном случае я хочу вставить строку.
Вот мой резолвер -
{
"version" : "2017-02-28",
"operation": "Invoke",
#set($id = $util.autoId())
#set($notes = $util.defaultIfNullOrEmpty($context.arguments.notes, 'null'))
"payload": {
"sql":"INSERT INTO things VALUES ('$id', :NOTES)",
"variableMapping": {
":NOTES" : $notes
},
"responseSQL": "SELECT * FROM things WHERE id = '$id'"
}
}
С помощью этого graphql
mutation CreateThing{
createThing() {
id
notes
}
}
Я получил -
{
"data": {
"createRoll": {
"id": "6af68989-0bdc-44e2-8558-aeb4c8418e93",
"notes": "null"
}
}
}
когда мне действительно нужен нулевой без кавычек.
И с этим graphql -
mutation CreateThing{
createThing(notes: "Here are some notes") {
id
notes
}
}
Я получил -
{
"data": {
"createThing": {
"id": "6af68989-0bdc-44e2-8558-aeb4c8418e93",
"notes": "Here are some notes"
}
}
}
чего я и хочу.
Как мне поместить пустое значение без кавычек и строку в кавычках в одно и то же поле?





TL; DR, вы должны использовать $util.toJson() для правильной печати $context.arguments.notes. Замените назначение $notes на
#set($notes = $util.toJson($util.defaultIfNullOrEmpty($context.arguments.notes, null)))
Объяснение:
Причина в том, что VTL печатает все, что возвращает метод toString(), и ваш вызов
$util.defaultIfNullOrEmpty($context.arguments.notes, 'null') вернет строку "null", которая будет напечатана как "null".
Если вы замените его на $util.defaultIfNullOrEmpty($context.arguments.notes, null), он вернет строку null. Однако VTL будет печатать $notes, потому что именно так он обрабатывает ссылки null. Чтобы напечатать null, которое является допустимым JSON-представлением null, мы должны сериализовать его в JSON. Итак, правильное утверждение:
#set($notes = $util.toJson($util.defaultIfNullOrEmpty($context.arguments.notes, null)))
Полный тест:
Я предполагаю, что вы начали с образца RDS, представленного в консоли AWS AppSync, и изменили его. Для воспроизведения я обновил поле content в схеме, чтобы оно допускало значение NULL:
type Mutation {
...
createPost(author: String!, content: String): Post
...
}
type Post {
id: ID!
author: String!
content: String
views: Int
comments: [Comment]
}
и я изменил схему таблицы posts, поэтому content также может быть нулевым: (внутри лямбда-функции)
function conditionallyCreatePostsTable(connection) {
const createTableSQL = `CREATE TABLE IF NOT EXISTS posts (
id VARCHAR(64) NOT NULL,
author VARCHAR(64) NOT NULL,
content VARCHAR(2048),
views INT NOT NULL,
PRIMARY KEY(id))`;
return executeSQL(connection, createTableSQL);
}
Это шаблон запроса на мутацию createPost:
{
"version" : "2017-02-28",
"operation": "Invoke",
#set($id = $util.autoId())
"payload": {
"sql":"INSERT INTO posts VALUES ('$id', :AUTHOR, :CONTENT, 1)",
"variableMapping": {
":AUTHOR" : "$context.arguments.author",
":CONTENT" : $util.toJson($util.defaultIfNullOrEmpty($context.arguments.content, null))
},
"responseSQL": "SELECT id, author, content, views FROM posts WHERE id = '$id'"
}
}
и шаблон ответа:
$util.toJson($context.result[0])
Следующий запрос:
mutation CreatePost {
createPost(author: "Me") {
id
author
content
views
}
}
возвращает:
{
"data": {
"createPost": {
"id": "b42ee08c-956d-4b89-afda-60fe231e86d7",
"author": "Me",
"content": null,
"views": 1
}
}
}
и
mutation CreatePost {
createPost(author: "Me", content: "content") {
id
author
content
views
}
}
возвращается
{
"data": {
"createPost": {
"id": "c6af0cbf-cf05-4110-8bc2-833bf9fca9f5",
"author": "Me",
"content": "content",
"views": 1
}
}
}
Мы занимались той же проблемой. По какой-то причине принятый ответ у нас не работает. Возможно, потому, что это бета-функция и есть новая версия преобразователя (2018-05-29 против 2017-02-28, здесь изменения: Журнал изменений шаблона сопоставления преобразователя).
Мы используем это на данный момент с помощью NULLIF():
{
"version": "2018-05-29",
"statements": [
"INSERT INTO sales_customers_addresses (`id`, `customerid`, `type`, `company`, `country`, `email`) VALUES (NULL, :CUSTOMERID, :TYPE, NULLIF(:COMPANY, ''), NULLIF(:COUNTRY, ''), :EMAIL)"
],
"variableMap": {
":CUSTOMERID": $customerid,
":TYPE": "$type",
":COMPANY": "$util.defaultIfNullOrEmpty($context.args.address.company, '')",
":COUNTRY": "$util.defaultIfNullOrEmpty($context.args.address.country, '')",
":EMAIL": "$context.args.address.email"
}
}
В моем ответе используется версия 2017-02-28, потому что она привязана к источнику данных Lambda, а не к источнику данных RDS. Lambda поддерживает версии как 2017-02-28, так и 2018-05-29. Исходный вопрос, размещенный здесь, был связан с этим руководством github.com/aws-samples/aws-appsync-rds-aurora-sample. Он использует Lambda в качестве источника данных AppSync для прокси-вызова RDS. Это руководство было создано до того, как RDS изначально была поддержана AppSync, в зависимости от вашего варианта использования теперь может иметь больше смысла напрямую использовать источник данных RDS.