Table of Contents
AWSのDynamoDBの項目からqueryを使ってデータを取得するときに苦労した話
query のoption設定で必ず必要になるKeyConditionExpressionについて
queryのKeyConditionExpressionに必ず必要になるパーティションキー(PK)を参照した条件、演算子には”=” しか使うことはできない。
なので、queryで詳細な取得の条件を作るときは工夫が必要になってくる。
一番手っ取り早いのは、
- 値が全て必ず1になる項目をパーティションキーにする
- ソートキーを被りのない値が入る項目にする
- ソートキーで絞り込みの条件を作る
PK(数値) (パーティションキー) | update-date (ソートキー) | article-id | body |
1 | 1692592888 | article-0000000000 | textBox20000000000 |
1 | 1692592948 | article-0000000001 | textBox20000000001 |
1 | 1692593008 | article-0000000002 | textBox20000000002 |
1 | 1692593068 | article-0000000003 | textBox20000000003 |
… | …. | …… | … |
図:パーティションキーを使って絞り込みをできるようにしたDynamoDBのテーブルのイメージ
このテーブルでは、ソートキーには特定の時間をエポック秒に変換したものを登録させて、ある時間より前、後などの条件を用いて複数の項目を取得できるようにしている。
パーティションキーは登録時に必ず1が登録されるようにLambdaを組んだ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
options = { 'TableName':tblName, 'Limit':10, # 取得するデータ件数 'ScanIndexForward':False, 'KeyConditionExpression':'#aId = :valueHeader AND #updateDE < :valueEpochSec', 'ExpressionAttributeNames':{ '#aId': 'PK', '#updateDE': 'update-date-epoch-second' }, #文字列 'article'と リクエストのurlからもらうエポック秒updateDate用の2つの:XXXX を作る 'ExpressionAttributeValues':{ ':valueHeader': {'N': '1'}, ':valueEpochSec': {'N': str(lastEvaluatedEpochSecond)} }, } response = dynamodbCli.query(**options)response = dynamodbCli.query(**options) |
パーティションキーを用いて絞り込みをするqueryのoptionの例
ExpressionAttributeValuesで宣言する値には変数を使うこともできる。
1 |
'KeyConditionExpression':'#aId = :valueHeader AND #updateDE < :valueEpochSec' |
の部分のパーティションキーを参照した条件を
1 |
'KeyConditionExpression':'#aId > :valueHeader AND #updateDE < :valueEpochSec' |
のような = 以外の演算子を用いたものにすると、CloudWatchでエラーが発生した。
AWSでqueryを絞り込みに使うのは本来は向いておらず、scanを使うのが望ましいらしい。ただ、scanを使うときは取り扱うデータ量が多く、処理に時間がかかりやすいことを考慮する必要があるため、スピードを重視する際は今回のような条件式を用いたqueryを使う必要がある。
参考文献
- PartitionKeyの絞り込みに = 以外は使えない これは確定
- https://qiita.com/eyuta/items/ab45c47e7851931cab2a
しかし、
aws dynamodb query
でパーティションキーを用いた絞り込みを行う場合、上記のページにあるように完全一致(=
)しか使用することができません。そのため、パーティションキーを部分一致で絞り込んだ上で項目を出力したい場合は、代わりに
[aws dynamodb scan](<https://docs.aws.amazon.com/cli/latest/reference/dynamodb/scan.html>)
を使用する必要があります。 - https://stackoverflow.com/questions/74223516/error-query-key-condition-not-supported-while-performing-a-query-with-secondar
You cannot do a range query on a partition key, only on the sort key. Depending on the throughput your table has you can define a single PK for your index, lets say for example the Number
1
.GSI
- https://qiita.com/eyuta/items/ab45c47e7851931cab2a