33
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DynamoDBのQueryについてまとめてみました。

33
Last updated at Posted at 2020-09-02

概要

DynamoDBを初めて触るにあたり、DynamoDBの特徴や設計思想をまとめたサイトはたくさんあったのですが、
クエリ(以下、「Query」)についてまとめたサイトが見当たらなかったため、備忘録としてまとめてみました。

読者対象

・DynamoDBを初めて触るにあたり、あらかじめの概要は調査して理解できたが、具体的に操作するにはどうすれば良いか不明確な方
・RDBについての前提知識がある方(基本的なクエリの書き方や用語について知識がある方)

参考サイト

・AWS 公式ドキュメント
https://docs.aws.amazon.com/dynamodb/index.html

・gitにサンプルコードを公開しています
https://github.com/ryohei0109-develop/Amazon.DynamoDb.Sample

用語について

●検索方法について

・Query

後述する「パーティションキー」を条件(WHERE句)として検索する方法です。

・Scan

テーブル全体を読み取り、その結果にフィルターを適用して絞り込む検索方法です。
「パーティションキー」を条件にしないため、テーブル全件を読み取るコストが発生し、検索速度はQueryに比べると遅いです。
データ量が多いテーブルでは特にコストが高くなるため、可能な限りQueryで検索できるようにテーブル設計をすることが重要です。

●プライマリキーについて

プライマリキーは、QueryでWHERE句に条件として指定できます。
プライマリキー以外をWHERE句として条件にしたい場合は、Scanで検索するか、Filter Expressionを使用する必要があります。

・Hash attribute

主キー、PK
「パーティションキー」とも呼ばれます。

・Range attribute

主キーと合わせて複合主キーとして設定可能。
「ソートキー」とも呼ばれます。

・Secondary Indexes

プライマリキーに対するクエリに加えて、代替キーを使用して、テーブル内のデータのクエリを実行可能。
QueryもしくはScanで検索可能。
以下2つの種類が存在する。

-> Global Secondary Index (GSI)
パーティションキー・ソートキーともに、元のテーブルとは別の属性を指定して作成できるインデックス。テーブル作成後にも追加可能。

-> Local Secondary Index (LSI)
パーティションキーは元のテーブルと同じで、ソートキーだけを別の属性に変えたインデックス。テーブル作成時にのみ設定可能。

型対応表

JavaScript DynamoDB
string S
number N
boolean BOOL
null NULL
array L
object M

Queryの表記方法

SQL同様、テーブルを検索するQueryには様々な項目が設定できます。
(例) 「SELECT」、「WHERE」、「AS」等

また、各項目に設定する値は大文字・小文字が区別されるためご注意下さい。

●Expression Attribute Names

SQLでいう「AS」にあたる部分です。
NoSQLでは予約語をエスケープしてそのまま使うことができないため、別の名称に置き換える必要があります。
置き換え後の名称の先頭は必ず「#」で始まる必要があります。

// 例
// 「Name」属性名を「#n」という名称に置き換えて予約語重複の対策をします。
{
    { "#n", "Name" }
}

●Projection Expression

SQLでいう「SELECT」にあたる部分です。
取得属性名を配列で指定します。
Expression Attribute Names(AS句)で別名に置き換えている場合は、置き換え後の名称で指定します。

// 例
{
    [ "Id", "#Name", "Price" ]
}

●Key Condition Expression

SQLでいう「WHERE」句になります。(その1)
後述する「Expression Attribute Values」で設定した条件をプライマリキーに割り当てます。
指定できる種類は以下の通りです。
・a = b
 true if the attribute a is equal to the value b
・a < b
 true if a is less than b
・a <= b
 true if a is less than or equal to b
・a > b
 true if a is greater than b
・a >= b
 true if a is greater than or equal to b
・a BETWEEN b AND c
 true if a is greater than or equal to b, and less than or equal to c.
・begins_with (a, substr)
 true if the value of attribute a begins with a particular substring.

// 例
// 「Expression Attribute Values」で設定した「:name」という条件を「ForumName」属性に適用します。
"ForumName = :name"

●Expression Attribute Values

SQLでいう「WHERE」句になります。(その2)
式の属性値はコロン (:) で始まり、1 つ以上の英数字が続きます。
作成した「Expression Attribute Values」は、前述の「Key Condition Expression」や「Filter Expression」で呼び出して使用します。

// 例
// 「:name」という名前で、String型文字列「Amazon DynamoDB」を条件として設定します。
{":name":{"S":"Amazon DynamoDB"}}

●Filter Expressions for Query

SQLでいう「WHERE」句になります。(その3)
QueryのWHERE句には通常「パーティションキー」しか使用できませんが、
「パーティションキー」以外の属性で条件を追加したい時にFilterを使います。
※逆にFilterには「パーティションキー」を指定できません。

1回のQueryで、最大1MBまでのデータを取得可能ですが、この制限は、Filterを評価する前に適用されます。
なので、DynamoDBのテーブル設計時は、「パーティションキー」で検索結果数を絞り込めるようにした方が良さそうです。

Query例

参考サイト: https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Query.html

注意: 以下のCLI例ではインデントに全角スペースを使用しています。実際に実行する際は半角スペースに置き換えてください。

// 例1
// ThreadテーブルからForumNameが"Amazon DynamoDB"のレコードを取得します。
// 「expression-attribute-values」で「:name」という名前で検索条件を設定し、それを「key-condition-expression」で呼び出して使用しています。
// ※key-condition-expressionにはプライマリキー(パーティションキー+ソートキー)しか指定できないためご注意下さい。
// SQL: SELECT * FROM Thread WHERE ForumName = 'Amazon DynamoDB';

aws dynamodb query \
 --table-name Thread \
 --key-condition-expression "ForumName = :name" \
 --expression-attribute-values  '{":name":{"S":"Amazon DynamoDB"}}'
// 例2
// ThreadテーブルからForumNameが"Amazon DynamoDB"及びSubjectが"DynamoDB Thread 1"のレコードを取得します。
// 「expression-attribute-values」で「:name」、「:sub」という名前で検索条件を設定し、それを「key-condition-expression」で呼び出して使用しています。
// ※key-condition-expressionにはプライマリキー(パーティションキー+ソートキー)しか指定できないためご注意下さい。
// SQL: SELECT * FROM Thread WHERE ForumName = 'Amazon DynamoDB' AND Subject = 'DynamoDB Thread 1';

aws dynamodb query \
 --table-name Thread \
 --key-condition-expression "ForumName = :name and Subject = :sub" \
 --expression-attribute-values  '{
  ":name":{"S":"Amazon DynamoDB"},
  ":sub":{"S":"DynamoDB Thread 1"}
 }'
// 例3
// ReplyテーブルからIdが"Amazon DynamoDB#DynamoDB Thread 1"かつReplyDateTimeが"2015-09"で始まるレコードを取得します。
// SQL: SELECT * FROM Reply WHERE Id = 'Amazon DynamoDB#DynamoDB Thread 1' AND ReplyDateTime LIKE '2015-09%';

aws dynamodb query \
 --table-name Reply \
 --key-condition-expression "Id = :id and begins_with(ReplyDateTime, :dt)" \
 --expression-attribute-values  '{
  ":id":{"S":"Amazon DynamoDB#DynamoDB Thread 1"},
  ":dt":{"S":"2015-09"}
 }'
// 例4 (Filter)
// Threadテーブルから以下の3つの条件で絞り込んで取得します。
// 条件1: ForumName = 'Amazon DynamoDB'
// 条件2: Subject = 'DynamoDB Thread 1'
//   上記2属性はプライマリキーなので「key-condition-expression」で指定します。
// 条件3: Views >= 3
//   フィルター条件として「filter-expression」で指定しています。
//   「Views」は予約語なので「#v」に置き換えています。

aws dynamodb query \
 --table-name Thread \
 --key-condition-expression "ForumName = :fn and Subject = :sub" \
 --filter-expression "#v >= :num" \
 --expression-attribute-names '{"#v": "Views"}' \
 --expression-attribute-values '{
  ":fn":{"S":"Amazon DynamoDB"},
  ":sub":{"S":"DynamoDB Thread 1"},
  ":num":{"N":"3"}
 }'

Queryの注意点

・Query の結果は常にソートキーの値によってソートされます。
ソートキーのデータ型が Number である場合は、結果が番号順で返されます。
その他の場合は、UTF-8 バイトの順序で結果が返されます。
デフォルトの並べ替え順序は昇順です。
順序を反転させるには、ScanIndexForward パラメータを false に設定します。

・1回のQueryオペレーションで、最大 1 MB のデータを取得できます。
この制限は、結果へのFilterExpressionの適用前に適用されます。
レスポンスにLastEvaluatedKeyが存在し、Null以外の場合、結果セットをページ分割する必要があります。
(参照: Paginating Table Query Results

・パーティションキーのみ(ソートキーなし)のテーブルでもQueryは実行可能ですが、
パーティションキーは完全一致が必須のため、検索結果が必ず1件になります。
その場合は GetItem を使用する方が適切です。

AUTO INCREMENTについて

MySQL等のRDBにはAUTO INCREMENT機能があり、自動的にユニークな値を採番してPKとして使用できる機能がありますが、
DynamoDBにはデフォルトの機能としては存在しないため、同様の機能を使用したい場合は自前で実装する必要があります。

補足:アトミックカウンターについて

DynamoDBには「アトミックカウンター」という機能があります。
これは UpdateExpressionADD を使って数値属性を安全にインクリメント/デクリメントする機能で、
ページビュー数やいいね数のようなカウンターの実装に適しています。
AUTO INCREMENTとは用途が異なりますので、混同しないようご注意ください。

(参照: AWS公式ドキュメント - アトミックカウンター

33
17
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
33
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?