パーティションキーとソートキーで注文をクエリする

AWSBeginner
オンラインで実践に進む

はじめに

注文サポートツールには、選択した月の正しい顧客の注文を表示する必要があります。1 件のアイテムだけを検索したり、フィルター適用後の空ページで処理を止めたりすると、有効なレコードを見落とすことがあります。このラボでは、複合キーを持つテーブルを作成し、Ada の 10 月の注文をクエリします。さらに、提供されたアプリケーションを設定し、継続キーをたどって梱包済み注文を表示します。

最初に「注文用の DynamoDB テーブルを作成する」を完了し、型付きアイテムと更新を学んでください。この単元は、新しい使い捨ての接続、架空のデータファイル、通常のアプリケーションを使って独立して開始します。/home/labex/project、公式 AWS CLI、AWS View を使用します。以前の VM のリソースは再利用しません。

認定試験との関連

このラボでは、次の試験トピックに関連する実践的な演習を行います。

アクセスパターンに合わせてキーを設計する

このステップでは、顧客と日付で検索する注文を準備します。複合プライマリキーは、パーティションキーとソートキーで構成されます。パーティションキーは顧客の注文をまとめ、ソートキーはそのグループ内の各注文を識別してクエリ結果の順序を決めます。2 つの値の組み合わせで 1 件のアイテムを識別します。

日付には固定幅の YYYY-MM-DD 文字列を使い、その後に # と注文 ID を続けます。文字列のソートキーは UTF-8 のバイトを比較するため、この形式では日付が時系列順に並びます。これは小規模な注文モデルであり、あらゆる用途に使える単一テーブル設計ではありません。

cd /home/labex/project
aws sts get-caller-identity
aws dynamodb create-table --table-name labex-d02-orders --attribute-definitions AttributeName=customer_id,AttributeType=S AttributeName=order_key,AttributeType=S --key-schema AttributeName=customer_id,KeyType=HASH AttributeName=order_key,KeyType=RANGE --billing-mode PAY_PER_REQUEST
aws dynamodb wait table-exists --table-name labex-d02-orders

準備済みの orders.json には、認証情報ではなく 5 件の架空の注文が入っています。cat で通常の API リクエストを表示し、読み込む前に各顧客、日付、状態を確認できます。

cat orders.json
aws dynamodb batch-write-item --cli-input-json file://orders.json

BatchWriteItem は、これらの異なるキーを持つアイテムを読み込みます。UnprocessedItems が {} であることを確認してください。AWS では未処理のバッチを再試行する必要があり、レスポンスが返っただけではすべての書き込みの完了は保証されません。サンプルには Ada の 9 月、10 月、11 月の注文と Bob の 10 月の注文が含まれています。そのため、成功する 1 つのケースだけでなく、検索範囲の境界をテストできます。

1 人の顧客と日付範囲をクエリする

このステップでは、キー条件を使って Ada の 10 月の注文を選択します。Query には 1 つのパーティションキーに対する等価条件が必要で、ソートキーの範囲も絞り込めます。Scan は、最初にキーのパーティションを選択するのではなく、テーブルを調べます。次のステップでフィルターを追加します。まずはキーを使って顧客と日付範囲を選びましょう。

顧客キーで Ada のパーティションを選択し、日付範囲でその中の 10 月の注文を選択します。

顧客キーで Ada のパーティションを選択し、日付範囲でその中の 10 月の注文を選択します。

まず、5 件すべてのレコードを確認し、スキャンの対象範囲を理解します。

aws dynamodb scan --table-name labex-d02-orders --consistent-read --query 'Items'

提供された注文検索アプリケーションは、lookup.json を読み取り、DynamoDB Query API を呼び出します。実行ファイルは order-lookup です。確認用にソースコードも提供されていますが、Python を書く必要はありません。通常の Query リクエストのフィールドを設定し、コマンド履歴ではなく実際のアプリケーションの結果を確認します。

BETWEEN は両端の値を含みます。注文キーは、日付の後に # と ID を続けた形式です。開始値の 2026-10-01# は、その日の ID より前に並びます。終了値の 2026-10-31#~ は、ここで使う英字と数字より ~ が後に並ぶため、その日の ID より後に並びます。この境界の指定は、このキー形式に固有のものです。

引用符付きのヒアドキュメントは、JSON をそのまま lookup.json に書き込みます。request には Query のフィールドが入ります。現時点の paginate: false は、アプリケーションに 1 ページだけを要求させます。次のステップで継続処理を有効にします。

cat > lookup.json <<'JSON'
{
  "paginate": false,
  "request": {
    "TableName": "labex-d02-orders",
    "KeyConditionExpression": "customer_id = :customer AND order_key BETWEEN :start AND :end",
    "ExpressionAttributeValues": {
      ":customer": {
        "S": "ada"
      },
      ":start": {
        "S": "2026-10-01#"
      },
      ":end": {
        "S": "2026-10-31#~"
      }
    },
    "ConsistentRead": true
  }
}
JSON

Query の値には、GetItem と同じように型付きの文字列を使います。アプリケーションの設定ファイルには独自の paginate 設定もあるため、同じキーを使う直接の CLI リクエストと比較します。

aws dynamodb query --table-name labex-d02-orders --key-condition-expression 'customer_id = :customer AND order_key BETWEEN :start AND :end' --expression-attribute-values '{":customer":{"S":"ada"},":start":{"S":"2026-10-01#"},":end":{"S":"2026-10-31#~"}}' --consistent-read
./order-lookup

どちらの結果にも、ソートキーの昇順で Ada の O100 と O101 だけが含まれます。Bob の O200 と、対象月以外の Ada の注文は除外されます。AWS View を開き、保存されたテーブルのアイテムと並んで表示される実際の Order lookup の結果を確認してください。これらの読み取りによってレコードは変更されません。

以下の公式 Console の例は、パーティションキーによる Query を示しています。Artist と songTitle は、ここでの customer_id と order_key と同じキーの役割を持ちます。画面の見方を理解するために参照し、この演習は Terminal と AWS View で続けてください。

パーティションキーによる Query を示す公式 DynamoDB Console の例。

出典:AWS DynamoDB チュートリアル。

フィルター適用後のページが空でもページネーションを続ける

このステップでは、最初の空ページで止まらずに、10 月の梱包済み注文を取得します。DynamoDB は、フィルターを適用する前の評価対象アイテムに Limit を適用します。Query のレスポンスには、Items が空でも LastEvaluatedKey が含まれる場合があります。アプリケーションが次のページを要求するかどうかを判断する手掛かりは、アイテム数ではなく、この継続キーです。フィルターは、すでに実行された読み取りの処理量を減らしません。

準備済みの packed-page.json は同じキーを使い、PACKED 状態のフィルターを追加し、Limit: 1 を設定しています。この小さな上限により、ページの境界を確認できます。--no-paginate は CLI による追加ページの取得を止めるため、サービスの 1 回分のレスポンスを確認できます。

cat packed-page.json
aws dynamodb query --cli-input-json file://packed-page.json --no-paginate

最初に評価される注文は NEW なので、Items: []、Count: 0、ScannedCount: 1、O100 を示す LastEvaluatedKey が返るはずです。これは結果の終わりではありません。

最初の 2 ページ:フィルターにより 1 ページ目は空になりますが、継続キーをたどると梱包済み注文に到達します。

最初の 2 ページ:フィルターにより 1 ページ目は空になりますが、継続キーをたどると梱包済み注文に到達します。

API が継続キーを返さなくなるまで、そのキーをたどるようにアプリケーションを設定します。#state は予約語の status を避けるために使い、:state はフィルターの値を渡します。

cat > lookup.json <<'JSON'
{
  "paginate": true,
  "request": {
    "TableName": "labex-d02-orders",
    "KeyConditionExpression": "customer_id = :customer AND order_key BETWEEN :start AND :end",
    "ExpressionAttributeValues": {
      ":customer": {
        "S": "ada"
      },
      ":start": {
        "S": "2026-10-01#"
      },
      ":end": {
        "S": "2026-10-31#~"
      },
      ":state": {
        "S": "PACKED"
      }
    },
    "ConsistentRead": true,
    "ExpressionAttributeNames": {
      "#state": "status"
    },
    "FilterExpression": "#state = :state",
    "Limit": 1
  }
}
JSON
./order-lookup

アプリケーションは、PACKED 状態の Ada の O101 だけを返し、Count: 1、Evaluated: 2 を表示します。このデータセットでは、Pages: 3 にクエリの終わりを確認する最後の空リクエストが含まれます。継続キーは読み取りの境界を示すものであり、一致するアイテムがさらにあることを保証するものではありません。アプリケーションは、サービスが継続キーを返さなくなるまで ExclusiveStartKey を使って処理を続けます。AWS View では検索結果が変わりますが、保存されたレコードはすべてそのままです。

実際のアプリケーションが継続キーをたどり、10 月の梱包済み注文だけを返します。

リソース一覧を確認し、所有するテーブルを削除する

このステップでは、検索の動作を確かめてから後片付けをします。まず、対象テーブルに元の 5 件のレコードが残っていることを確認します。読み取りと設定の変更によって、注文データが変わっていてはいけません。

aws dynamodb scan --table-name labex-d02-orders --consistent-read --select COUNT

Count: 5 が返るはずです。labex-d02-orders だけを削除し、存在しなくなるまで待ちます。参照テーブルは環境に属するため、残す必要があります。

aws dynamodb delete-table --table-name labex-d02-orders
aws dynamodb wait table-not-exists --table-name labex-d02-orders
aws dynamodb list-tables
aws dynamodb get-item --table-name labex-d02-reference --key '{"id":{"S":"platform"}}' --consistent-read

一覧には labex-d02-reference だけが残り、その note は keep unchanged のままです。AWS View からは、所有していたテーブルと検索結果が消えます。削除を証明するのは、サービスからの正常なレスポンスです。接続できないことは削除の証明になりません。この使い捨ての接続は、VM とともに終了します。

まとめ

注文を顧客ごとにまとめ、日付を使ったソートキーで順序を付けました。Query は目的のパーティションと範囲を選択し、Scan はより広いテーブル全体を調べました。フィルターは評価後に適用され、空ページでも継続処理が必要になる場合があることを確認しました。提供されたアプリケーションは、実際の Query リクエストでページをたどり、梱包済み注文を取得しました。最後に、所有するリソースだけを削除しました。