Trying to remove item from a list in AWS AppSync in VTL - amazon-web-services

I am trying to make a custom resolver in VTL that will remove a certain string from a dynamodb list. I was trying to use $util.list.copyAndRemoveAll to remove the friend from the list. But I am not quite sure how to use it and the documentation isn't very clear to me and I don't even know if I am using the function correctly within VTL. https://docs.aws.amazon.com/appsync/latest/devguide/list-helpers-in-util-list.html
Thank you in advance.
GraphQL mutation
type Mutation {
removeFromIncomingFriendList(pk: String!, sk: String!, friend: String!): String!
}
#user_incoming_friend_requests is a list of usernames of users that have sent friend requests.
{
"version" : "2018-05-29",
"operation" : "UpdateItem",
"key" : {
"pk" : { "S" : "USER#USERNAME" },
"sk" : { "S" : "METADATA#USERNAME" },
},
"update": {
"expression" : "SET #user_incoming_friend_requests = :newList ADD version :plusOne",
"expressionNames": {
"#user_incoming_friend_requests" : "user_incoming_friend_requests",
},
"expressionValues" : {
":newList": $util.list.copyAndRemoveAll("#user_incoming_friend_requests", [${context.arguments.friend}])
":plusOne" : {"N":1}
}
}
}

Related

AWS AppSync vtl make set null if argument is empty list

I want to update a 'person' item in my table.
I want to update the persons name and his set of skills.
It's also possible that we just use the updatePerson mutation to update the name. And we will update the skills later.
At that point the argument 'skills' is an empty list. However DynamoDB does not allow for empty sets.
Currently I am trying to work around this by first checking if the skills argument is an empty list. But it is still telling me "An string set may not be empty for key :skills".
This is my current request mapping template, but atm the isNullOrDefault check does not work.
#if ($util.isNullOrEmpty($context.arguments.skills))
#set ($skills = $utils.dynamodb.toNullJson())
#else
#set ($skills = $utils.dynamodb.toStringSetJson($context.arguments.skills))
#end
{
"version" : "2018-05-29",
"operation" : "UpdateItem",
"key": {
"id" : $utils.dynamodb.toDynamoDBJson($context.arguments.id)
},
"update" : {
"expression" : "set #name = :name, #skills= :skills,
"expressionNames" : {
"#name": "name",
"#skills": "skills",
},
"expressionValues" : {
":name" : $utils.dynamodb.toDynamoDBJson($context.arguments.name),
":skills" : $skills,
}
}
}
Do you know how I can set the set of skills if the skills argument is not an empty array and not set it if the skills argument is an empty array?
Instead of setting null into a string-set attribute, I think you just remove the attribute from the item item.skills = undefined.
You can use SET, and REMOVE actions to achieve that. The update is dynamically generated based on the input of skills. Sample code (I haven't tested it myself)
#set ($update = {
"expression" : "set #name = :name remove #skills",
"expressionNames" : {
"#name": "name",
"#skills": "skills"
},
"expressionValues" : {
":name" : $utils.dynamodb.toDynamoDBJson($context.arguments.name)
}
})
#if (!$util.isNullOrEmpty($context.arguments.skills))
#set ($update = {
"expression" : "set #name = :name set #skills = $skill",
"expressionNames" : {
"#name": "name",
"#skills": "skills"
},
"expressionValues" : {
":name" : $utils.dynamodb.toDynamoDBJson($context.arguments.name),
":skills" :$utils.dynamodb.toStringSetJson($context.arguments.skills),
}
})
#end
{
"version" : "2018-05-29",
"operation" : "UpdateItem",
"key": {
"id" : $utils.dynamodb.toDynamoDBJson($context.arguments.id)
},
"update" : $update // or maybe $util.toJson($update)
}

update dynamodb list item

This seems like it should be really simple but I haven't found any examples or documentation. I've got a dynamodb table that looks like this:
record 1: {name, email, items[{product}, {item2}, {item3]}
record 2: (name, email, items[{product}, {item2}, {item3]}
I need to be able to update items elements, i.e., update item1 object in record 1. I can do this with the following code by hardcoding the list array element, but I can't figure out how to pass the item number into the update expression :
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : { "S" : "${context.arguments.input.id}" }
},
"update" : {
"expression" : "SET #items[0].#product= :productVal",
"expressionNames" : {
"#product": "product",
},
"expressionValues" : {
":productVal": { "S" : "${context.arguments.input.product}" },
}
}
Have you tried something like:
"update" : {
"expression" : "SET #items[:idx].#product= :productVal",
"expressionNames" : {
"#product": "product",
},
"expressionValues" : {
":productVal": { "S" : "${context.arguments.input.product}" },
":idx": { "N" : 0 }
}
}

How to defined filter expression to filter nested json array based on object key value in aws app sync query filter?

I have the following filter conditions to be for filtering studentBookmark json array based on value of JSON key. I want to know how to filter the queried data based on object value key from JSON array.
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
## Provide a query expression. **
"expression": "studentId = :id",
"expressionValues" : {
":id" : $util.dynamodb.toDynamoDBJson($ctx.identity.username)
}
},
"filter" : {
## --- issue here for studentBookmarks -- Need help ----
"expression": "isBookmarked = :isBookmarked OR studentBookmarks.studentId = :studentId",
"expressionValues" : {
":isBookmarked" : { "BOOL": true },
":studentId": { "S": "${ctx.identity.username}" },
},
},
"index": "studentId-index",
}
I want to know what proper expression to be given to filter based nested json array.

How I can update boolean field in DynamoDb with Mapping template?

I have next code for update item in DB with mapping template:
$!{expSet.put("available", ":available")}
$!{expValues.put(":available", { "BOOL": $ctx.args.available })}
when I send available = false - it's ok, but if available = true I get error
"Unable to parse the JSON document: 'Unexpected character (':' (code
58)): was expecting double-quote to start field name
schema in GraphQl
type Item {
....
available: Boolean!
....
}
What I do wrong ?
Your UpdateItem request mapping template should look something like:
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : { "S" : "${context.arguments.id}" }
},
"update" : {
"expression" : "SET #available = :available",
"expressionNames": {
"#available" : "available"
},
"expressionValues": {
":available" : { "BOOL": ${context.arguments.available} }
}
}
}

How to use multiple global secondary indexes for app sync query?

I have three condition terms in where like condition. I have specified there indexes in the dynamo db table. I require a way specify all three indexes if that is a good practice or any other way to query based on the expression.
Also I want to know whether the expression is a valid one or not.
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
## Also not sure about the query expression. Is it valid ?
"expression": "studentId = :studentId and (chapterId = :chapterId isUserAudio = :isUserAudio)",
"expressionValues" : {
":studentId" : {
"S" : "${ctx.args.studentId}"
},
":chapterId": {
"S": "${ctx.args.chapterId}"
},
":isUserAudio": {
"BOOL": "${ctx.args.isUserAudio}"
}
}
},
"index": "" # can multiple indexes be specified here
}
I believe you should be able to use a combination of query expressions and filter expressions to achieve your goal. Try changing your resolver to this:
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
"expression": "studentId = :studentId",
"expressionValues" : {
":studentId" : {
"S" : "${ctx.args.studentId}"
}
}
},
"filter" : {
"expression": "chapterId = :chapterId AND isUserAudio = :isUserAudio",
"expressionValues" : {
":chapterId": {
"S": "${ctx.args.chapterId}"
},
":isUserAudio": {
"BOOL": "${ctx.args.isUserAudio}"
}
}
},
"index": "the-index-with-studentId-as-a-hashkey"
}
This will initially query the index and then with the results from the index will apply a filter to the values. Let me know if that works!
Hope this helps
You can only Query one table or one index at a time. It is not possible to execute one query that accesses more than one table or index. You will need to Query each index separately and combine the data in your application.
DynamoDB comparator guide is here. The expression is not valid. Maybe you want:
studentId = :studentId AND chapterId = :chapterId AND isUserAudio = :isUserAudio