发布 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)
        }
    }
}

More details

我在 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 的冲突解决文档:

更新冲突解决方案:

  1. 一种方法是按照 documentation 的建议更新它(我就是这样做的)。

  1. 我检查了更改了哪些文件,唯一重要的更新密钥可以在 amplify/backend/api/<yourApi>/transform.conf.json
  2. 中找到

发件人:

收件人: