#概要
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でWHERE句に条件として指定できます。
プライマリキー以外をWHERE句として条件にしたい場合は、Scanで検索する必要があります。
####・Hash attribute
主キー、PK
「パーティションキー」とも呼ばれます。
####・Range attribute
主キーと合わせて複合主キーとして設定可能。
「ソートキー」とも呼ばれます。
####・Secondary Indexes
プライマリキーに対するクエリに加えて、代替キーを使用して、テーブル内のデータのクエリを実行可能。
QueryもしくはScanで検索可能。
以下2つの種類が存在する。
->Global Secondary Index
->Local Secondary Index
#型対応表
JavaScrfipt | DynamoDB |
---|---|
string | S |
number | N |
boolean | N |
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」で呼び出して使用します。
// 例
// 「: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
// 例1
// ThreadテーブルからForumNameが"Amazon DynamoDB"のレコードを取得します。
// 「expression-attribute-values」で「:name」という名前で検索条件を設定し、それを「key-condition-expression」で呼び出して使用しています。
// ※expression-attribute-valuesにはパーティションキーしか指定できないためご注意下さい。
// SQL: `SELECT * FROM `Thread` WHERE `Name` = '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」で呼び出して使用しています。
// ※expression-attribute-valuesにはパーティションキーしか指定できないためご注意下さい。
// SQL: `SELECT * FROM `Thread` WHERE `Name` = '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以外の場合、結果セットをページ分割する必要があります (AWS参照: Paginating Table Query Resultsを参照)。
・Queryは複合PKを設定しているテーブルにしか使用できません。
※パーティションキーの指定は必須のため、複合PK構造でないと必ず検索結果が1件になるため、
その場合はItemGet()メソッドを使用して下さい、ということのようです。
#アトミックカウンター
MySQL等のRDBにはAUTO INCREMENT機能があり、自動的にユニークな値を採番してPKとして使用できる機能がありますが、
DynamoDBにはデフォルトの機能としては存在しないため、同様の使用したい場合は自前で実装する必要があります。
(参照: AWS公式ドキュメント https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.AtomicCounters)