今回はdynamodbのデータの操作方法でとても詰まったのでそれを記事にしたいと思います。
dynamodbの個人的なメリット
- 実は無期限の無料利用枠。25GBのストレージ量であれば常に無料で利用可能
- 普段Vueを書いているのでjavascriptの記述で書けるのは魅力的(lambdaのランタイムにNode.jsを選択)
dynamodbはテーブルの正規化ができないので、なるべく少ないテーブル数で構築するのが好ましいらしい。
まず簡易掲示板を作ると仮定する
期待するテーブル: PostsテーブルとCommentsテーブル
- Postsテーブルのスキーマ
id: number
name: string
text: string
- Commentsテーブルのスキーマ
id: string
post_id: string
name: string
comment: string
サンプルデータをdynamodbで表現すると
{
"id": "1",
"name": "テスト1",
"text": "初めての投稿",
"comments": [
{
"id": "1",
"name": "テスト2",
"comment": "コメント1"
},
{
"id": "2",
"name": "テスト3",
"comment": "コメント2"
}
]
}
comments配列に要素を追加するには
set文にlist_append関数を用いると実現可能。
以下のようなparamsをdocumentClientのupdateメソッドの引数に渡してあげるだけ
const AWS = require('aws-sdk');
const documentClient = new AWS.DynamoDB.DocumentClient();
const newComment = {
id: "3",
name: "テスト4",
comment: "コメント3"
};
const params = {
TableName: "tableName",
Key: {
id: "1"
},
UpdateExpression: `SET #key = list_append(#key, :value)`,
ExpressionAttributeNames: {
'#key': "comments",
},
ExpressionAttributeValues: {
':value': [newComment]
},
};
await documentClient
.update(params)
.promise();
解説
dynamodbではsql文のようなものをUpdateExpressionに書くことができる。
SET #key = list_append(#key, :value)
list_append関数はデータの追加というより配列の結合である。comments配列と[newComment]配列を連結するイメージ。
#key
はプレースホルダーでExpressionAttributeNamesに割り当てたい名前を与えてあげる。
dynamodbには予約語が多いが、プレースホルダーを使うと回避できる。
[dynamodbの予約語リスト]
(https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/ReservedWords.html)
:value
もプレースホルダーでExpressionAttributeValuesで割り当てたい変数を代入する
では先ほど追加したオブジェクトのcommentを'hogehoge'に更新しよう
const updateComment = {
id: "3",
name: "テスト4",
comment: "hogehoge"
};
const params = {
TableName: "tableName",
Key: {
id: "1"
},
UpdateExpression: `set #key[?]= :value`, // インデックスがわからない。。
ExpressionAttributeNames: {
'#key': "comments"
},
ExpressionAttributeValues: {
':value': updateComment
},
};
自分はここでどハマりました。
comments配列のインデックスがわからないとコメントの更新ができない
#key
配列をループで回すことができれば代入できそうだが、、
解決策
思い切ってデータ構造を変える。comments配列からオブジェクトに変換し、idを外に出す
{
"id": "1",
"name": "テスト1",
"text": "初めての投稿",
"comments": {
"1": {
"name": "テスト2",
"comment": "コメント1"
},
"2": {
"name": "テスト3",
"comment": "コメント2"
}
}
}
こうすると
const updateComment = {
id: "3",
name: "テスト4",
comment: "hogehoge"
};
const params = {
TableName: "tableName",
Key: {
id: "1"
},
UpdateExpression: `set #key.#id = :value`,
ExpressionAttributeNames: {
'#key': "comments",
'#id': updateComment.id
},
ExpressionAttributeValues: {
':value': updateComment
},
};
こうすることで配列のインデックスに悩まされることから解放されました。
まとめ
dynamodbでは配列の末尾に要素を追加するならlist_apend関数が使える。
でも更新するのは難しい!!
「こうしたらできるよ!」とかあったらコメントいただけたら嬉しいです。