I am working on DynamoDB with the help of AppSync GraphQL queries.
I have a one DynamoDB table in which username is Partition key(hash key) and timestamp_value is sort key(range key).
I am saving two things against one item i.e. one is reading and second one is activity (like exercise, sports etc.) For adding this two things we have different UI screens. Both things might have same timestamp so it will save in one item.
So now I need a upsert (insert or update) query which can be used for both the above operations because when you try to insert new reading then it will check that item is present or not. If present then it will update or not then it will insert the item and same thing has to happen when user want to add a new activity.
I am confused with the documentation and I didn't find exact AppSync request mapping resolver for doing upsert operation.
Below is the PutItem request mapping resolver :-
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"username": $util.dynamodb.toDynamoDBJson($ctx.identity.username),
"timestamp": $util.dynamodb.toDynamoDBJson($ctx.args.input.timestamp),
},
"attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
"condition": {
"expression": "attribute_not_exists(#timestamp)",
"expressionNames": {
"#timestamp": "timestamp",
},
},
}
And below is the UpdateItem request mapping resolver:-
{
"version": "2017-02-28",
"operation": "UpdateItem",
"key": {
"username": $util.dynamodb.toDynamoDBJson($ctx.identity.username),
"timestamp": $util.dynamodb.toDynamoDBJson($ctx.args.input.timestamp),
},
## Set up some space to keep track of things we're updating **
#set( $expNames = {} )
#set( $expValues = {} )
#set( $expSet = {} )
#set( $expAdd = {} )
#set( $expRemove = [] )
## Iterate through each argument, skipping keys **
#foreach( $entry in $util.map.copyAndRemoveAllKeys($ctx.args.input, ["username", "timestamp"]).entrySet() )
#if( $util.isNull($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}", $util.dynamodb.toDynamoDB($entry.value))}
#end
#end
## Start building the update expression, starting with attributes we'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 we'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 we'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": "SET attribute_exists(#username) AND attribute_not_exists(#timestamp)",
"expressionNames": {
"#username": "username",
"#timestamp": "timestamp",
},
}
}
So how can I update the resolver so that I can do upsert operation?