sdk-goでdynamoDBの複雑なstructの値をupdateする


やりたいこと

GoでのdynamoDBに対しての操作は割とめんどかったりします。単純なStringやIntのものであればまだ良いのですが、ListのMapのなかのListとか、値の構造が複雑になってくると気が滅入ります。

// シンプルなパターン
&dynamodb.UpdateItemInput{
  TableName: aws.String("sampleTable"),
  Key: // 省略,
  ExpressionAttributeValues: map[string]*dynamodb.Attribute{
   ":ssv": {
      S: aws.String("sampleStringValue")
    },
   ":siv": {
      N: aws.String(strconv.Itoa(0)) // ここもintをstringに型変換してそれをaws.String()してkeyにはNを指定って感じでわかりづらい。
    },
  },
  UpdateExpression: aws.String("set sampleStringValue=:ssv and sampleIntValue=:siv")
}

// 複雑なパターン
&dynamodb.UpdateItemInput{
  TableName: aws.String("sampleTable"),
  Key: //省略,
  ExpressionAttributeValues: map[string]*dynamodb.Attribute{
    ":slv": {
      L: [
       {
         M: {
           ":smp": {
            aws.String("sample")
            }....
         }
       }
      ]
    },
  }
}

これを楽にやれるのがsdk-goのexpressionってやつです。

expressionの使い方

update := expression.UpdateBuilder{}.Set(
  expression.Name("sampleComplexValue"),
  expression.Value(sampleCompexValue)
)

expr, err := expression.NewBuilder().WithUpdate(update).Build()

&dynamodb.UpdateItemInput{
  TableName: aws.String("sampleTable"),
  Key: //省略,
  ExpressionAttributeNames: expr.Names(),
  ExpressionAttributeValues: expr.Values(),
  UpdateExpression: expr.Update()
}

上の例よりかなりスマートにかけますね。可読性も格段に上がります。
expression.Valuesの引数に複雑な(もちろん単純なものでもなんの問題もありませんが)値を渡すだけで、ここまでできるのは結構ありがたい。

もちろんexpressionは上記の例のような更新処理だけでなく、Query処理等にも使えるので積極的に使っていきたいところですね。