LoginSignup
22
12

More than 3 years have passed since last update.

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

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で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 * FROMThreadWHEREName` = '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)

22
12
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
22
12