I'd like to add a string word to the listOfVideosRated[]
list in my Users table.

- 425
- 2
- 14
- 34
-
1I think you will need to get the record first, then update the record and push. The records in dynamo are stored as json objects, I don't think can modify an objects keys, just replace them. I could be wrong – Seth McClaine Jul 17 '19 at 22:28
1 Answers
If you can post your schema / resolver mapping template I can offer more specific advice, but I'll do my best to answer this with what you've posted so far.
Simple Way
If you have the existing item already, one way to do this would be to update the existing Pairs and pass that to your existing mutation.
const existingItem = {
id: "e5eb02ae-04d5-4331-91e6-11efaaf12ea5",
Pairs: [['a', 'b'],['c', 'd'],['e', 'f']]
}
const newPairs = {
number1: "g",
number2: "h"
}
const updateinfo = {
id: existingItem.id,
// Note that if existingItem.Pairs is always defined this can be simplified to
// Pairs: [...existingItem.Pairs, [newPairs.number1, newPairs.number2]]
Pairs: existingItem.Pairs ?
[...existingItem.Pairs, [newPairs.number1, newPairs.number2]] :
[[newPairs.number1, newPairs.number2]]
}
try {
await API.graphql(graphqlOperation (UpdateInfo, { input: updateinfo }))
//mutation
console.log('success')
}
catch (err) {
console.log(err)
}
Using DynamoDB functions
If you do not have the existing item or if Pairs
can be pretty big, AWS DynamoDB's list_append
function can be used instead.
list_append (operand, operand)
This function evaluates to a list with a new element added to it. You can append the new element to the start or the end of the list by reversing the order of the operands.
Here is an example with a specific mutation that uses it.
### SDL
type Item {
id: ID!
Pairs: [[String]]
}
input AddPairInput {
id: ID!
number1: String!
number2: String!
}
type Mutation {
addPairToItem(input: AddPairInput!): Item!
}
...rest of schema omitted for brevity
### Resolver Request Mapping Template
{
"version": "2017-02-28",
"operation": "UpdateItem",
"key": {
"id": { "S": "$ctx.args.input.id"}
},
"update": {
### Note: we also use if_not_exists here so this works if Pairs is not yet defined on the item.
"expression":"SET Pairs = list_append(if_not_exists(Pairs, :emptyList), :newPair)",
"expressionValues":
{
":newPair":{"L": [{"L":[{"S":"$ctx.args.input.number1"},
{"S":"$ctx.args.input.number2"}]}]},
":emptyList":{"L": []}
}
}
}
### Resolver Response Mapping Template
$util.toJson($ctx.result)
This way is also nice because if someone else updates Pairs, you won't overwrite their update. You can also add the new Pair to the beginning of the list by inverting the order of your arguments to the list_append
function.
DynamoDB Functions with AWS Amplify
If your project was generated by AWS Amplify, you will need to add a customer resolver.
Step 1: Add a new mutation to your schema
### ./amplify/backend/api/<api_name>/schema.graphql
type Item @model {
id: ID!
Pairs: [[String]]
}
type Mutation {
addPairToItem(input: AddPairToItemInput!): Item!
}
input AddPairToItemInput {
id: ID!
number1: String!
number2: String!
}
Step 2: Add a resolver request mapping template
### ./amplify/backend/api/<api_name>/resolvers/Mutation.addPairToItem.req.vtl
{
"version": "2017-02-28",
"operation": "UpdateItem",
"key": {
"id": { "S": "$ctx.args.input.id"}
},
"update": {
"expression":"SET Pairs = list_append(if_not_exists(Pairs, :emptyList), :newPair)",
"expressionValues":
{
":newPair":{"L": [{"L":[{"S":"$ctx.args.input.number1"},{"S":"$ctx.args.input.number2"}]}]},
":emptyList":{"L": []}
}
}
}
Step 3: Add a resolver response mapping template
### ./amplify/backend/api/<api_name>/resolvers/Mutation.addPairToItem.res.vtl
$util.toJson($ctx.result)
Step 4: Add your custom resolver to your CustomResources stack
### ./amplify/backend/api/<api_name>/stacks/CustomResources.json
"Resources": {
// ...other resources may exist here
"AddPairToItemResolver": {
"Type": "AWS::AppSync::Resolver",
"Properties": {
"ApiId": {
"Ref": "AppSyncApiId"
},
"DataSourceName": "ItemTable",
"TypeName": "Mutation",
"FieldName": "addPairToItem",
"RequestMappingTemplateS3Location": {
"Fn::Sub": [
"s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Mutation.addPairToItem.req.vtl",
{
"S3DeploymentBucket": {
"Ref": "S3DeploymentBucket"
},
"S3DeploymentRootKey": {
"Ref": "S3DeploymentRootKey"
}
}
]
},
"ResponseMappingTemplateS3Location": {
"Fn::Sub": [
"s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Mutation.addPairToItem.res.vtl",
{
"S3DeploymentBucket": {
"Ref": "S3DeploymentBucket"
},
"S3DeploymentRootKey": {
"Ref": "S3DeploymentRootKey"
}
}
]
}
}
}
},
Step 5: Build and Deploy your new changes
- Run
amplify api gql-compile
to see the new changes in your generated code (optional). - Run
amplify push
to deploy your changes.
Now you can either run amplify api console
or use the new generated code to test the changes with your new mutation.
To generate the new code you can run amplify codegen
. You should then be able to do something like this
import Amplify, { API, graphqlOperation } from "aws-amplify";
import * as mutations from './graphql/mutations';
// Mutation
const addPairToItem = {
id: '1',
number1: 'a',
number2: 'b'
};
const newItem = await API.graphql(graphqlOperation(mutations.addPairToItem, {input: addPairToItem}));
Additional Examples
Remember to update your CustomResources.json file with any new resolvers you add.
Adding a single item to a list of scalar values
### ./amplify/backend/api/<api_name>/schema.graphql
type Item @model {
id: ID!
words: [String]
}
input AddWordInput {
id: ID!
word: String!
}
type Mutation {
addWordToItem(input: AddWordInput!): Item!
}
### ./amplify/backend/api/<api_name>/resolvers/Mutation.addWordToItem.req.vtl
{
"version": "2017-02-28",
"operation": "UpdateItem",
"key": {
"id": { "S": "$ctx.args.input.id"}
},
"update": {
"expression":"SET words = list_append(if_not_exists(words, :emptyList), :newWord)",
"expressionValues":
{
":newWord":{"L": [{"S":"$ctx.args.input.word"}]},
":emptyList":{"L": []}
}
}
}
### ./amplify/backend/api/<api_name>/resolvers/Mutation.addWordToItem.res.vtl
$util.toJson($ctx.result)
### Usage
import Amplify, { API, graphqlOperation } from "aws-amplify";
import * as mutations from './graphql/mutations';
// Mutation
const newWord = {
id: '1',
word: 'foo'
};
const newItem = await API.graphql(graphqlOperation(mutations.addWordToItem, {input: newWord}));
Adding multiple items to a list of scalar values
Note: I am introducing $util.dynamodb.toDynamoDBJson
here to make constructing our VTL easier. I've been explicit thus far but this utility can simplify a lot of the work. More here
### ./amplify/backend/api/<api_name>/schema.graphql
type Item @model {
id: ID!
words: [String]
}
input AddWordsInput {
id: ID!
words: [String!]!
}
type Mutation {
addWordsToItem(input: AddWordsInput!): Item!
}
### ./amplify/backend/api/<api_name>/resolvers/Mutation.addWordsToItem.req.vtl
{
"version": "2017-02-28",
"operation": "UpdateItem",
"key": {
"id": { "S": "$ctx.args.input.id"}
},
"update": {
"expression":"SET words = list_append(if_not_exists(words, :emptyList), :newWords)",
"expressionValues":
{
":newWords": $util.dynamodb.toDynamoDBJson($ctx.args.input.words),
":emptyList": $util.dynamodb.toDynamoDBJson([])
}
}
}
### ./amplify/backend/api/<api_name>/resolvers/Mutation.addWordsToItem.res.vtl
$util.toJson($ctx.result)
### Usage
import Amplify, { API, graphqlOperation } from "aws-amplify";
import * as mutations from './graphql/mutations';
// Mutation
const newWords = {
id: '1',
words: ["bar","xyz","bar"]
};
const newItem = await API.graphql(graphqlOperation(mutations.addWordsToItem, {input: newWords}));
Remove an item from a list of scalar values
Removing elements from lists in DynamoDB is done using the REMOVE action. You must specify a non-negative index as part of the update expression. If the index does not exist on the item, your request will not fail (e.g. no index out of bounds exceptions).
type Item @model {
id: ID!
words: [String]
}
input RemoveWordInput {
id: ID!
wordIndex: Int!
}
type Mutation {
removeWordFromItem(input: RemoveWordInput!): Item!
}
### ./amplify/backend/api/<api_name>/resolvers/Mutation.removeWordFromItem.req.vtl
{
"version": "2017-02-28",
"operation": "UpdateItem",
"key": {
"id": { "S": "$ctx.args.input.id"}
},
"update": {
"expression":"REMOVE words[$ctx.args.input.wordIndex]"
}
}
### ./amplify/backend/api/<api_name>/resolvers/Mutation.removeWordFromItem.res.vtl
$util.toJson($ctx.result)
### Usage
import Amplify, { API, graphqlOperation } from "aws-amplify";
import * as mutations from './graphql/mutations';
// Mutation
const removeWord = {
id: '1',
// The index is 0 based so wordIndex: 0
// would delete the first item,
// wordIndex: 1 deletes the second, etc.
wordIndex: 1
};
const newItem = await API.graphql(graphqlOperation(mutations.removeWordFromItem, {input: removeWord}));

- 656
- 6
- 6
-
@NathanQuinn How do we delete? And also how do we delete a single item from a list? list_append only concatenates two lists but there is no documetation on how to remove an item from a list. – Babu Jul 29 '19 at 13:10
-
@chai86 Do you mean just a list of scalar values? (e.g. ["a", "b", "c]) – Nathan Quinn Aug 03 '19 at 03:01
-
@Babu When you say delete, do you mean remove an attribute entirely from an item? I understand what you mean when you ask about deleting an item from a list, but want to understand your first use case. I will post some additional examples of using other DynamoDB functions. – Nathan Quinn Aug 03 '19 at 03:07
-
1@chai86 I added an example of adding single scalar values and multiple scalar values to a list. This answer is getting pretty long now. I will make a GitHub repo containing more. – Nathan Quinn Aug 03 '19 at 06:55
-
@NathanQuinn consider the dynamodb field type is "List" I need to remove an item from it.Right now list_append technically concatenates two lists? But I just need to implement the functionality to append and remove a single scalar type. Pls share the github repo. Much appreciated and Thanks!! – Babu Aug 03 '19 at 07:57
-
@Babu I added an example of deleting an item here. I will update with the GitHub repo when I wrap up some more examples. – Nathan Quinn Aug 03 '19 at 16:48
-
@NathanQuinn I'm soooo close to finishing the app i'm working on (and Amplify has been really useful). However i'm stuck on this last part to REMOVE a row, could you please urgently help!!!! I've updated the original post with all the information. Thanks :) – chai86 Dec 02 '19 at 13:51
-
@NathanQuinn A github repo with examples is definitely MUCH appreciated, if you have time, adding "an object" to a list is also something I need right now, for example a type Message with ID, author and content, and a type Collection with [Message] – Purefan Dec 12 '19 at 11:16
-
4Absolutely fantastic answer, very helpful. Wish I could've upvoted more! – tedsmitt Feb 06 '20 at 18:48
-
-