如何使用 AppSync 解析器和 Aurora 将可选字段插入为 null?
How do I insert an optional field as null using AppSync Resolvers and Aurora?
我有一个可选的字符串字段 notes,它有时是空的。如果它是空的我想插入null,否则我想插入字符串
这是我的解析器 -
{
"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"
}
}
}
当我真的想要不带引号的 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"
}
}
}
这就是我想要的。
如何将无引号的 null 和带引号的字符串放入同一字段?
TL;DR 你应该使用 $util.toJson()
来正确打印 $context.arguments.notes
。将您的 $notes
作业替换为
#set($notes = $util.toJson($util.defaultIfNullOrEmpty($context.arguments.notes, null)))
解释:
原因是 VTL 会打印 toString()
方法 return 和您对
$util.defaultIfNullOrEmpty($context.arguments.notes, 'null')
将 return 字符串 "null"
,将打印为 "null"
。
如果您用 $util.defaultIfNullOrEmpty($context.arguments.notes, null)
替换,那么它将 return 一个 null
字符串。但是,VTL 将打印 $notes
,因为这是它处理 null
引用的方式。为了打印 null
,这是 null
的有效 JSON 表示,我们必须将其序列化为 JSON。所以正确的说法是:
#set($notes = $util.toJson($util.defaultIfNullOrEmpty($context.arguments.notes, null)))
完整测试:
我假设您从 AWS AppSync 控制台中提供的 RDS 示例开始并对其进行了修改。为了重现,我将架构中的 content
字段更新为可为空:
type Mutation {
...
createPost(author: String!, content: String): Post
...
}
type Post {
id: ID!
author: String!
content: String
views: Int
comments: [Comment]
}
并且我修改了 posts
table 架构,因此 content
也可以在那里为空:(在 Lambda 函数内)
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
}
}
returns:
{
"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
}
}
returns
{
"data": {
"createPost": {
"id": "c6af0cbf-cf05-4110-8bc2-833bf9fca9f5",
"author": "Me",
"content": "content",
"views": 1
}
}
}
我们正在调查同一问题。出于某种原因,接受的答案对我们不起作用。可能是因为它是测试版功能并且有一个新的解析器版本(2018-05-29 与 2017-02-28,此处更改:Resolver Mapping Template Changelog)。
我们暂时使用这个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"
}
}
我有一个可选的字符串字段 notes,它有时是空的。如果它是空的我想插入null,否则我想插入字符串
这是我的解析器 -
{
"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"
}
}
}
当我真的想要不带引号的 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"
}
}
}
这就是我想要的。
如何将无引号的 null 和带引号的字符串放入同一字段?
TL;DR 你应该使用 $util.toJson()
来正确打印 $context.arguments.notes
。将您的 $notes
作业替换为
#set($notes = $util.toJson($util.defaultIfNullOrEmpty($context.arguments.notes, null)))
解释:
原因是 VTL 会打印 toString()
方法 return 和您对
$util.defaultIfNullOrEmpty($context.arguments.notes, 'null')
将 return 字符串 "null"
,将打印为 "null"
。
如果您用 $util.defaultIfNullOrEmpty($context.arguments.notes, null)
替换,那么它将 return 一个 null
字符串。但是,VTL 将打印 $notes
,因为这是它处理 null
引用的方式。为了打印 null
,这是 null
的有效 JSON 表示,我们必须将其序列化为 JSON。所以正确的说法是:
#set($notes = $util.toJson($util.defaultIfNullOrEmpty($context.arguments.notes, null)))
完整测试:
我假设您从 AWS AppSync 控制台中提供的 RDS 示例开始并对其进行了修改。为了重现,我将架构中的 content
字段更新为可为空:
type Mutation {
...
createPost(author: String!, content: String): Post
...
}
type Post {
id: ID!
author: String!
content: String
views: Int
comments: [Comment]
}
并且我修改了 posts
table 架构,因此 content
也可以在那里为空:(在 Lambda 函数内)
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
}
}
returns:
{
"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
}
}
returns
{
"data": {
"createPost": {
"id": "c6af0cbf-cf05-4110-8bc2-833bf9fca9f5",
"author": "Me",
"content": "content",
"views": 1
}
}
}
我们正在调查同一问题。出于某种原因,接受的答案对我们不起作用。可能是因为它是测试版功能并且有一个新的解析器版本(2018-05-29 与 2017-02-28,此处更改:Resolver Mapping Template Changelog)。
我们暂时使用这个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"
}
}