发布 AWS Amplify GraphQL 突变时如何避免在数组中创建重复项
How to avoid creating duplicate items in an array when posting an AWS Amplify GraphQL mutation
前言:我是 GraphQL 和 Amplify 的新手。
我有一个包含两个数组的用户对象,一个名为 preferred_genres
,另一个名为 preferred_characters
。我有一个个人资料页面,用户可以在其中编辑他们的个人资料并将项目添加到这些数组。
AWS Amplify 提供的更新突变似乎只是向数组添加元素,从不删除它们。如果在我的 UI 上,我从列表中删除了一个项目,然后提交更新突变,则该项目不会从我的后端删除。如果我将一个项目添加到数组中,该项目将添加到后端,但我最终也会为那些已经在后端的项目添加重复值。
我想做的是用我从前端提交的数据覆盖后端的数组。我错过了一些明显的东西吗?在 GraphQL 中是否有更合适的方法来实现这一点?
架构
type User @model {
id: ID!
...
preferred_characters: [Character]
preferred_genres: [Genre]
...
}
实现此目的的一种方法是更改您的 updateUser 解析器以更新或创建这些条目。
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
},
## Set up some space to keep track of things you're updating **
#set( $expNames = {} )
#set( $expValues = {} )
#set( $expSet = {} )
#set( $expAdd = {} )
#set( $expRemove = [] )
## Increment "version" by 1 **
$!{expAdd.put("version", ":one")}
$!{expValues.put(":one", { "N" : 1 })}
## Iterate through each argument, skipping "id" and "expectedVersion" **
#foreach( $entry in $context.arguments.entrySet() )
#if( $entry.key != "id" && $entry.key != "expectedVersion" )
#if( (!$entry.value) && ("$!{entry.value}" == "") )
## If the argument is set to "null", then remove that attribute from the item in DynamoDB **
#set( $discard = ${expRemove.add("#${entry.key}")} )
$!{expNames.put("#${entry.key}", "$entry.key")}
#else
## Otherwise set (or update) the attribute on the item in DynamoDB **
$!{expSet.put("#${entry.key}", ":${entry.key}")}
$!{expNames.put("#${entry.key}", "$entry.key")}
$!{expValues.put(":${entry.key}", { "S" : "${entry.value}" })}
#end
#end
#end
## Start building the update expression, starting with attributes you're going to SET **
#set( $expression = "" )
#if( !${expSet.isEmpty()} )
#set( $expression = "SET" )
#foreach( $entry in $expSet.entrySet() )
#set( $expression = "${expression} ${entry.key} = ${entry.value}" )
#if ( $foreach.hasNext )
#set( $expression = "${expression}," )
#end
#end
#end
## Continue building the update expression, adding attributes you're going to ADD **
#if( !${expAdd.isEmpty()} )
#set( $expression = "${expression} ADD" )
#foreach( $entry in $expAdd.entrySet() )
#set( $expression = "${expression} ${entry.key} ${entry.value}" )
#if ( $foreach.hasNext )
#set( $expression = "${expression}," )
#end
#end
#end
## Continue building the update expression, adding attributes you're going to REMOVE **
#if( !${expRemove.isEmpty()} )
#set( $expression = "${expression} REMOVE" )
#foreach( $entry in $expRemove )
#set( $expression = "${expression} ${entry}" )
#if ( $foreach.hasNext )
#set( $expression = "${expression}," )
#end
#end
#end
## Finally, write the update expression into the document, along with any expressionNames and expressionValues **
"update" : {
"expression" : "${expression}"
#if( !${expNames.isEmpty()} )
,"expressionNames" : $utils.toJson($expNames)
#end
#if( !${expValues.isEmpty()} )
,"expressionValues" : $utils.toJson($expValues)
#end
},
"condition" : {
"expression" : "version = :expectedVersion",
"expressionValues" : {
":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion)
}
}
}
我在 API 中偶然发现了 this question in the Amplify GitHub issues about the AWSJSON scalar having a similar issue. The issue seems to be related to conflict resolution。
我不记得设置了那个,但我尝试了 amplify update API
,选择了我的 GraphQL API 和高级选项,拒绝了任何冲突解决和 运行 amplify push
.
现在值正在按预期保存。当我从数组中删除一个项目时,它会从后端和 visa-versa.
中删除
DataStore 的冲突解决文档:
更新冲突解决方案:
- 一种方法是按照 documentation 的建议更新它(我就是这样做的)。
- 我检查了更改了哪些文件,唯一重要的更新密钥可以在
amplify/backend/api/<yourApi>/transform.conf.json
中找到
发件人:
收件人:
前言:我是 GraphQL 和 Amplify 的新手。
我有一个包含两个数组的用户对象,一个名为 preferred_genres
,另一个名为 preferred_characters
。我有一个个人资料页面,用户可以在其中编辑他们的个人资料并将项目添加到这些数组。
AWS Amplify 提供的更新突变似乎只是向数组添加元素,从不删除它们。如果在我的 UI 上,我从列表中删除了一个项目,然后提交更新突变,则该项目不会从我的后端删除。如果我将一个项目添加到数组中,该项目将添加到后端,但我最终也会为那些已经在后端的项目添加重复值。
我想做的是用我从前端提交的数据覆盖后端的数组。我错过了一些明显的东西吗?在 GraphQL 中是否有更合适的方法来实现这一点?
架构
type User @model {
id: ID!
...
preferred_characters: [Character]
preferred_genres: [Genre]
...
}
实现此目的的一种方法是更改您的 updateUser 解析器以更新或创建这些条目。
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
},
## Set up some space to keep track of things you're updating **
#set( $expNames = {} )
#set( $expValues = {} )
#set( $expSet = {} )
#set( $expAdd = {} )
#set( $expRemove = [] )
## Increment "version" by 1 **
$!{expAdd.put("version", ":one")}
$!{expValues.put(":one", { "N" : 1 })}
## Iterate through each argument, skipping "id" and "expectedVersion" **
#foreach( $entry in $context.arguments.entrySet() )
#if( $entry.key != "id" && $entry.key != "expectedVersion" )
#if( (!$entry.value) && ("$!{entry.value}" == "") )
## If the argument is set to "null", then remove that attribute from the item in DynamoDB **
#set( $discard = ${expRemove.add("#${entry.key}")} )
$!{expNames.put("#${entry.key}", "$entry.key")}
#else
## Otherwise set (or update) the attribute on the item in DynamoDB **
$!{expSet.put("#${entry.key}", ":${entry.key}")}
$!{expNames.put("#${entry.key}", "$entry.key")}
$!{expValues.put(":${entry.key}", { "S" : "${entry.value}" })}
#end
#end
#end
## Start building the update expression, starting with attributes you're going to SET **
#set( $expression = "" )
#if( !${expSet.isEmpty()} )
#set( $expression = "SET" )
#foreach( $entry in $expSet.entrySet() )
#set( $expression = "${expression} ${entry.key} = ${entry.value}" )
#if ( $foreach.hasNext )
#set( $expression = "${expression}," )
#end
#end
#end
## Continue building the update expression, adding attributes you're going to ADD **
#if( !${expAdd.isEmpty()} )
#set( $expression = "${expression} ADD" )
#foreach( $entry in $expAdd.entrySet() )
#set( $expression = "${expression} ${entry.key} ${entry.value}" )
#if ( $foreach.hasNext )
#set( $expression = "${expression}," )
#end
#end
#end
## Continue building the update expression, adding attributes you're going to REMOVE **
#if( !${expRemove.isEmpty()} )
#set( $expression = "${expression} REMOVE" )
#foreach( $entry in $expRemove )
#set( $expression = "${expression} ${entry}" )
#if ( $foreach.hasNext )
#set( $expression = "${expression}," )
#end
#end
#end
## Finally, write the update expression into the document, along with any expressionNames and expressionValues **
"update" : {
"expression" : "${expression}"
#if( !${expNames.isEmpty()} )
,"expressionNames" : $utils.toJson($expNames)
#end
#if( !${expValues.isEmpty()} )
,"expressionValues" : $utils.toJson($expValues)
#end
},
"condition" : {
"expression" : "version = :expectedVersion",
"expressionValues" : {
":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion)
}
}
}
我在 API 中偶然发现了 this question in the Amplify GitHub issues about the AWSJSON scalar having a similar issue. The issue seems to be related to conflict resolution。
我不记得设置了那个,但我尝试了 amplify update API
,选择了我的 GraphQL API 和高级选项,拒绝了任何冲突解决和 运行 amplify push
.
现在值正在按预期保存。当我从数组中删除一个项目时,它会从后端和 visa-versa.
中删除DataStore 的冲突解决文档:
更新冲突解决方案:
- 一种方法是按照 documentation 的建议更新它(我就是这样做的)。
- 我检查了更改了哪些文件,唯一重要的更新密钥可以在
amplify/backend/api/<yourApi>/transform.conf.json
中找到
发件人:
收件人: