17
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Person Link newAdvent Calendar 2020

Day 20

dynamodbで配列の取り扱いについて

Last updated at Posted at 2020-12-19

今回は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関数が使える。
でも更新するのは難しい!!
「こうしたらできるよ!」とかあったらコメントいただけたら嬉しいです。

17
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?