Skip to content

Instantly share code, notes, and snippets.

@wliao008
Created January 15, 2018 03:27
Show Gist options
  • Save wliao008/e0dba6a3cf089d46932d39b90f9d838f to your computer and use it in GitHub Desktop.
Save wliao008/e0dba6a3cf089d46932d39b90f9d838f to your computer and use it in GitHub Desktop.
How to add item to a dynamodb list with golang
/*
Took me a while to figure this out, this should never be so difficult IMHO. The dynamodb api could use more examples in its doc.
The documentation for doing this is scattered in a few places:
1. dynamodb api doc for golang: https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/
2. the Update Expression: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html
The structs belowed are abbreviated for the sake of the demo: adding a string to the questions slice in the dynamodb table.
Note you will HAVE to use if_not_exists if using list_append(), and you can only use it with SET, otherwise it would return this error:
"the document path provided in the update expression is invalid for update",
apparently it won't work if the attribute is empty or null initally.
*/
type Test struct {
Id int `json:"id"`
Name string `json:"name"`
Questions []string `dynamodbav:"questions,omitempty"`
}
func (dq *DynamodbQuestion) Add2Test(testId string) bool {
sess, err := session.NewSession(&aws.Config{Region: aws.String(config.AWS_REGION), Endpoint: aws.String(config.AWS_DYNAMODB_ENDPOINT)})
svc := dynamodb.New(sess)
if err != nil {
fmt.Println(err)
return false
}
av := &dynamodb.AttributeValue{
S: aws.String(dq.Id),
}
var qids []*dynamodb.AttributeValue
qids = append(qids, av)
input := &dynamodb.UpdateItemInput{
Key: map[string]*dynamodb.AttributeValue{
"id": {
N: aws.String(testId),
},
"uid": {
S: aws.String(dq.UserId),
},
},
ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
":qid": {
L: qids,
},
":empty_list": {
L: []*dynamodb.AttributeValue{},
},
},
ReturnValues: aws.String("ALL_NEW"),
UpdateExpression: aws.String("SET questions = list_append(if_not_exists(questions, :empty_list), :qid)"),
TableName: aws.String("tests"),
}
@Shuo-Li
Copy link

Shuo-Li commented Mar 15, 2022

@jonny-rimek Thanks a lot for writing this up. I've been scratching my head on the exact issue you described. I tried your solution and found out it works quite well with ADD and SET, but it doesn't work with REMOVE. When I tried using REMOVE as below:

UpdateExpression: aws.String("REMOVE #ri :vals")

I got this error message: "operation error DynamoDB: UpdateItem, https response error StatusCode: 400, RequestID: AKGB0BQ349M5BNFL3U96IC677NVV4KQNSO5AEMVJF66Q9ASUAAJG, api error ValidationException: Invalid UpdateExpression: Syntax error; token: ":vals", near: "#ri :vals""

Have you tried using REMOVE on a set or list before? If so, did it work?

I'm also going to create an issue on github go sdk v2. If I hear anything back from aws team, I'll let you know here.

Thanks again for writing this up!

@Shuo-Li
Copy link

Shuo-Li commented Mar 15, 2022

@jonny-rimek I read on The Dynamobook of Alexis DeBrie that one should use REMOVE to remove elements from a set. I just figured out that the keyword "DELETE" should have been used instead of "REMOVE"

@jonny-rimek
Copy link

@Shuo-Li glad I could help, and you solved your problem. REMOVE is for LISTS, which can contain both numbers and strings, DELETE is for SETS, which only contain either numbers or strings (and binary sets too afaik)

Unfortunately, the docs aren't super clear on that https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.DELETE

@wliao008
Copy link
Author

@Shuo-Li lol completely unrelated but i used to work with Alex DeBrie at Hudl, great dude, what a pleasant surprise, thanks for the trip down memory lane..

@Shuo-Li
Copy link

Shuo-Li commented Mar 15, 2022

@wliao008 I've learnt a great deal from Alex's book, which is probably THE best book about the single-table design with dynamodb database

@Shuo-Li
Copy link

Shuo-Li commented Mar 15, 2022

@jonny-rimek The document link you posted was the one that helped me figure out DELETE should have been used. Wish I could have read it earlier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment