Skip to content

Instantly share code, notes, and snippets.

@andream16
Last active November 25, 2022 08:52
Show Gist options
  • Save andream16/49d198486aebc403269805a9544d6f7b to your computer and use it in GitHub Desktop.
Save andream16/49d198486aebc403269805a9544d6f7b to your computer and use it in GitHub Desktop.
Build ExpressionAttributeValues and UpdateExpression from map[string]interface{} - AWS Go SDK, DynamoDB
package main
import (
"github.com/fatih/structs"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/dynamodb"
"strings"
"fmt"
)
type TestStruct struct {
Name string
NestedStuff NestedStuff
SuperNestedStuff SuperNestedStuff
}
type NestedStuff struct {
Something string
}
type SuperNestedStuff struct {
SomethingNested NestedStuff
}
// Useful for https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/dynamo-example-update-table-item.html
// input := &dynamodb.UpdateItemInput{
// ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
// ":r": {
// N: aws.String("0.5"),
// },
// },
// TableName: aws.String("Movies"),
// Key: map[string]*dynamodb.AttributeValue{
// "year": {
// N: aws.String("2015"),
// },
// "title": {
// S: aws.String("The Big New Movie"),
// },
// },
// ReturnValues: aws.String("UPDATED_NEW"),
// UpdateExpression: aws.String("set info.rating = :r"),
//}
func main() {
// Just a test nested Struct
test := TestStruct{
Name : "hello",
NestedStuff : NestedStuff{
Something: "something1",
},
SuperNestedStuff : SuperNestedStuff{
SomethingNested : NestedStuff{
Something: "something2",
},
},
}
// Get map[string]interface{} from struct
m := structs.Map(test)
// Get ExpressionAttributeValues from a map[string]interface{}.
// Second parameter is parent's name that is used recursively. The first time it's an empty string.
exprAttrValues := BuildExpressionAttributeValues(m, "")
fmt.Println(fmt.Sprintf("ExpressionAttributeValues %v", exprAttrValues))
// ExpressionAttributeValues map[:name:{
// S: "hello"
//} :nestedstuff:{
// M: {
// :nestedstuffsomething: {
// S: "something1"
// }
// }
//} :supernestedstuff:{
// M: {
// :supernestedstuffsomethingnested: {
// M: {
// :supernestedstuffsomethingnestedsomething: {
// S: "something2"
// }
// }
// }
// }
//}]
// Get UpdateExpression from a map[string]interface{}.
// Second and Third parameters are parent's name that are used recursively. The first time they are both empty strings.
updateExpr := BuildUpdateExpression(m, "", "")
fmt.Println(fmt.Sprintf("UpdateExpression %v", updateExpr))
// UpdateExpression Name = :name, NestedStuff.Something = :nestedstuffsomething, SuperNestedStuff.SomethingNested.Something = :supernestedstuffsomethingnestedsomething
}
func BuildExpressionAttributeValues(input map[string]interface{}, parentName string) map[string]*dynamodb.AttributeValue {
// Map to be returned
m := make(map[string]*dynamodb.AttributeValue)
for k, v := range input {
keyName := strings.Join([]string{":", parentName, strings.ToLower(k)}, "")
// Add All the cases you need.
switch t := v.(type) {
case map[string]interface{}:
nextName := strings.TrimPrefix(keyName, ":")
m[keyName] = &dynamodb.AttributeValue{
M : BuildExpressionAttributeValues(t, nextName),
}
case string:
m[keyName] = &dynamodb.AttributeValue{
S : aws.String(t),
}
case bool:
m[keyName] = &dynamodb.AttributeValue{
BOOL : aws.Bool(t),
}
}
}
return m
}
func BuildUpdateExpression(input map[string]interface{}, parentName, exprParentName string) string {
var s []string
for k, v := range input {
keyName := strings.Join([]string{":", exprParentName, strings.ToLower(k)}, "")
// Add All the cases you need.
switch t := v.(type) {
case string, bool:
currAttrName := k
if len(parentName) > 0 {
currAttrName = strings.Join([]string{parentName, currAttrName}, ".")
}
s = append(s, strings.Join([]string{currAttrName, "=", keyName}, " "))
case map[string]interface{}:
nextExprParentName := strings.TrimPrefix(keyName, ":")
nextParentName := k
if len(parentName) > 0 {
nextParentName = strings.Join([]string{parentName, k}, ".")
}
s = append(s, BuildUpdateExpression(t, nextParentName, nextExprParentName))
}
}
return strings.Join(s, ", ")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment