Amazon DynamoDB 開発者ガイド API Version 2012-08-10 Amazon DynamoDB 開発者ガイド Amazon DynamoDB 開発者ガイド Amazon DynamoDB: 開発者ガイド Copyright © 2017 Amazon Web Services, Inc. and/or its affiliates. All rights reserved. Amazon's trademarks and trade dress may not be used in connection with any product or service that is not Amazon's, in any manner that is likely to cause confusion among customers, or in any manner that disparages or discredits Amazon. All other trademarks not owned by Amazon are the property of their respective owners, who may or may not be affiliated with, connected to, or sponsored by Amazon. Amazon DynamoDB 開発者ガイド Table of Contents Amazon DynamoDB とは ............................................................................................................... 1 仕組み ................................................................................................................................. 2 コアコンポーネント ...................................................................................................... 2 DynamoDB API ............................................................................................................ 9 命名ルールおよびデータ型 ............................................................................................ 11 読み込み整合性 ........................................................................................................... 16 プロビジョニングされたスループット ............................................................................ 16 パーティションとデータ分散 ......................................................................................... 19 SQL から NoSQL へ ........................................................................................................... 23 SQL か NoSQL か ...................................................................................................... 23 データベースにアクセスする ......................................................................................... 25 テーブルの作成 ........................................................................................................... 26 テーブルに関する情報の取得 ......................................................................................... 28 テーブルへのデータの書き込み ..................................................................................... 29 テーブルからデータを読み込む ..................................................................................... 32 インデックス管理 ........................................................................................................ 37 テーブルのデータ変更 .................................................................................................. 40 テーブルからデータを削除する ..................................................................................... 42 テーブルの削除 ........................................................................................................... 43 DynamoDB のセットアップ .......................................................................................................... 44 DynamoDB (ダウンロード可能バージョン) のセットアップ ....................................................... 44 DynamoDB のダウンロードと実行 ................................................................................. 44 ローカルエンドポイントの設定 ..................................................................................... 46 使用に関する注意事項 .................................................................................................. 47 DynamoDB (ウェブサービス) のセットアップ .......................................................................... 48 AWS にサインアップする ............................................................................................. 48 AWS アクセスキー ID およびシークレットアクセスキーの取得 .......................................... 48 DynamoDB へのアクセス ............................................................................................................. 50 コンソールを使用する .......................................................................................................... 50 項目と属性を操作する .................................................................................................. 52 テーブルを監視する ..................................................................................................... 56 CloudWatch アラームを設定する ................................................................................... 57 DynamoDB ストリーム とトリガーの管理 ....................................................................... 57 CLI の使用 ......................................................................................................................... 58 AWS CLI のダウンロードと設定 .................................................................................... 59 DynamoDB での AWS CLI の使用 ................................................................................. 59 ダウンロード可能な DynamoDB での AWS CLI の使用 ..................................................... 60 API の使用 ......................................................................................................................... 61 DynamoDB を使用したプログラミング ........................................................................................... 62 DynamoDB の AWS SDK サポートの概要 ............................................................................... 62 プログラム用インターフェイス ............................................................................................. 64 低レベル インターフェイス .......................................................................................... 64 ドキュメント インターフェイス .................................................................................... 65 オブジェクト永続性インターフェイス ............................................................................ 66 DynamoDB 低レベル API ..................................................................................................... 68 リクエストの形式 ........................................................................................................ 70 レスポンスの形式 ........................................................................................................ 70 データ型記述子 ........................................................................................................... 71 数値データ ................................................................................................................. 72 バイナリデータ ........................................................................................................... 72 エラー処理 ......................................................................................................................... 72 エラーコンポーネント .................................................................................................. 73 エラーメッセージおよびコード ..................................................................................... 73 アプリケーションのエラー処理 ..................................................................................... 76 エラーの再試行とエクスポネンシャルバックオフ ............................................................. 76 API Version 2012-08-10 iv Amazon DynamoDB 開発者ガイド バッチオペレーションとエラー処理 ............................................................................... 77 DynamoDB 用の高レベルプログラミングインターフェイス ....................................................... 78 Java: DynamoDBMapper .............................................................................................. 78 .NET ドキュメントモデル ........................................................................................... 116 .NET: オブジェクト永続性モデル ................................................................................. 138 コードサンプルの実行 ........................................................................................................ 165 サンプルデータのロード ............................................................................................. 166 Java コードサンプル .................................................................................................. 171 .NET コードサンプル ................................................................................................. 173 PHP コードサンプル .................................................................................................. 175 DynamoDB の操作 ..................................................................................................................... 178 テーブルの操作 ................................................................................................................. 178 プライマリキーの指定 ................................................................................................ 179 テーブルの読み書き要件 ............................................................................................. 179 キャパシティーユニットの計算 .................................................................................... 181 テーブルのリストと情報を取得する .............................................................................. 183 DynamoDB のタグ付け ............................................................................................... 184 テーブルの操作 : Java ................................................................................................ 186 テーブルの操作 : .NET ................................................................................................ 191 テーブルの操作 : PHP ................................................................................................ 198 項目の操作 ....................................................................................................................... 204 概要 ......................................................................................................................... 205 項目を読み込む ......................................................................................................... 206 項目を書き込む ......................................................................................................... 206 バッチオペレーション ................................................................................................ 207 アトミックカウンタ ................................................................................................... 207 条件付きの書き込み ................................................................................................... 208 式を使用した項目の読み取りと書き込み ....................................................................... 210 項目の操作 : Java ...................................................................................................... 228 項目の操作 : .NET ...................................................................................................... 250 項目の操作 : PHP ...................................................................................................... 274 クエリおよびスキャンの使用 ............................................................................................... 287 Query ...................................................................................................................... 287 スキャン .................................................................................................................. 289 クエリまたはスキャンからの結果のフィルタリング ........................................................ 289 クエリおよびスキャンオペレーションによって消費されるキャパシティーユニット ............. 290 ページ単位の出力件数を指定 ....................................................................................... 290 制限 ......................................................................................................................... 290 応答での項目のカウント ............................................................................................. 291 読み込み整合性 ......................................................................................................... 291 クエリおよびスキャンのパフォーマンス ....................................................................... 292 並列スキャン ............................................................................................................ 292 クエリ ..................................................................................................................... 294 スキャニング ............................................................................................................ 310 インデックスの使用 ........................................................................................................... 333 グローバルセカンダリインデックス .............................................................................. 336 ローカルセカンダリインデックス ................................................................................. 383 ストリームの使用 .............................................................................................................. 426 DynamoDB ストリーム におけるエンドポイント ............................................................ 427 ストリームの有効化 ................................................................................................... 428 ストリームの読み込みと処理 ....................................................................................... 429 DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 ................... 430 チュートリアル : DynamoDB ストリーム の低レベルの API ............................................. 443 クロスリージョン レプリケーション ............................................................................. 450 DynamoDB ストリーム と AWS Lambda のトリガー ...................................................... 451 認証とアクセスコントロール ....................................................................................................... 460 認証 ................................................................................................................................. 460 アクセスコントロール ........................................................................................................ 461 API Version 2012-08-10 v Amazon DynamoDB 開発者ガイド アクセス管理の概要 ........................................................................................................... 462 Amazon DynamoDB リソースおよびオペレーション ....................................................... 462 リソース所有権について ............................................................................................. 463 リソースへのアクセスの管理 ....................................................................................... 463 ポリシー要素の指定 : アクション、効果、プリンシパル .................................................. 464 ポリシーでの条件の指定 ............................................................................................. 465 アイデンティティベースのポリシー (IAM ポリシー) を使用する ................................................ 465 コンソールのアクセス許可 .......................................................................................... 466 Amazon DynamoDB での AWS 管理 (事前定義) ポリシー ................................................ 466 お客様が管理するポリシーの例 .................................................................................... 467 DynamoDB API の権限リファレンス .................................................................................... 473 関連トピック ............................................................................................................ 477 条件の使用 ....................................................................................................................... 477 概要 ......................................................................................................................... 477 条件の指定: 条件キーの使用 ........................................................................................ 480 関連トピック ............................................................................................................ 488 ウェブアイデンティティフェデレーションの使用 ................................................................... 488 ウェブアイデンティティフェデレーションに関するその他のリソース ................................ 488 ウェブアイデンティティフェデレーションのポリシー例 .................................................. 489 ウェブアイデンティティフェデレーションを使用するための準備 ...................................... 491 ウェブアイデンティティフェデレーションを使用するアプリケーションの記述 ................... 492 Amazon DynamoDB のモニタリング ............................................................................................ 495 モニタリングツール ........................................................................................................... 496 自動化ツール ............................................................................................................ 496 手動ツール ............................................................................................................... 496 Amazon CloudWatch でのモニタリング ................................................................................ 497 メトリクスとディメンション ....................................................................................... 497 メトリクスの使用 ...................................................................................................... 508 アラームの作成 ......................................................................................................... 509 AWS CloudTrail を使用した DynamoDB オペレーションのログ記録 .......................................... 511 CloudTrail での DynamoDB 情報 ................................................................................. 512 DynamoDB ログファイルエントリの概要 ...................................................................... 512 他の AWS のサービスとの統合 .................................................................................................... 518 Amazon Redshift との統合 .................................................................................................. 518 Amazon EMR との統合 ...................................................................................................... 519 概要 ......................................................................................................................... 520 チュートリアル: Amazon DynamoDB および Apache Hive の使用 ..................................... 520 Hive に外部テーブルを作成します。 ............................................................................. 527 HiveQL ステートメントの処理 ..................................................................................... 529 DynamoDB でのデータのクエリ .................................................................................. 530 Amazon DynamoDB でデータを出し入れする ................................................................ 532 パフォーマンスの調節 ................................................................................................ 544 Amazon Data Pipeline との統合 .......................................................................................... 548 データをエクスポートおよびインポートデータするための前提条件 ................................... 550 DynamoDB から Amazon S3 にデータをエクスポートする .............................................. 554 Amazon S3 から DynamoDB にデータをインポートする ................................................. 555 トラブルシューティング ............................................................................................. 556 AWS Data Pipeline と DynamoDB 用の定義済みテンプレート .......................................... 557 DynamoDB での制限 .................................................................................................................. 558 キャパシティーユニットとプロビジョニングされるスループット .............................................. 558 キャパシティーユニットサイズ .................................................................................... 558 プロビジョニングされたスループットの最小値と最大値 .................................................. 559 プロビジョニングされるスループットを増やす .............................................................. 559 プロビジョニングされるスループットを減らす .............................................................. 559 テーブル .......................................................................................................................... 560 テーブルのサイズ ...................................................................................................... 560 アカウントあたりのテーブル数 .................................................................................... 560 セカンダリインデックス ..................................................................................................... 560 API Version 2012-08-10 vi Amazon DynamoDB 開発者ガイド テーブルごとのセカンダリインデックス ....................................................................... 560 テーブルあたりの射影されたセカンダリインデックス属性 ............................................... 560 パーティションキーおよびソートキー ................................................................................... 560 パーティションキーの長さ .......................................................................................... 560 パーティションキーの値 ............................................................................................. 560 ソートキーの長さ ...................................................................................................... 561 ソートキー値 ............................................................................................................ 561 名前付けルール ................................................................................................................. 561 テーブル名およびセカンダリインデックス名 ................................................................. 561 属性名 ..................................................................................................................... 561 データ型 .......................................................................................................................... 561 文字列 ..................................................................................................................... 561 数値 ......................................................................................................................... 562 バイナリ .................................................................................................................. 562 アイテム .......................................................................................................................... 562 項目のサイズ ............................................................................................................ 562 ローカルセカンダリインデックスを持つテーブルの項目サイズ ......................................... 562 属性 ................................................................................................................................. 562 項目あたりの属性名と値のペア .................................................................................... 562 リスト、マップ、またはセットの値の最大数 ................................................................. 563 属性値 ..................................................................................................................... 563 入れ子の属性の深さ ................................................................................................... 563 式パラメーター ................................................................................................................. 563 長さ ......................................................................................................................... 563 演算子およびオペランド ............................................................................................. 563 予約語 ..................................................................................................................... 563 DynamoDB ストリーム ....................................................................................................... 563 DynamoDB ストリーム のシャードの同時リーダー ......................................................... 563 ストリームが有効なテーブルの最大書き込みキャパシティー ............................................ 564 API 固有の制限 ................................................................................................................. 564 ベストプラクティス ................................................................................................................... 565 テーブルのベストプラクティス ............................................................................................ 565 項目のベストプラクティス .................................................................................................. 565 クエリとスキャンのベストプラクティス ............................................................................... 566 ローカルセカンダリインデックス のベストプラクティス ......................................................... 566 グローバルセカンダリインデックス のベストプラクティス ...................................................... 566 テーブルの操作のガイドライン ............................................................................................ 566 テーブル内のすべての項目に対して均一なデータアクセスを実現する設計 ......................... 567 パーティションの動作について .................................................................................... 569 急激に増大するキャパシティーは控えめに使用する ........................................................ 573 データアップロード時に書き込みアクティビティを分散する ............................................ 573 時系列データへのアクセスパターンを理解する .............................................................. 574 人気の高い項目をキャッシュに格納する ....................................................................... 575 プロビジョニングされたスループットを調整するときにワークロードの均一性を考慮する .... 575 大規模環境でのアプリケーションのテスト .................................................................... 576 項目の操作のガイドライン .................................................................................................. 577 大規模な設定属性の代わりに 1 対多のテーブルを使用する .............................................. 577 複数テーブルの使用による多様なアクセスパターンのサポート ......................................... 578 大量の属性値を圧縮する ............................................................................................. 579 Amazon S3 に大量の属性値を格納する ......................................................................... 580 大量の属性を複数の項目に分割する .............................................................................. 580 クエリおよびスキャンのガイドライン ................................................................................... 581 読み込みアクティビティの急激な増大の回避 ................................................................. 581 並列スキャンの利用 ................................................................................................... 583 ローカルセカンダリインデックス のガイドライン .................................................................. 584 インデックスの使用は控えめにする .............................................................................. 584 射影を慎重に選択する ................................................................................................ 584 フェッチを回避するための頻繁なクエリの最適化 ........................................................... 585 API Version 2012-08-10 vii Amazon DynamoDB 開発者ガイド スパースなインデックスの利用 .................................................................................... 585 項目コレクションの拡張の監視 .................................................................................... 586 グローバルセカンダリインデックス のガイドライン ............................................................... 586 ワークロードが均一になるようにキーを選択する ........................................................... 586 スパースなインデックスの利用 .................................................................................... 587 グローバルセカンダリインデックス を使用したすばやい検索 ........................................... 587 結果整合性のある読み込みレプリカを作成する .............................................................. 587 付録 ......................................................................................................................................... 589 サンプルテーブルとデータ .................................................................................................. 589 サンプルデータファイル ............................................................................................. 590 サンプルテーブルの作成とデータのアップロード ................................................................... 599 サンプルテーブルの作成とデータのアップロード – Java ................................................. 600 サンプルテーブルの作成とデータのアップロード – .NET ................................................. 608 サンプルテーブルの作成とデータのアップロード – PHP ................................................. 617 AWS SDK for Python(Boto)を使用したサンプルアプリケーション ......................................... 626 ステップ 1: ローカルにデプロイおよびテストを実行する ................................................. 627 ステップ 2: データモデルと実装の詳細を調べる ............................................................. 630 ステップ 3: 本稼働環境でのデプロイ ............................................................................ 637 ステップ 4: リソースをクリーンアップする ................................................................... 644 DynamoDB 用の追加のツールとリソース .............................................................................. 644 Amazon DynamoDB Storage Backend for Titan ............................................................. 645 Amazon DynamoDB 用 Logstash プラグイン ................................................................. 668 DynamoDB の予約語 .......................................................................................................... 668 レガシー条件パラメータ ..................................................................................................... 678 AttributesToGet ......................................................................................................... 679 AttributeUpdates ........................................................................................................ 680 ConditionalOperator ................................................................................................... 681 Expected .................................................................................................................. 682 KeyConditions ........................................................................................................... 685 QueryFilter ................................................................................................................ 687 ScanFilter ................................................................................................................. 689 レガシー パラメータを使用した条件書き込み ................................................................ 690 現在の低レベル API バージョン (2012-08-10) ........................................................................ 696 前バージョンの低レベル API (2011-12-05) ............................................................................ 697 BatchGetItem ............................................................................................................ 697 BatchWriteItem .......................................................................................................... 703 CreateTable .............................................................................................................. 708 DeleteItem ................................................................................................................ 713 DeleteTable .............................................................................................................. 717 DescribeTables ......................................................................................................... 721 GetItem .................................................................................................................... 724 ListTables ................................................................................................................. 726 PutItem .................................................................................................................... 728 Query ...................................................................................................................... 734 スキャン .................................................................................................................. 743 UpdateItem ............................................................................................................... 754 UpdateTable ............................................................................................................. 760 ドキュメント履歴 ...................................................................................................................... 764 API Version 2012-08-10 viii Amazon DynamoDB 開発者ガイド Amazon DynamoDB とは これは Amazon DynamoDB 開発者ガイド です。 Amazon DynamoDB は、完全に管理された NoSQL データベースサービスで、高速かつ予測可能なパ フォーマンスとシームレスな拡張性を提供します。DynamoDB を使用すると、分散データベースの運 用とスケーリングに伴う管理作業をまかせることができるため、ハードウェアのプロビジョニング、 設定と構成、レプリケーション、ソフトウェアパッチ適用、クラスタースケーリングなどを自分で行 う必要はなくなります。 DynamoDB では、任意の量のデータを保存および取得できるデータベーステーブルを作成し、任意の レベルのリクエストトラフィックを処理できます。ダウンタイムやパフォーマンスの低下を発生させ ずに、テーブルのスループット容量を拡張または縮小し、AWS マネジメントコンソールを使用して、 リソースの利用率とパフォーマンスメトリクスをモニタリングできます。 DynamoDB は十分な数のサーバー間でデータとトラフィックを自動的に分散し、一貫した高速なパ フォーマンスを維持したまま、スループットとストレージの要件に対応します。すべてのデータは SSD (Solid State Disk) に保存され、1 つの AWS リージョン内の複数のアベイラビリティーゾーン間 で自動的にレプリケートすることによって、高い可用性とデータ堅牢性を実現します。 最初に以下のセクションを読むことをお勧めします。 • Amazon DynamoDB: 仕組み (p. 2)—DynamoDB の基本的な概念を学習します。 • DynamoDB のセットアップ (p. 44)—DynamoDB (ダウンロード可能バージョンまたはウェブ サービス) をセットアップする方法を学習します。 • DynamoDB へのアクセス (p. 50)—コンソール、CLI、または API を使用して DynamoDB にアク セスする方法を学習します。 アプリケーション開発の詳細については、以下を参照してください。 • DynamoDB および AWS SDK を使用したプログラミング (p. 62) • DynamoDB の操作 (p. 178) Note 言語固有のチュートリアルとサンプルコードを「Amazon DynamoDB 入門ガイド」で参照 することもできます。AWS SDK は、さまざまな言語で利用できます。詳細なリストについ ては、「Tools for Amazon Web Services」を参照してください。 API Version 2012-08-10 1 Amazon DynamoDB 開発者ガイド 仕組み パフォーマンスを最大にしてスループットコストを最小にするための推奨事項をすばやく見つけるに は、「DynamoDB のベストプラクティス (p. 565)」を参照してください。DynamoDB リソースにタ グ付けする方法については、「DynamoDB のタグ付け (p. 184)」を参照してください。 最後に、リレーショナルデータベース管理システム (RDBMS) データベースを識別し、DynamoDB に 移行する場合は、「RDBMS から Amazon DynamoDB への移行のベストプラクティス」を参照してく ださい。 Amazon DynamoDB: 仕組み 以下のセクションでは、Amazon DynamoDB サービスコンポーネントと、それらの対話方法の概要を 示します。 この概要を読んだ後は、「テーブルの作成とサンプルデータのロード (p. 166)」セクションの操作を お試しください。このセクションでは、サンプルテーブルを作成し、データをアップロードして、い くつかの基本的なデータベース操作を実行します。 言語固有のチュートリアルとサンプルコードを「Amazon DynamoDB 入門ガイド」で参照することも できます。 トピック • DynamoDB コアコンポーネント (p. 2) • DynamoDB API (p. 9) • 命名ルールおよびデータ型 (p. 11) • 読み込み整合性 (p. 16) • プロビジョニングされたスループット (p. 16) • パーティションとデータ分散 (p. 19) DynamoDB コアコンポーネント DynamoDB では、テーブル、項目、および属性が、操作するコアコンポーネントです。テーブルは項 目の集合であり、各項目は属性の集合です。DynamoDB はプライマリキーを使用してテーブルの各項 目を一意に識別し、セカンダリインデックスを使用してクエリの柔軟性を高めます。DynamoDB スト リーム を使用して、DynamoDB テーブルのデータ変更イベントをキャプチャできます。 DynamoDB には制限があります。詳細については、「DynamoDB での制限 (p. 558)」を参照してく ださい。 トピック • テーブル、項目、属性 (p. 2) • プライマリキー (p. 5) • セカンダリインデックス (p. 6) • DynamoDB ストリーム (p. 8) テーブル、項目、属性 DynamoDB の基本コンポーネントは次のとおりです。 • テーブル – 他のデータベース管理システムと同様、DynamoDB はデータをテーブルに保存しま す。テーブルは、データのコレクションです。たとえば、個人の連絡先情報を保存するために使用 できる People (以下に示す) というテーブルの例を参照してください。 API Version 2012-08-10 2 Amazon DynamoDB 開発者ガイド コアコンポーネント • 項目 – 各テーブルには複数の項目が含まれています。項目は、他のすべての項目間で一意に識別可 能な属性のグループです。DynamoDB の項目は、多くの点で他のリレーショナルデータベースシス テムの行、レコード、またはタプルに似ています。例の People テーブルでは、各項目は人を表し ます。 • 属性 – 各項目は 1 つ以上の属性で構成されます。属性は、基盤となるデータ要素であり、そ れ以上分割する必要がないものです。DynamoDB 内の属性は、多くの点で他のデータベー スシステムのフィールドや列に似ています。たとえば、People サンプルテーブルの項目に は、PersonID、LastName、FirstName のような名前の属性が含まれます。 次の図は、いくつかの項目と属性の例を含む、People という名前のテーブルを示しています。 People テーブルについて、以下の点に注意してください。 • テーブルの各項目には一意の識別子があります。これは、テーブルの他のすべての項目からその項 目を区別するプライマリキーです。People テーブルで、プライマリキーは 1 つの属性 (PersonID) で構成されます。 • プライマリキー以外、People テーブルはスキーマレスです。つまり、属性またはデータ型を事前 に定義する必要はありません。各項目は、独自の固有の属性を持つことができます。 • 属性のほとんどはスカラーです。つまり、1 つの値のみを持つことができます。文字列と数値はス カラーの一般的な例です。 • 項目の一部には、入れ子の属性 (Address) があります。DynamoDB は深さが最大 32 レベルの入れ 子の属性をサポートします。 以下は、音楽コレクションを継続して追跡するために使用できる、Music という名前の別のサンプル テーブルです。 API Version 2012-08-10 3 Amazon DynamoDB 開発者ガイド コアコンポーネント Music テーブルについて、以下の点に注意してください。 • Music のプライマリキーは 2 つの属性 (Artist および SongTitle) で構成されます。テーブルの 各項目にはこれら 2 つの属性が必要です。Artist および SongTitle の組み合わせにより、テー ブルの各項目が他のすべての項目から区別されます。 • プライマリキー以外、Music テーブルはスキーマレスです。つまり、属性またはデータ型を事前に 定義する必要はありません。各項目は、独自の固有の属性を持つことができます。 • 項目の 1 つに、入れ子の属性 (PromotionInfo) があります。これには、入れ子の他の属性が含ま れます。DynamoDB は深さが最大 32 レベルの入れ子の属性をサポートします。 詳細については、「DynamoDB でのテーブルの操作 (p. 178)」を参照してください。 API Version 2012-08-10 4 Amazon DynamoDB 開発者ガイド コアコンポーネント プライマリキー テーブルを作成する場合には、テーブル名に加えて、テーブルのプライマリキーを指定する必要があ ります。プライマリキーはテーブルの各項目を一意に識別するため、テーブル内の 2 つの項目が同じ キーを持つことはありません。 DynamoDB は 2 種類の異なるプライマリキーをサポートします。 • パーティションキー – パーティションキーという 1 つの属性で構成されたシンプルなプライマリ キー。 DynamoDB は、パーティションキーの値を内部ハッシュ関数への入力として使用します。ハッシュ 関数からの出力により、項目が保存されるパーティション (DynamoDB 内部の物理ストレージ) が決 まります。 パーティションキーのみを含むテーブルでは、2 つの項目が同じパーティションキー値を持つこと はできません。 「テーブル、項目、属性 (p. 2)」で説明されている People テーブルは、シンプルなプライマリ キー (PersonID) があるテーブルの例です。この項目に値 PersonId を指定すると、People テー ブルの任意の項目にすぐにアクセスできます。 • パーティションとソートキー – 複合プライマリキーと呼ばれるこのキーのタイプは、2 つの属性で 構成されます。最初の属性はパーティションキーであり、2 番目の属性はソートキーです。 DynamoDB は、パーティションキーの値を内部ハッシュ関数への入力として使用します。ハッシュ 関数からの出力により、項目が保存されるパーティション (DynamoDB 内部の物理ストレージ) が決 まります。同じパーティションキーを持つすべての項目は、ソートキー値でソートされてまとめて 保存されます。 パーティションキーとソートキーがあるテーブルでは、2 つの項目が同じパーティションキー値を 持つこともできます。ただし、それらの 2 つの項目には別のソートキー値が必要です。 「テーブル、項目、属性 (p. 2)」で説明されている Music テーブルは、複合プライマリキー (Artist および SongTitle) があるテーブルの例です。この Music テーブルの任意の項目には、 その項目の Artist および SongTitle 値を指定すればすぐにアクセスできます。 複合プライマリキーは、データのクエリを実行するときに柔軟性を高めます。たとえば、Artist の値のみを指定した場合、DynamoDB はそのアーティストのすべての曲を取得します。Artist の 値と SongTitle の範囲を指定し、特定のアーティストの曲のサブセットのみを取得することもで きます。 Note 項目のパーティションキーは、そのハッシュ属性とも呼ばれます。ハッシュ属性という用語 は、DynamoDB が内部のハッシュ関数を使用し、パーティションキーの値に基づいてパー ティション間でデータ項目を均等に分散することに由来しています。 項目のソートキーは、範囲属性とも呼ばれます。範囲属性という用語は、ソートキー値で並 べ替えられた順に、DynamoDB が同じパーティションキーを持つ項目どうしを物理的に近く に保存する方法に由来しています。 各プライマリキー属性はスカラー値 (単一値のみを保持できる) である必要があります。プライマリ キー属性に許可される唯一のデータ型は、文字列、数値、またはバイナリです。他のキー以外の属性 では、このような制限はありません。 API Version 2012-08-10 5 Amazon DynamoDB 開発者ガイド コアコンポーネント セカンダリインデックス テーブルで 1 つ以上のセカンダリインデックスを作成できます。セカンダリインデックス では、プラ イマリキーに対するクエリに加えて、代替キーを使用して、テーブル内のデータのクエリを行うこと ができます。DynamoDB ではインデックスを使用する必要はありませんが、インデックスを使用する と、データのクエリを実行するときにアプリケーションの柔軟性が高まります。 DynamoDB では、次の 2 種類のインデックスをサポートしています。 • Global secondary index – テーブルと異なるパーティションキーとソートキーを持つインデックス。 • ローカルセカンダリインデックス – テーブルと同じパーティションキーと、異なるソートキーを持 つインデックス。 テーブルあたり最大 5 個のグローバルセカンダリインデックスと 5 個のローカルセカンダリインデッ クスまで定義できます。 前に示した Music サンプルテーブルでは、Artist (パーティションキー) または Artist および SongTitle (パーティションキーとソートキー) によってデータ項目にクエリを実行できます。Genre および AlbumTitle によってデータにクエリを実行する場合はどうでしょうか。これを行うには、こ れらの属性にインデックスを作成し、Music テーブルのクエリと同様に、インデックスにクエリを実 行できます。 次の図は、GenreAlbumTitle という新しいインデックスがある Music サンプルテーブルを示してい ます。 API Version 2012-08-10 6 Amazon DynamoDB 開発者ガイド コアコンポーネント GenreAlbumTitle インデックスについて、以下の点に注意してください。 • 各インデックスはテーブルに属します。これをインデックスの基本テーブルと呼びます。前述の例 では、Music が GenreAlbumTitle インデックスの基本テーブルです。 • DynamoDB はインデックスを自動的に維持します。基本テーブルの項目を追加、更新、または削除 すると、DynamoDB はそのテーブルに属するすべてのインデックスの対応する項目を追加、更新、 または削除します。 • インデックスを作成するときは、基本テーブルからインデックスにコピーまたは射影される属性を 指定します。少なくとも、DynamoDB は基本テーブルからインデックスにキー属性を射影します。 これは GenreAlbumTitle のケースで、Music テーブルのキー属性のみがインデックスに射影され ます。 API Version 2012-08-10 7 Amazon DynamoDB 開発者ガイド コアコンポーネント GenreAlbumTitle インデックスにクエリを実行し、特定のジャンルのすべてのアルバム (たとえ ば、すべての Rock アルバム) を検索できます。また、インデックスにクエリを実行して、特定のジャ ンル内のすべてのアルバムのうち、特定のアルバムタイトル (たとえば、タイトルが文字 H で始まる すべての Country アルバム) のみを検索することもできます。 詳細については、「セカンダリインデックスを使用したデータアクセス性の向上 (p. 333)」を参照し てください。 DynamoDB ストリーム DynamoDB ストリーム は、DynamoDB テーブルのデータ変更イベントをキャプチャするオプション の機能です。これらのイベントに関するデータは、ほとんどリアルタイムに、イベントの発生順にス トリームに表示されます。 各イベントはストリームレコードによって表されます。テーブルでストリームを有効にする と、DynamoDB ストリーム は次のいずれかのイベントが発生するたびに、ストリームレコードを書 き込みます。 • 新しい項目がテーブルに追加された場合、ストリームはすべての属性を含む項目全体のイメージを キャプチャします。 • 項目が更新された場合、ストリームは項目で変更された属性について、「前」と「後」のイメージ をキャプチャします。 • テーブルから項目を削除する場合、ストリームは項目が削除される前に項目全体のイメージを取得 します。 各ストリームレコードには、テーブルの名前、イベントのタイムスタンプ、およびその他のメタデー タも含まれます。ストリームレコードには 24 時間の有効期間があり、その後はストリームから自動 的に削除されます。 DynamoDB ストリーム は AWS Lambda と共に使用してトリガーを作成できます。これは、スト リームで関心のあるイベントが発生するたびに自動的に実行されるコードです。たとえば、会社の 顧客情報を含む Customers テーブルがあるとします。新規の各顧客に、歓迎の E メールを送信す るとします。そのテーブルでストリームを有効にし、そのストリームを Lambda 関数に関連付けま す。Lambda 関数は、新しいストリームレコードが表示されるたびに実行されますが、Customers テーブルに追加された新しい項目を処理するのみです。EmailAddress 属性を持つ項目につい て、Lambda 関数は Amazon Simple Email Service (Amazon SES) を呼び出してそのアドレスに E メールを送信します。 このシナリオを以下に図で示します。 API Version 2012-08-10 8 Amazon DynamoDB 開発者ガイド DynamoDB API Note この例で、最後の顧客 Craig Roe は、EmailAddress がないために E メールを受信しないこ とに注意してください。 トリガーに加えて、DynamoDB ストリーム は AWS リージョン内および AWS リージョン間のデータ レプリケーション、DynamoDB テーブル内のデータのマテリアライズされたビュー、Amazon Kinesis のマテリアライズされたビューを使用したデータ分析など、数多くの強力なソリューションを可能に します。 詳細については、「DynamoDB ストリーム を使用したテーブルアクティビティのキャプ チャ (p. 426)」を参照してください。 DynamoDB API DynamoDB を使用するには、アプリケーションでいくつかの簡単な API オペレーションを使用する必 要があります。以下に、カテゴリー別にこれらのオペレーションの概要を示します。 トピック • コントロールプレーン (p. 10) • データプレーン (p. 10) • DynamoDB ストリーム (p. 11) API Version 2012-08-10 9 Amazon DynamoDB 開発者ガイド DynamoDB API コントロールプレーン コントロールプレーンの操作では、DynamoDB テーブルを作成、管理できます。また、インデック ス、ストリーム、およびテーブルに依存する他のオブジェクトを操作できます。 • CreateTable – 新しいテーブルを作成します。オプションで、1 つ以上のセカンダリインデックス を作成し、テーブルに対して DynamoDB ストリーム を有効にできます。 • DescribeTable – プライマリキーのスキーマ、スループット設定、インデックス情報など、テー ブルに関する情報を返します。 • ListTables – リストのすべてのテーブルの名前を返します。 • UpdateTable – テーブルまたはそのインデックスの設定を変更、テーブルの新しいインデックスを 作成または削除、またはテーブルの DynamoDB ストリーム 設定を変更します。 • DeleteTable – テーブルとそのすべての依存オブジェクトを DynamoDB から削除します。 データプレーン データプレーンオペレーションでは、テーブルのデータで、作成、読み込み、更新、および削除 (CRUD とも呼ばれます) アクションを実行できます。一部のデータプレーンオペレーションでも、セ カンダリインデックス からデータを読み込むことができます。 データの作成 • PutItem – テーブルに単一の項目を書き込みます。プライマリキー属性を指定する必要があります が、その他の属性を指定する必要はありません。 • BatchWriteItem – 25 個の項目をテーブルに書き込みます。これは、PutItem を複数回呼び出 すよりも効率的です。アプリケーションで項目を書き込むために、1 回のネットワークラウンドト リップのみで済むためです。また、BatchWriteItem を使用して、1 つ以上のテーブルから複数の 項目を削除することもできます。 データの読み取り • GetItem – テーブルから単一の項目を取り出します。目的の項目のプライマリキーを指定する必要 があります。項目全体またはその属性のサブセットのみを取り出すことができます。 • BatchGetItem – 1 つ以上のテーブルから 100 個の項目を取り出します。これは、GetItem を複数 回呼び出すよりも効率的です。アプリケーションで項目を読み込むために、1 回のネットワークラ ウンドトリップのみで済むためです。 • Query – 特定のパーティションキーがあるすべての項目を取り出します。パーティションキーの値 を指定する必要があります。項目全体またはその属性のサブセットのみを取り出すことができま す。オプションで、ソートキーの値に条件を適用し、同じパーティションキーがあるデータのサブ セットだけを取り出すことができます。テーブルにパーティションキーとソートキーの両方を持つ テーブルがある場合、テーブルでこのオペレーションを使用できます。また、インデックスにパー ティションキーとソートキーの両方がある場合、インデックスでこのオペレーションを使用できま す。 • Scan – 指定されたテーブルまたはインデックスのすべての項目を取り出します。項目全体またはそ の属性のサブセットのみを取り出すことができます。オプションでフィルタリング条件を適用する と、関心のある値のみを返し、残りは破棄できます。 データの更新 • UpdateItem – 項目の 1 つ以上の属性を変更します。変更する項目のプライマリキーを指定する必 要があります。新しい属性を追加したり、既存の属性を変更または削除したりできます。ユーザー 定義の条件を満たす場合にのみ更新が成功するように、条件付きの更新を実行できます。オプショ API Version 2012-08-10 10 Amazon DynamoDB 開発者ガイド 命名ルールおよびデータ型 ンで、アトミックカウンタを実装できます。このカウンタは、他の書き込みリクエストを妨害する ことなく、数値属性をインクリメントまたはデクリメントします。 データの削除 • DeleteItem – テーブルから単一の項目を削除します。削除する項目のプライマリキーを指定する 必要があります。 • BatchWriteItem – 1 つ以上のテーブルから最大 25 個の項目を削除します。これは、DeleteItem を複数回呼び出すよりも効率的です。アプリケーションで項目を削除するために、1 回のネット ワークラウンドトリップのみで済むためです。また、BatchWriteItem を使用して、1 つ以上の テーブルに複数の項目を追加することもできます。 DynamoDB ストリーム DynamoDB ストリーム オペレーションでは、テーブルのストリームを有効または無効にし、スト リームに含まれるデータ変更レコードにアクセスすることができます。 • ListStreams – すべてのストリームのリスト、または特定のテーブルのストリームのみを返しま す。 • DescribeStream – Amazon リソースネーム (ARN)、アプリケーションが最初のいくつかのスト リームレコードの読み込みを開始できる場所など、ストリームに関する情報を返します。 • GetShardIterator – シャードイテレーターを返します。これは、ストリームからレコードを取得 するためにアプリケーションが使用するデータ構造です。 • GetRecords – 特定のシャードイテレーターを使用して 1 つ以上のストリームレコードを取得しま す。 命名ルールおよびデータ型 このセクションでは、DynamoDB の命名規則と、DynamoDB がサポートするさまざまなデータ 型について説明します。データタイプに適用される制限があります。詳細については、「データ 型 (p. 561)」を参照してください。 トピック • 名前付けルール (p. 11) • データ型 (p. 12) 名前付けルール DynamoDB のテーブル、属性、および他のオブジェクトには名前が必要です。名前は有意義で簡潔 である必要があります。たとえば、Products、Books、Authors などの名前は見ればすぐわかりま す。 DynamoDB の命名規則は次のとおりです。 • すべての名前は UTF-8 を使用してエンコードする必要があり、大文字と小文字が区別されます。 • テーブル名とインデックス名の長さは 3~255 文字で、次の文字のみを含めることができます。 • a-z • A-Z • 0-9 • _ (下線) API Version 2012-08-10 11 Amazon DynamoDB 開発者ガイド 命名ルールおよびデータ型 • - (ダッシュ) • . (ドット) • 属性名の長さは 1~255 文字である必要があります。 予約語と特殊文字 その他のデータベース管理システムと同様、DynamoDB には予約語と特殊文字のリストがあります。 • DynamoDB の予約語の一覧については、「DynamoDB の予約語 (p. 668)」を参照してください。 • DynamoDB では、# (ハッシュ) および: (コロン) に特別な意味があります。 DynamoDB では、命名目的でこれらの予約語と特殊文字を使用することができますが、お勧めしませ ん。これは、式でこれらの名前を使用するたびに、プレースホルダー変数を定義する必要があるため です。 詳細については、「属性の名前および値でのプレースホルダーの使用 (p. 213)」を参照してくださ い。 データ型 DynamoDB では、テーブル内の属性に対してさまざまなデータ型がサポートされています。データ型 は次のように分類できます。 • スカラー型 – スカラー型は 1 つの値を表すことができます。スカラー型は、数値、文字列、バイナ リ、ブール、および null です。 • ドキュメント型 – ドキュメント型は、JSON ドキュメントで見られるもののように、入れ子の属性 を持つ複雑な構造を表すことができます。ドキュメント型は、リストとマップです。 • セット型 – セット型は複数のスカラー値を表すことができます。セット型は、文字セット、数値 セット、およびバイナリセットです。 テーブルまたは セカンダリインデックス を作成するときは、各プライマリキー属性 (パーティション キーとソートキー) の名前とデータ型を指定する必要があります。さらに、各プライマリキー属性は、 文字列、数値、またはバイナリとして定義する必要があります。 DynamoDB は NoSQL データベースであり、スキーマレスです。つまり、プライマリキー属性以外 に、テーブルの作成時に属性またはデータ型を定義する必要はありません。これに対して、リレー ショナルデータベースでは、テーブルの作成時に各列の名前とデータ型を定義する必要があります。 ここでは、各データ型についてJSON 形式の例を挙げて説明します。 スカラー型 スカラー型は、数値、文字列、バイナリ、ブール、および null です。 文字列 文字列は、UTF-8 バイナリエンコードの Unicode です。文字列の長さは、0 より大きい必要があ り、DynamoDB 項目の最大サイズ 400 KB によって制限されます。 プライマリキー属性を文字列型属性として定義する場合、以下の制約がさらに適用されます。 • シンプルなプライマリキーの場合、最初の属性値 (パーティションキー) の最大長は 2048 バイト で す。 • 複合プライマリキーの場合、2 番目の属性値 (ソートキー) の最大長は 1024 バイト です。 API Version 2012-08-10 12 Amazon DynamoDB 開発者ガイド 命名ルールおよびデータ型 DynamoDB は、基礎となる UTF-8 文字列エンコードのバイトを使用して文字列を照合し、比較しま す。たとえば、「a」(0x61) は「A」(0x41) より大きく、「¿」(0xC2BF) は 「z」(0x7A) より大きいで す。 Example "Bicycle" 文字列データ型を使用して、日付またはタイムスタンプを表すことができます。これを行う 1 つの方 法は、これらの例に示すように、ISO 8601 文字列を使用することです。 • 2016-02-15 • 2015-12-21T17:42:34Z • 20150311T122706Z 詳細については、http://en.wikipedia.org/wiki/ISO_8601 を参照してください。 数値 数値は、正、負、または 0 とすることができます。数値は最大 38 桁の精度であり、これを超えると 例外が発生します。 • 正の範囲: 1E-130~9.9999999999999999999999999999999999999E+125 • 負の範囲: -9.9999999999999999999999999999999999999E+125~-1E-130 DynamoDB では、数値は可変長で表されます。先頭と末尾の 0 は切り捨てられます。 すべての数値はネットワーク経由で文字列として DynamoDB に送信され、言語やライブラリ間の互 換性が最大になります。ただし、DynamoDB は算術演算では数値を数値型属性として扱います。 Note 数値の精度が重要な場合は、数値型から変換する文字列を使用して、DynamoDB に数値を渡 します。 Example 300 数値データ型を使用して、日付またはタイムスタンプを表すことができます。これを行う 1 つの方法 は、エポック時間 (1970 年 1 月 1 日の 00:00:00 UTC 以降の秒数) を使用することです。たとえば、 エポック時間 1437136300 は、2015 年 7 月 17 日の 12:31:40 UTC を表します。 詳細については、http://en.wikipedia.org/wiki/Unix_time を参照してください。 バイナリ バイナリ型の属性には、圧縮テキスト、暗号化データ、イメージなど、任意のバイナリデータが保存 されます。DynamoDB は、バイナリ値を比較するたびに、各バイナリデータを符号なしとして扱いま す。 API Version 2012-08-10 13 Amazon DynamoDB 開発者ガイド 命名ルールおよびデータ型 バイナリ属性の長さは 0 より大きい必要があり、DynamoDB 項目の最大サイズ 400 KB によって制限 されます。 プライマリキー属性をバイナリ型属性として定義する場合、以下の制約がさらに適用されます。 • シンプルなプライマリキーの場合、最初の属性値 (パーティションキー) の最大長は 2048 バイト で す。 • 複合プライマリキーの場合、2 番目の属性値 (ソートキー) の最大長は 1024 バイト です。 アプリケーションは、DynamoDB に送信する前に、base64 エンコード形式のバイナリ値をエンコー ドする必要があります。DynamoDB は、これらの値を受信すると、データを符号なしバイト配列にデ コードし、それをバイナリ属性の長さとして使用します。 Example 次に示しているのはバイナリ属性の例であり、Base64 でエンコードされたテキストを使用していま す。 dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk ブール ブール型の属性には、true または false が格納されます。 Example true Null Null は不明または未定義の状態の属性を表します。 Example NULL ドキュメント型 ドキュメント型は、リストとマップです。これらのデータ型は、相互に入れ子にして、最大 32 レベ ルの深さまで複雑なデータ構造を表すことができます。 値を含む項目が DynamoDB のサイズ制限 (400 KB) 内である限り、リストまたはマップの値の最大数 の制限はありません。 属性値は空の文字列または空のセット (文字列セット、数値セット、またはバイナリセット) にす ることはできません。ただし、空のリストおよびマップは許可されます。詳細については、「属 性 (p. 562)」を参照してください。 リスト リスト型の属性には、順序付きの値のコレクションを保存できます。リストは角括弧で囲まれます: [ ... ] API Version 2012-08-10 14 Amazon DynamoDB 開発者ガイド 命名ルールおよびデータ型 リストは JSON 配列に似ています。リスト要素に保存できるデータ型に制限はなく、リスト要素の要 素が同じ型である必要はありません。 次の例は、2 つの文字列と数が含まれるリストを示します。 Example FavoriteThings: ["Cookies", "Coffee", 3.14159] Note DynamoDB では、要素が深い入れ子になっていても、リスト内の個々の要素を操作できま す。詳細については、「ドキュメントパス (p. 212)」を参照してください。 マップ マップ型属性は、順序なしの名前と値のペアのコレクションを保存できます。マップは中括弧で囲ま れます: { ... } マップは、JSON オブジェクトと同様です。マップの要素に保存できるデータ型に制限はなく、マッ プの要素が同じ型である必要はありません。 マップは DynamoDB で JSON ドキュメントを保存するのに最適です。以下の例は、文字列、数値、 別のマップを含む入れ子のリストを要素とするマップを示しています。 Example { Day: "Monday", UnreadEmails: 42, ItemsOnMyDesk: [ "Coffee Cup", "Telephone", { Pens: { Quantity : 3}, Pencils: { Quantity : 2}, Erasers: { Quantity : 1} } ] } Note DynamoDB では、要素が深い入れ子になっていても、マップ内の個々の要素を操作できま す。詳細については、「ドキュメントパス (p. 212)」を参照してください。 セット DynamoDB は、数値、文字列、またはバイナリ値のセットを表す型をサポートします。セット内のす べての要素は、同じ型である必要があります。たとえば、数値セット型の属性は数値のみを含むこと ができ、文字列セットは文字列のみを含むことができるなどです。 API Version 2012-08-10 15 Amazon DynamoDB 開発者ガイド 読み込み整合性 値を含む項目が DynamoDB のサイズ制限 (400 KB) 内である限り、セットの値の最大数の制限はあり ません。 設定内の各値は一意である必要があります。設定内の値の順序は保持されません。したがって、アプ リケーションは、設定内の要素の特定の順序に依存することはできません。最後に、DynamoDB では 空白のセットはサポートされていません。 Example (文字セット、数値セット、バイナリセット) ["Black", "Green" ,"Red"] [42.2, -19, 7.5, 3.14] ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] 読み込み整合性 Amazon DynamoDB は、世界中の複数の AWS リージョンで利用できます。各リージョンは完全に 独立していて、他の AWS リージョンから分離されています。たとえば、us-east-1 リージョンに People というテーブルがあり、us-west-2 リージョンに People という名前の別のテーブルがある 場合、これらは 2 つの完全に異なるテーブルであると見なされます。DynamoDB を利用できるすべて の AWS リージョンのリストについては、アマゾン ウェブ サービス全般のリファレンスのAWS リー ジョンとエンドポイントを参照してください。 各 AWS リージョンは、複数のそれぞれ独立した場所で構成されており、これらの場所はアベイラビ リティーゾーンと呼ばれます。各アベイラビリティーゾーンは、他のアベイラビリティーゾーンにお ける障害の影響は受けず、同じリージョン内の他のアベイラビリティーゾーンに対して、低コスト、 低レイテンシーでネットワーク接続できます。これにより、リージョンの複数のアベイラビリティー ゾーン間でデータの迅速なレプリケーションが可能になります。 アプリケーションが DynamoDB テーブルにデータを書き込み、HTTP 200 応答 (OK) を受け取ると、 データのすべてのコピーが更新されます。データは、すべてのストレージの場所で結果的に整合性が 保たれます (通常は 1 秒以内)。 DynamoDB は結果整合性と強力な整合性のある読み込みをサポートします。 結果整合性のある読み込み DynamoDB テーブルからの読み込みオペレーションの応答には、最近の書き込みオペレーションの結 果が反映されていないことがあります。応答には古いデータが含まれる場合があります。少し時間が たってから読み込みリクエストを繰り返すと、応答で最新のデータが返されます。 強力な整合性のある読み込み 強力な整合性のある読み込みをリクエストすると、DynamoDB は成功した以前のすべての書き込み オペレーションからの更新が反映された最新データの応答を返します。強力な整合性のある読み込み は、ネットワークの遅延または停止があった場合には利用できなくなる可能性があります。 Note DynamoDB は、特に指定がない限り、結果的に整合性のある読み込みを使用します。読み取 りオペレーション (GetItem、Query、Scan など) では ConsistentRead パラメーターが提 供されます。このパラメーターを true に設定すると、DynamoDB はオペレーション中に強い 整合性のある読み込みを使用します。 プロビジョニングされたスループット トピック API Version 2012-08-10 16 Amazon DynamoDB 開発者ガイド プロビジョニングされたスループット • 読み込みキャパシティーユニット (p. 17) • 書き込みキャパシティーユニット (p. 18) • リザーブドキャパシティーの購入 (p. 19) テーブルを作成する場合は、読み込みと書き込み用に予約するプロビジョンドスループット容量を指 定します。DynamoDB では、低レイテンシーで一貫したスループットパフォーマンスを実現するため に必要なリソースを予約します。また、プロビジョンドスループット設定を変更し、必要に応じて容 量を増減できます。 DynamoDB では、キャパシティーユニットの観点で、プロビジョンドスループット要件を指定しま す。次のガイドラインを使用して、プロビジョンドスループットを決定します。 • 1 つの読み込みキャパシティーユニットは、最大サイズ 4 KB の項目について、1 秒あたり 1 回の 強力な整合性のある読み込み、あるいは 1 秒あたり 2 回の結果的に整合性のある読み込みを表し ます。4 KB より大きい項目を読み込む必要がある場合、DynamoDB は追加の読み込みキャパシ ティーユニットを消費する必要があります。必要な読み込みキャパシティーユニットの最大数は、 項目のサイズと、結果整合性のある読み込みまたは強力な整合性のある読み込みが必要かどうかに よって異なります。 • 1 つの書き込みキャパシティーユニットは、最大でサイズが 1 KB までの項目について、1 秒あたり 1 回の書き込みを表します。1 KB より大きい項目を書き込む必要がある場合、DynamoDB は追加 の書き込みキャパシティーユニットを消費する必要があります。必要な書き込みキャパシティーユ ニットの合計数は、項目サイズに応じて異なります。 セカンダリインデックスがあるテーブルの場合、DynamoDB はさらにキャパシティーユニットを消費 します。たとえば、1 つの 1 KB の項目をテーブルに追加するときに、その項目にインデックス付きの 属性が含まれている場合には、テーブルへの書き込み用とインデックスへの書き込み用の 2 つの書き 込みキャパシティーユニットが必要になります。詳細については、以下のトピックを参照してくださ い。 • プロビジョニングされたスループットに関する考慮事項(ローカルセカンダリインデック ス) (p. 389) • プロビジョニングされたスループットに関する考慮事項(グローバルセカンダリインデック ス) (p. 342) アプリケーションの読み込みまたは書き込みリクエストが、テーブルにプロビジョニン グされたスループットを超えると、DynamoDB がそれらのリクエストを制限する可能 性があります。これが発生すると、リクエストは HTTP 400 コード (Bad Request) と ProvisionedThroughputExceededException で失敗します。AWS SDK には、制限されたリク エストを再試行するための組み込みサポートがあります。ただし、エラー処理コードでエクスポネン シャルパックオフロジックの使用を検討することをお勧めします。詳細については、「エラーの再試 行とエクスポネンシャルバックオフ (p. 76)」を参照してください。 AWS マネジメントコンソール を使用して、プロビジョニングされたスループットと実際のスルー プットをモニタリングし、制限されているリクエストがあるかどうか判断できます。また、トラ フィックの変化を予測し、プロビジョニンドキャパシティー設定を変更できます。 読み込みキャパシティーユニット 項目のサイズが 4 KB よりも小さい場合、それぞれの読み込みキャパシティーユニットでは、1 秒あ たり 1 回の強力な整合性のある読み込みか、1 秒あたり 2 回の結果整合性のある読み込みが得られま す。 たとえば、テーブルから 1 秒あたり 80 項目を読み込むとします。項目のサイズが 3 KB で、強い整合 性のある読み込みが必要であるとします。このシナリオでは、読み込みごとに 1 つのプロビジョニン グされた読み込みキャパシティーユニットが必要です。これを判断するには、次の例に示すようにオ ペレーションの項目サイズを 4 KB で除算し、次に最も近い整数に切り上げます。 API Version 2012-08-10 17 Amazon DynamoDB 開発者ガイド プロビジョニングされたスループット 3 KB / 4 KB = 0.75 --> 1 このシナリオでは、テーブルのプロビジョングされた読み込みスループットを 80 読み込みキャパシ ティーユニットに設定する必要があります。 1 read capacity unit per item × 80 reads per second = 80 read capacity units 強い整合性のある読み込みの代わりに結果的に整合性のある読み込みが必要な場合は、40 個の読み込 みキャパシティーユニットのみをプロビジョニングする必要があります。 項目が 4 KB より大きい場合は、項目サイズを次の 4 KB 境界に切り上げる必要があります。たとえ ば、1 秒あたり 100 個の強い整合性のある読み込みを実行し、項目のサイズが 6 KB であるとしま す。最初に、次に示すように項目ごとに必要な読み込みキャパシティーの数を判断し、それを最も近 い整数に切り上げる必要があります。 6 KB / 4 KB = 1.5 --> 2 結果は項目あたり 2 つの読み込みキャパシティーユニットになります。ここで、この数値を、1 秒あ たりの強い整合性のある読み込み数で乗算します。 2 read capacity units per item × 100 reads per second = 200 したがって、テーブルのプロビジョニングされた読み込みキャパシティーユニットを 200 に設定する 必要があります (強い整合性のある読み込みの代わりに結果的に整合性のある読み込みが必要な場合 は、100 個の読み込みキャパシティーユニットのみをプロビジョニングする必要があります)。 単一の項目を読み込むには、GetItem オペレーションを使用します。複数の項目を読み込む場 合、BatchGetItem を使用してテーブルから最大 100 項目を取り出すことができます。 Query および Scan オペレーションを使用して、1 つのリクエストによってテーブルまたはインデッ クスから連続する複数の項目を取り出すことができます。これらのオペレーションで、DynamoDB は 処理済みの項目の累積サイズを使用して、プロビジョニングするスループットを計算します。たとえ ば、Query オペレーションによって 1 KB の項目を 100 個取り出した場合、読み込みキャパシティー の計算は、GetItem または BatchGetItem を使用して個別に取り出した場合のように (100 × 4 KB) = 100 読み込みキャパシティーユニットにはなりません。代わりに、合計は後に示すように 25 読み込 みキャパシティーユニットのみになります。 (100 * 1024 bytes = 100 KB) / 4 KB = 25 read capacity units 詳細については、「キャパシティーユニットの計算 (p. 181)」を参照してください。 書き込みキャパシティーユニット 項目のサイズが 1 KB より小さい場合、それぞれの書き込みキャパシティーユニットでの書き込み数 は 1 秒あたり 1 回になります。たとえば、テーブルに 1 秒あたり 100 項目を書き込み、項目のサイズ が 512 バイトであるとします。このシナリオでは、書き込みごとに 1 つのプロビジョニングされた書 き込みキャパシティーユニットが必要です。これを判断するには、オペレーションの項目サイズを 1 KB で除算し、次に最も近い整数に切り上げます。 512 bytes / 1 KB = 0.5 --> 1 このシナリオでは、テーブルのプロビジョニングされた書き込みスループットを 100 書き込みキャパ シティーユニットに設定する必要があります。 API Version 2012-08-10 18 Amazon DynamoDB 開発者ガイド パーティションとデータ分散 1 write capacity unit per item × 100 writes per second = 100 write capacity units 項目が 1 KB より大きい場合は、項目サイズを次の 1 KB 境界に切り上げる必要があります。たとえ ば、1 秒あたり 10 個の書き込みを実行し、項目のサイズが 1.5 KB であるとします。最初に、次に示 すように項目あたりの必要な書き込みキャパシティーユニットの数を判断し、最も近い整数に切り上 げます。 1.5 KB / 1 KB = 1.5 --> 2 結果は項目あたり 2 つの書き込みキャパシティーユニットになります。ここでは、これを 1 秒あたり の書き込み数で乗算します。 2 write capacity units per item × 10 writes per second = 20 write capacity units したがって、このシナリオではテーブルのプロビジョニングされた書き込みキャパシティーユニット を 20 に設定する必要があります。 1 つの項目を操作するためには、必要に応じて PutItem、UpdateItem、または DeleteItem オペ レーションを使用します。また、BatchWriteItem を使用して、1 つのオペレーションで最大 25 項 目を配置または削除することができます。(BatchWriteItem は PutItem および DeleteItem オペレー ションはサポートしますが、UpdateItem はサポートしないことにご注意ください。) リザーブドキャパシティーの購入 DynamoDB では、「Amazon DynamoDB 料金表」に説明されているように、リザーブドキャパシ ティーを購入することができます。リザーブドキャパシティーでは、1 回限りの前払い料金を支払 い、期間中、最小使用レベルを支払う契約を結びます。読み込みキャパシティーユニットおよび書 き込みキャパシティーユニットを事前に予約することで、オンデマンドのプロビジョニングされたス ループット設定と比べて大幅なコスト削減を実現できます。 リザーブドキャパシティを管理するには、DynamoDB コンソールに移動し、[Reserved Capacity] を 選択します。 Note ユーザーがリザーブドキャパシティーを表示または購入できないようにしながら、コン ソールの他の部分にはアクセスを許可することができます。詳細については、「Amazon DynamoDB に対する認証とアクセスコントロール (p. 460)」の「リザーブドキャパシティの 提供タイプを購入するためのアクセス許可」を参照してください。 パーティションとデータ分散 DynamoDB はデータをパーティションに保存します。パーティションは、Solid State Drive (SSD) に よってバックアップされ、AWS リージョン内の複数のアベイラビリティーゾーン間で自動的にレプ リケートされる、テーブル用のストレージの割り当てです。パーティション管理は完全に DynamoDB によって処理され、お客様はパーティションを管理する必要はありません。 テーブルを作成するときに、テーブルの最初のステータスは CREATING になります。このフェーズの 間に、DynamoDB はテーブルに十分なパーティションを割り当て、プロビジョニングされたスルー プット要件に対応できるようにします。テーブルのステータスが ACTIVE に変わったらテーブルデー タの書き込みと読み取りを開始できます。 API Version 2012-08-10 19 Amazon DynamoDB 開発者ガイド パーティションとデータ分散 DynamoDB は次の状況でテーブルに追加のパーティションを割り当てます。 • テーブルのプロビジョニングされたスループット設定を、既存のパーティションがサポートできる 以上に増やした。 • 既存のパーティションが容量いっぱいになり、より多くのストレージ領域が必要になった。 詳細については、「パーティションの動作について (p. 569)」を参照してください。 パーティション管理は自動的にバックグラウンドで自動的に発生し、アプリケーションに対して透過 的です。テーブルは利用可能な状態のままで、プロビジョニングされたスループット要件を完全にサ ポートします。 DynamoDB のインデックスもパーティションで構成されます。インデックスのデータは、基本テーブ ルのデータとは別に保存されますが、インデックスパーティションはテーブルパーティションと同様 に動作します。 データ分散: パーティションキー テーブルにシンプルなプライマリキー (パーティションキーのみ) がある場合、DynamoDB はパーティ ションキーの値に基づいて、各項目を保存および取得します。 DynamoDB は項目をテーブルに書き込むため、パーティションキーの値を内部ハッシュ関数への入力 として使用します。ハッシュ関数からの出力値によって、項目が保存されるパーティションが決まり ます。 テーブルから項目を読み取るには、項目に対するパーティションキーの値を指定する必要がありま す。DynamoDB はこの値をハッシュ関数への入力として使用して、項目が見つかるパーティションを 提供します。 次の図は、複数のパーティションにまたがる Pets という名前のテーブルを示しています。テーブル のプライマリキーは AnimalType です (このキー属性のみが表示されます)。DynamoDB はそのハッ シュ関数を使用して、新しい項目を保存する場所を決定します (この場合は文字列 Dog のハッシュ値 に基づく)。項目はソート順に保存されないことに注意してください。各項目の場所は、そのパーティ ションキーのハッシュ値によって決まります。 API Version 2012-08-10 20 Amazon DynamoDB 開発者ガイド パーティションとデータ分散 Note DynamoDB は、パーティション数にかかわらず、テーブルのパーティションにまたがる項目 の均一な分散に対して最適化されません。テーブルの項目数に対して大きな個別の値を持つ ことができるパーティションキーを選択することをお勧めします。詳細については、「テー ブルの操作のガイドライン (p. 566)」を参照してください。 データ分散: パーティションキーおよびソートキー テーブルに複合プライマリキー (パーティションキーとソートキー) がある場合、DynamoDB は「デー タ分散: パーティションキー (p. 20)」に説明されているのと同じ方法でパーティションキーのハッ シュ値を計算します。ただし、パーティションキーの値が同じすべての項目は、ソートキー値によっ て並べ替えられて物理的に近くに配置されます。 テーブルに項目を書き込むため、DynamoDB はパーティションキーのハッシュ値を計算し、項目を含 めるパーティションを決定します。そのパーティションで、パーティションキーの値が同じ複数の項 目がある可能性があるため、DynamoDB は同じパーティションキーを持つ項目をソートキーで昇順に ソートして保存します。 テーブルから項目を読み込むには、パーティションキーの値とソートキーの値を指定する必要があり ます。DynamoDB は、パーティションキーのハッシュ値を計算し、項目が見つかるパーティションを 提供します。 目的の項目に同じパーティションキー値がある場合、単一の操作 (Query) でテーブルから複数の項 目を読み取ることができます。DynamoDB はそのパーティションキー値を持つすべての項目を返し API Version 2012-08-10 21 Amazon DynamoDB 開発者ガイド パーティションとデータ分散 ます。オプションでソートキーに条件を適用し、特定範囲内の値を持つ項目だけを返すことができま す。 Pets テーブルに、AnimalType (パーティションキー) と Name (ソートキー) で構成される複合プライ マリキーがあるとします。次の図は、パーティションキー値が Dog で、ソートキー値が Fido の項目 を書き込む DynamoDB を示しています。 DynamoDB は、Pets テーブルから同じ項目を読み取るため、ハッシュ値 Dog を計算し、これらの 項目が保存されたパーティションを提供します。次に、DynamoDB は、Fido が見つかるまでソート キーの属性値をスキャンします。 AnimalType が Dog のすべての項目を読み込むには、ソートキーの条件を指定しないで Query オペ レーションを発行できます。デフォルトでは、項目は保存されている順序 (つまり、ソートキーによっ て昇順でソート) で返されます。オプションで、代わりに降順をリクエストできます。 Dog 項目の一部のみにクエリを実行するには、ソートキーに条件を適用できます (たとえば、Dog が Name~A の範囲内である K 項目のみ)。 Note DynamoDB テーブルには、パーティションキーの値ごとに個別のソートキー値の数に上限は ありません。Dog テーブルに数十億の Pets 項目を保存する必要がある場合、DynamoDB は 自動的に十分なストレージを割り当てて、この要件に対応します。 API Version 2012-08-10 22 Amazon DynamoDB 開発者ガイド SQL から NoSQL へ SQL から NoSQL へ アプリケーション開発者なら、リレーショナルデータベース管理システム (RDBMS) および構造化ク エリ言語 (SQL) を使用した経験があるかもしれません。 Amazon DynamoDB を使い始めると、多く の類似点があると同時に、異なる点も多くあることに気づきます。 このセクションでは、SQL ステー トメントを同等の DynamoDB オペレーションと比較、対比しながら、一般的なデータベースタスク について説明します。 NoSQL は、可用性が高く、スケーラブルで、高パフォーマンス用に最適化された、非リレーショナル データベースシステムについて説明するのに使用される用語です。 NoSQL データベース (DynamoDB など) は、リレーショナルモデルの代わりに、キーと値のペアやドキュメントストレージなど、データ 管理のための代替モデルを使用します。 詳細については、http://aws.amazon.com/nosql をご覧くださ い。 Note このセクションの SQL の例は、MySQL のリレーショナルデータベース管理システムと互換 性があります。 このセクションの DynamoDB 例では、JSON 形式のオペレーションのパラメーターと共に DynamoDB オペレーションの名前を表示します。 これらのオペレーションを使用するコード サンプルについては、Amazon DynamoDB 入門ガイド を参照してください。 トピック • SQL か NoSQL か (p. 23) • データベースにアクセスする (p. 25) • テーブルの作成 (p. 26) • テーブルに関する情報の取得 (p. 28) • テーブルへのデータの書き込み (p. 29) • テーブルからデータを読み込む (p. 32) • インデックス管理 (p. 37) • テーブルのデータ変更 (p. 40) • テーブルからデータを削除する (p. 42) • テーブルの削除 (p. 43) SQL か NoSQL か 現在のアプリケーションには今までになく厳しい要件があります。 たとえば、あるオンラインゲーム を、小数のユーザーおよび非常に小さいデータ量で開始するかもしれません。 しかし、ゲームが成功 すれば、それは基盤となるデータベース管理システムのリソースを簡単に上回ります。 ウェブベース のアプリケーションに、数百、数千、数百万の同時ユーザーがいて、テラバイトあるいはそれ以上の 新しいデータが毎日生成される、というのはよくあることです。 そのようなアプリケーションのデー タベースの場合は、1 秒あたり数万 (あるいは数十万) の読み取り/書き込みの処理が必要です。 Amazon DynamoDB は、これらのワークロードに適しています。 開発者として、少量のプロビジョニ ングされたスループットで開始し、アプリケーションの人気が出てくるにつれて、徐々に増加させる ことができます。 DynamoDB は、大量のデータや多数のユーザーの処理をシームレスにスケーリン グできます。 次の表はリレーショナルデータベース管理システム (RDBMS) と DynamoDB の、高レベルな相違点を 示します。 API Version 2012-08-10 23 Amazon DynamoDB 開発者ガイド SQL か NoSQL か 特徴 リレーショナルデータベース管 理システム (RDBMS) Amazon DynamoDB 最適なワークロード アドホッククエリ、データウェ アハウス、OLAP (オンライン 分析処理)。 ソーシャルネットワーク、ゲー ム、メディア共有、IoT (Internet of Things) を含む、ウェブス ケールアプリケーションです。 データモデル リレーショナルモデルには、 データを、テーブル、行、列 に正規化する、明確に定義さ れたスキーマが必要です。 さ らに、関係のすべては、テーブ ル、列、インデックスおよび他 のデータベースのエレメント間 で定義されます。 DynamoDB はスキーマレスで す。 すべてのテーブルに、各 データ項目を一意に識別する プライマリキーが必要ですが、 他の非キー属性のような制約 はありません。 DynamoDB は、JSON ドキュメントを含む 構造化データまたは半構造化 データを管理できます。 データアクセス SQL (構造化クエリ言語) は、 データを保存および取得するた めの基準です。 リレーショナ ルデータベースにはデータベー ス駆動型アプリケーションの開 発を簡素化するためのツールが 豊富ですが、これらのツールは すべて、SQL を使用します。 AWS マネジメントコンソール または AWS CLI を使用して DynamoDB を操作し、アドホッ クタスクを実行できます。 ア プリケーションでは、オブジェ クトベースでドキュメント中 心、または低レベルのインター フェイスを使用しながら、AWS Software Development Kit (SDK) を活用し、DynamoDB を操作で きます。 パフォーマンス リレーショナルデータベース は、ストレージに最適化されて いますので、パフォーマンスは 通常、ディスクサブシステムに よって異なります。 開発者と データベース管理者は、ピーク パフォーマンスを達成するため に、クエリ、インデックスおよ びテーブルの構造を最適化する 必要があります。 DynamoDB は、コンピューティ ングに最適化されていますの で、パフォーマンスは主に、 基盤となるハードウェアとネッ トワークレイテンシーの機能で す。 マネージド型サービスとし て、DynamoDB は、これらの実 装の詳細からアプリケーション を隔離し、堅牢で高パフォーマ ンスなアプリケーションの設計 と構築に集中できるようにしま す。 スケーリング より高速なハードウェアでス ケールアップするのが最も簡単 です。 データベーステーブル が分散システムの複数のホスト にまたがることは可能ですが、 この場合、追加の投資が必要 です。 リレーショナルデータ ベースは、スケーラビリティに 上限を課すファイルの数とサイ ズが最大サイズです。 DynamoDB は、ハードウェア の分散型クラスターを使用して スケールアウトできるように設 計されています。 この設計によ り、レイテンシーの増加なしで スループットを強化することが できます。 顧客がスループット 要件を指定すると、DynamoDB は、その要件に対応するため に十分なリソースを割り当てま す。 テーブル単位の項目数、お よびそのテーブルの合計サイズ に上限はありません。 API Version 2012-08-10 24 Amazon DynamoDB 開発者ガイド データベースにアクセスする データベースにアクセスする アプリケーションがデータベースにアクセスする前に、そのアプリケーションがデータベースを使用 する権限があることが認証され、アプリケーションが認可されているアクションのみを実行できるよ うに承認される必要があります。 次の図は、クライアントとリレーショナルデータベースおよび DynamoDB とのやり取りを示しま す。 次の表にクライアントのやり取りのタスクについての詳細があります。 特徴 リレーショナルデータベース管 理システム (RDBMS) Amazon DynamoDB データベースにアクセスするた めのツール ほとんどのリレーショナルデー タベースは、コマンドラインイ ンターフェース (CLI) を提供し ており、アドホックな SQL ス テートメントを入力して、結果 をすぐに見ることができます。 ほとんどの場合、アプリケー ションコードを書き込みます。 AWS マネジメントコンソール または AWS Command Line Interface (AWS CLI) を使用し て、アドホックなリクエストを DynamoDB に送信し、結果を表 示することもできます。 データベースに接続 アプリケーションプログラム は、データベースを使用した ネットワーク接続を確立し、維 持します。 アプリケーション が終了すると、接続を終了しま す。 DynamoDB は、ウェブサービ スで、その操作はステートレ スです。 アプリケーションは 永続的ネットワーク接続を維 持する必要はありません。 代 わりに、DynamoDB の操作は HTTP(S) リクエストおよびレス ポンスを使用して行われます。 認証 アプリケーションが認証される までデータベースに接続できま せん。 RDBMS は認証自体を DynamoDB に対するすべての リクエストは、その特定のリ クエストを認証する暗号署名 API Version 2012-08-10 25 Amazon DynamoDB 開発者ガイド テーブルの作成 特徴 リレーショナルデータベース管 理システム (RDBMS) Amazon DynamoDB 実行できますし、ホストのオペ レーティングシステムやディレ クトリサービスにこのタスクを オフロードすることもできま す。 と共に使用しなければなりませ ん。 AWS SDK は、署名の作成 とリクエストの署名に必要なす べての論理を提供します。 詳 細については、AWS General Reference の AWS API リクエ ストの署名を参照してくださ い。 承認 アプリケーションは承認された アクションのみ実行できます。 データベース管理者またはアプ リケーション所有者は、SQL GRANT および REVOKE ステー トメントを使用して、データ ベースオブジェクト (テーブル など)、データ (テーブル内の行 など)、特定の SQL ステートメ ントを発行する機能へのアクセ スを制御できます。 DynamoDB では、AWS Identity and Access Management (IAM) によって承認が処理されます。 DynamoDB リソース (テーブ ルなど) にアクセス許可を付 与する IAM ポリシーを書き 込み、IAM ユーザーとロー ルがそのポリシーを使用でき るようにします。 IAM はま た、DynamoDB テーブルの個々 のデータ項目のきめ細かなア クセス制御を特徴とします。 詳細については、「Amazon DynamoDB に対する認証とアク セスコントロール (p. 460)」を 参照してください。 リクエストを送信 アプリケーションは、実行する すべてのデータベース操作に対 する SQL ステートメントを発 行します。 SQL ステートメン トを受信すると、RDBMS は構 文を確認し、操作を実行するた めの計画を作成し、計画を実行 します。 アプリケーションは、HTTP(S) リクエストを DynamoDB に 送信 します。 リクエスト には、パラメーターととも に、DynamoDB の名前と実 行する操作が含まれます。 DynamoDB は、リクエストを迅 速に実行します。 レスポンスを受信 RDBMS は SQL ステートメ ントから結果を返します。 エ ラーがある場合は、RDBMS は エラー状況とエラーメッセージ を返します。 DynamoDB は、操作の結果を 含む HTTP(S) レスポンスを 返します。 エラーがある場合 は、DynamoDB は、HTTP エ ラー状況およびエラーメッセー ジを返します。 テーブルの作成 テーブルは、リレーショナルデータベースおよび DynamoDB の基本的なデータ構造です。 リレー ショナルデータベース管理システム (RDBMS) では、作成時に、テーブルのスキーマを定義する必要 があります。 これに対して、DynamoDB テーブルは、プライマリキー以外は schemaless— ですか ら、テーブル作成時に属性やデータ型を定義する必要はありません。 SQL 次の例に示すように、CREATE TABLE ステートメントを使用して、テーブルを作成します。 CREATE TABLE Music ( API Version 2012-08-10 26 Amazon DynamoDB 開発者ガイド テーブルの作成 Artist VARCHAR(20) NOT NULL, SongTitle VARCHAR(30) NOT NULL, AlbumTitle VARCHAR(25), Year INT, Price FLOAT, Genre VARCHAR(10), Tags TEXT, PRIMARY KEY(Artist, SongTitle) ); このテーブルのプライマリキーは、Artist および SongTitle で構成されます。 テーブルの列とデータ型すべて、およびテーブルのプライマリキーを定義する必要があります。 (こ れらの定義は、ALTER TABLE ステートメントを使用して、必要に応じて後で変更することができま す。) 多くの SQL 実装では、CREATE TABLE ステートメントの一部として、テーブルのストレージ仕様を 定義することができます。 他に明記されていない限り、テーブルはデフォルトのストレージ設定で作 成されます。 本稼働環境では、データベース管理者は最適なストレージパラメーターを特定すること もできます。 DynamoDB CreateTable アクションを使用してテーブルを作成し、次に示すように、パラメーターを指定しま す。 { TableName : "Music", KeySchema: [ { AttributeName: "Artist", KeyType: "HASH", //Partition key }, { AttributeName: "SongTitle", KeyType: "RANGE" //Sort key } ], AttributeDefinitions: [ { AttributeName: "Artist", AttributeType: "S" }, { AttributeName: "SongTitle", AttributeType: "S" } ], ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } } このテーブルのプライマリキーは、Artist (パーティションキー) および SongTitle (ソートキー) で構成 されています。 CreateTable に以下のパラメーターを提供する必要があります。 API Version 2012-08-10 27 Amazon DynamoDB 開発者ガイド テーブルに関する情報の取得 • TableName – テーブルの名前. • KeySchema – プライマリキーに使用される属性。 詳細については、「テーブル、項目、属 性 (p. 2)」および「プライマリキー (p. 5)」を参照してください。 • AttributeDefinitions – キースキーマ属性のデータ型。 • ProvisionedThroughput – このテーブルに必要な 1 秒あたりの読み取り/書き込み数。 DynamoDB は、スループット要件を常に満たすように、十分なストレージとシステムリソースを 確保しています。 これらは、UpdateTable アクションを使用して、必要に応じて後で変更できま す。 DynamoDB がストレージ割り当てを完全に管理しているため、テーブルのストレージ要件を 指定する必要はありません。 Note CreateTable を使用したコードサンプルについては、Amazon DynamoDB 入門ガイド を参 照してください。 テーブルに関する情報の取得 テーブルが仕様に従って作成されたことを確認できます。 リレーショナルデータベースでは、すべて テーブルのスキーマが表示されます。 DynamoDB テーブルはスキーマレスであるため、プライマリ キー属性のみが表示されます。 SQL ほとんどのリレーショナルデータベース管理システム (RDBMS) では、列、データ型、プライマリ キー定義などのテーブルの構造を説明できます。 SQL にはこれを行うための標準的な方法はありませ ん。 ただし、データベースシステムの多くが DESCRIBE コマンドを提供しています。 MySQL からの 例を示します。 DESCRIBE Music; すべての列名、データ型、サイズを含むテーブルの構造を返します。 +------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+-------+ | Artist | varchar(20) | NO | PRI | NULL | | | SongTitle | varchar(30) | NO | PRI | NULL | | | AlbumTitle | varchar(25) | YES | | NULL | | | Year | int(11) | YES | | NULL | | | Price | float | YES | | NULL | | | Genre | varchar(10) | YES | | NULL | | | Tags | text | YES | | NULL | | +------------+-------------+------+-----+---------+-------+ このテーブルのプライマリキーは、Artist および SongTitle で構成されます。 DynamoDB DynamoDB には、同様の DescribeTable アクションがあります。 次に示すように、唯一のパラ メーターは、テーブル名です。 { API Version 2012-08-10 28 Amazon DynamoDB 開発者ガイド テーブルへのデータの書き込み TableName : "Music" } DescribeTable からの返信は、次のようになります。 { "Table": { "AttributeDefinitions": [ { "AttributeName": "Artist", "AttributeType": "S" }, { "AttributeName": "SongTitle", "AttributeType": "S" } ], "TableName": "Music", "KeySchema": [ { "AttributeName": "Artist", "KeyType": "HASH" //Partition key }, { "AttributeName": "SongTitle", "KeyType": "RANGE" //Sort key } ], ... DescribeTable は、情報も返します。 テーブル、プロビジョニングされたスループット設定、概算 項目数とそのほかのメタデータのインデックスについて。 テーブルへのデータの書き込み リレーショナルデータベースのテーブルには、データの行が含まれます。 行は列で構成されます。 DynamoDB テーブルには、項目が含まれます。 項目は属性で構成されます。 このセクションでは、テーブルに 1 つの行 (または項目) を書き込む方法を説明します。 SQL リレーショナルデータベースのテーブルは、行と列で構成される、2 つのディメンションのデータ構 造です。 一部のデータベース管理システムは、通常、ネイティブ JSON または XML データ型を使用 する半構造化データのサポートを提供します。 ただし、実装の詳細はベンダー間で変わります。 SQL では、INSERT ステートメントを使用して、テーブルに行を追加します。 INSERT INTO Music (Artist, SongTitle, AlbumTitle, Year, Price, Genre, Tags) VALUES( 'No One You Know', 'Call Me Today', 'Somewhat Famous', API Version 2012-08-10 29 Amazon DynamoDB 開発者ガイド テーブルへのデータの書き込み 2015, 2.14, 'Country', '{"Composers": ["Smith", "Jones","Davis"],"LengthInSeconds": 214}' ); このテーブルのプライマリキーは、Artist および SongTitle で構成されます。 これらの列の値を指定す る必要があります。 Note この例では、タグ列を使用して、音楽テーブル内の曲に関する半構造化データを保存しま す。 タグ列を MySQL で 65535 文字まで格納できる TEXT 型として定義しました。 DynamoDB Amazon DynamoDB では、PutItem アクションを使用して、テーブルに項目を追加します。 { TableName: "Music", Item: { "Artist":"No One You Know", "SongTitle":"Call Me Today", "AlbumTitle":"Somewhat Famous", "Year": 2015, "Price": 2.14, "Genre": "Country", "Tags": { "Composers": [ "Smith", "Jones", "Davis" ], "LengthInSeconds": 214 } } } このテーブルのプライマリキーは、Artist および SongTitle で構成されます。 これらの属性の値を指定 する必要があります。 この PutItem 例に関する主要事項を示します。 • DynamoDB は、JSON を使用してドキュメントのネイティブサポートを提供します。 これにより DynamoDB はタグなどの半構造化データを保存するのに最適になります。 また、JSON ドキュメン ト内からデータを取得および操作できます。 • 音楽テーブルには、プライマリキー (Artist および SongTitle) 以外には事前定義された属性はありま せん。 • ほとんどの SQL データベースはトランザクション指向です。 INSERT ステートメントを発行す ると、データ変更は、COMMIT ステートメントを発行するまで永続的ではありません。 Amazon DynamoDB によって、PutItem アクションの効果は、DynamoDB が HTTP 200 ステータスコード (OK) で応答する場合、永続的になります。 Note PutItem を使用したコードサンプルについては、Amazon DynamoDB 入門ガイド を参照し てください。 API Version 2012-08-10 30 Amazon DynamoDB 開発者ガイド テーブルへのデータの書き込み 次に、PutItem の他の例をいくつか示します。 { TableName: "Music", Item: { "Artist": "No One You Know", "SongTitle": "My Dog Spot", "AlbumTitle":"Hey Now", "Price": 1.98, "Genre": "Country", "CriticRating": 8.4 } } { TableName: "Music", Item: { "Artist": "No One You Know", "SongTitle": "Somewhere Down The Road", "AlbumTitle":"Somewhat Famous", "Genre": "Country", "CriticRating": 8.4, "Year": 1984 } } { TableName: "Music", Item: { "Artist": "The Acme Band", "SongTitle": "Still In Love", "AlbumTitle":"The Buck Starts Here", "Price": 2.47, "Genre": "Rock", "PromotionInfo": { "RadioStationsPlaying":[ "KHCR", "KBQX", "WTNR", "WJJH" ], "TourDates": { "Seattle": "20150625", "Cleveland": "20150630" }, "Rotation": "Heavy" } } } { TableName: "Music", Item: { "Artist": "The Acme Band", "SongTitle": "Look Out, World", "AlbumTitle":"The Buck Starts Here", "Price": 0.99, "Genre": "Rock" } API Version 2012-08-10 31 Amazon DynamoDB 開発者ガイド テーブルからデータを読み込む } Note PutItem に加えて、Amazon DynamoDB は、同時に複数の項目に書き込むための BatchWriteItem アクションもサポートします。 テーブルからデータを読み込む SQL では、SELECT ステートメントを使用して、テーブルから 1 つ以上の行を取得します。 WHERE 句を使用して、返されたデータを調べます。 DynamoDB は、データ読み取りのために次のオペレーションを提供します。 • GetItem – テーブルから単一の項目を取り出します。これは、項目の物理的な場所に直接ア クセスできるため、単一の項目を読み取るのには最も効率的な方法です。 (DynamoDB はま た、BatchGetItemオペレーションを提供するため、単一の操作で、最大 100GetItem 呼び出しを 実行できます。) • Query – 特定のパーティションキーがあるすべての項目を取り出します。これらの項目内では、 ソートキーに条件を適用し、データのサブセットのみ取得できます。 Query は、データが格納さ れているパーティションに、すばやく効率的にアクセスできます。 (詳しくは、パーティションと データ分散 (p. 19) を参照してください)。 • Scan – 指定されたテーブルで、すべての項目を取り出します。 (大量のリソースシステムを消費す るため、このオペレーションは大きなテーブルでは使用しないでください。) Note リレーショナルデータベースでは、SELECT ステートメントを使用して、複数のテーブルから データを結合し、その結果を返すことができます。 結合は、リレーショナルモデルにおいて 必須です。 結合を効率的に実行するために、データベースおよびアプリケーションは、継続 的にパフォーマンスの調整をする必要があります。 DynamoDB は、非リレーショナル NoSQL データベースのため、テーブルの結合はサポート されません。 その代わり、アプリケーションは一度に 1 つのテーブルからデータを読み込み ます。 次のセクションでは、データを読み込むための異なるユースケースおよびこれらのタスクをリレー ショナルデータベースと DynamoDB を使って実行する方法を説明します。 トピック • プライマリキーを使用して項目を読み取る (p. 32) • テーブルに対するクエリの実行 (p. 34) • テーブルをスキャンする (p. 36) プライマリキーを使用して項目を読み取る データベースの一般的なアクセスパターンの 1 つは、テーブルから単一項目を読み取ることです。 目 的の項目のプライマリキーを指定する必要があります。 SQL SQL では、SELECT ステートメントを使用して、テーブルからデータを取得します。 結果の 1 つ以上 の列 (* オペレーター を使用すれば、すべて) をリクエストできます。 WHERE 句は返される行を決定 します。 API Version 2012-08-10 32 Amazon DynamoDB 開発者ガイド テーブルからデータを読み込む 音楽テーブルから 1 つの行を取得する SELECT ステートメントを次に示します。 WHERE 句はプライ マリキー値を指定します。 SELECT * FROM Music WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today' 列のサブセットのみを取得するようにこのクエリを変更できます。 SELECT AlbumTitle, Year, Price FROM Music WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today' このテーブルのプライマリキーが、Artist および SongTitle で構成されていることに注意してくださ い。 DynamoDB DynamoDB は、プライマリキーにより項目を取得するための GetItem アクションを提供します。 GetItem は、項目の物理的な場所への直接アクセスを提供するため非常に能率的です。 (詳しく は、パーティションとデータ分散 (p. 19) を参照してください)。 デフォルトでは、GetItem は、すべての属性を含む項目全体を返します。 { TableName: "Music", Key: { "Artist": "No One You Know", "SongTitle": "Call Me Today" } } 一部の属性のみが返されるように、ProjectionExpression パラメーターを追加できます。 { TableName: "Music", Key: { "Artist": "No One You Know", "SongTitle": "Call Me Today" }, "ProjectionExpression": "AlbumTitle, Year, Price" } このテーブルのプライマリキーが、Artist および SongTitle で構成されていることに注意してくださ い。 DynamoDB GetItem アクションは非常に効率的です。プライマリキー値を使用して、該当する項目 の正確な格納場所を特定し、そこから直接取得します。 SQL SELECT ステートメントは、プライマリ キー値によって項目を取得する場合、同様に効率的です。 SQL SELECT ステートメントは多くの種類のクエリおよびテーブルスキャンをサポートします。 DynamoDB は Query および Scanアクションで、同様の機能を提供しています。テーブルに対するク エリの実行 (p. 34) および テーブルをスキャンする (p. 36) を参照してください。 SQL SELECT ステートメントは、テーブルの結合を実行でき、同時に複数のテーブルからデータを取 得できます。 データベーステーブルが正規化され、テーブル間の関係が明確である場合、結合は最も API Version 2012-08-10 33 Amazon DynamoDB 開発者ガイド テーブルからデータを読み込む 効果的です。 ただし、1 つの SELECTステートメントであまりに多くのテーブルを結合すると、アプ リケーションパフォーマンスが影響を受けます。 データベースレプリケーション、マテリアライズド ビュー、またはクエリの書き換えを使用して、このような問題を回避できます。 DynamoDB は、非リレーショナルデータベースです。 したがって、テーブルの結合はサポートされ ません。 リレーショナルデータベースから既存のアプリケーションを DynamoDB に移行する場合、 結合の必要を排除するためデータモデルを非正規化する必要があります。 Note GetItem を使用したコードサンプルについては、Amazon DynamoDB 入門ガイド を参照し てください。 テーブルに対するクエリの実行 もう 1 つの一般的なアクセスパターンは、クエリ条件に基づき、テーブルから複数の項目を読み込む ことです。 SQL SQL SELECT ステートメントは、キー列、非キー列、または任意の組み合わせに対してクエリを実行 できます。 WHERE句は、次の例に示すように、返される行を決定します。 /* Return a single song, by primary key */ SELECT * FROM Music WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today'; /* Return all of the songs by an artist */ SELECT * FROM Music WHERE Artist='No One You Know'; /* Return all of the songs by an artist, matching first part of title */ SELECT * FROM Music WHERE Artist='No One You Know' AND SongTitle LIKE 'Call%'; /* Return all of the songs by an artist, with a particular word in the title... ...but only if the price is less than 1.00 */ SELECT * FROM Music WHERE Artist='No One You Know' AND SongTitle LIKE '%Today%' AND Price < 1.00; このテーブルのプライマリキーが、Artist および SongTitle で構成されていることに注意してくださ い。 DynamoDB DynamoDB Query アクションにより、同様の方法でデータを取得できます。 Queryアクションは、 データが保存されている物理的な場所にすばやく効率的にアクセスすることができます。 (詳しく は、パーティションとデータ分散 (p. 19) を参照してください)。 API Version 2012-08-10 34 Amazon DynamoDB 開発者ガイド テーブルからデータを読み込む Query は、複合プライマリキー (パーティションキーとソートキー) のある任意のテーブルで使用でき ます。 パーティションキーに対して等価条件を指定する必要があります。必要に応じて、ソートキー に対して別の条件を指定できます。 KeyConditionExpression パラメーターは、クエリを実行するキー値を指定します。 オプションの FilterExpression を使用して、結果が返される前に、そこから特定の項目を削除できます。 DynamoDB では、式パラメーター (KeyConditionExpression および FilterExpressionなど) で ExpressionAttributeValues をプレースホルダーとして使用する必要があります。 これは、実行 時に、実際の値を SELECT ステートメントに置き換えるリレーショナルデータベースでの バインド変 数の使用と似ています。 このテーブルのプライマリキーが、Artist および SongTitle で構成されていることに注意してくださ い。 次に DynamoDB の Query 例を示します。 // Return a single song, by primary key { TableName: "Music", KeyConditionExpression: "Artist = :a and SongTitle = :t", ExpressionAttributeValues: { ":a": "No One You Know", ":t": "Call Me Today" } } // Return all of the songs by an artist { TableName: "Music", KeyConditionExpression: "Artist = :a", ExpressionAttributeValues: { ":a": "No One You Know" } } // Return all of the songs by an artist, matching first part of title { TableName: "Music", KeyConditionExpression: "Artist = :a and begins_with(SongTitle, :t)", ExpressionAttributeValues: { ":a": "No One You Know", ":t": "Call" } } // Return all of the songs by an artist, with a particular word in the title... // ...but only if the price is less than 1.00 { TableName: "Music", KeyConditionExpression: "Artist = :a and contains(SongTitle, :t)", API Version 2012-08-10 35 Amazon DynamoDB 開発者ガイド テーブルからデータを読み込む FilterExpression: "price < :p", ExpressionAttributeValues: { ":a": "No One You Know", ":t": "Today", ":p": 1.00 } } Note Query を使用したコードサンプルについては、Amazon DynamoDB 入門ガイド を参照してく ださい。 テーブルをスキャンする SQL では、WHERE 句なしの SELECT ステートメントは、テーブルのすべての行を返します。 DynamoDB では、スキャンオペレーションが同じことを行います。 どちらの場合も、全ての、また は一部の項目を取得できます。 SQL または NoSQL データベースのいずれを使用するにしても、スキャンは大量のシステムリソース を消費するので、控え目に使用する必要があります。 スキャンが適切 (小さなテーブルをスキャンす るなど) または不可避 (データの一括エクスポートの実行など) な場合はあります。 しかし、一般的な ルールとして、スキャンを実行しないようアプリケーションを設計する必要があります。 SQL SQL では WHERE 句を指定せずに、SELECT ステートメントを使用してテーブルをスキャンし、データ のすべてを取得することができます。 結果の 1 つ以上の列をリクエストできます。 または、ワイル ドカード文字「*」を使用するなら、すべての列をリクエストできます。 次に例を示します。 /* Return all of the data in the table */ SELECT * FROM Music; /* Return all of the values for Artist and Title */ SELECT Artist, Title FROM Music; DynamoDB DynamoDB は、同じように機能する Scan アクションを提供します。 次に例を示します。 // Return all of the data in the table { TableName: "Music" } // Return all of the values for Artist and Title { TableName: "Music", ProjectionExpression: "Artist, Title" } API Version 2012-08-10 36 Amazon DynamoDB 開発者ガイド インデックス管理 Scan アクションは、結果に表示しない項目を破棄する FilterExpression パラメーターも提供しま す。 FilterExpression は、テーブル全体がスキャンされた後で、結果が返される前に適用されま す。 (これは大きなテーブルでは推奨されません。ごくわずかな一致する項目のみが返ってくる場合で も、Scan 全体にたいして課金されます。) Note Scan を使用するコードサンプルに関しては、Amazon DynamoDB 入門ガイド を参照してく ださい。 インデックス管理 インデックスは代替のクエリパターンへのアクセスを付与し、クエリを高速化できます。 このセク ションでは、SQL と DynamoDB におけるインデックスの作成と使用を比較します。 リレーショナルデータベースまたは DynamoDB のいずれを使用するにしても、インデックスの作成 は慎重に判断する必要があります。 テーブルに書き込みが発生するたびに、テーブルのインデックス はすべて、更新する必要があります。 大きなテーブルでの書き込み量が多い環境では、大量のシステ ムリソースを消費する可能性があります。 読み取り専用または読み取りがほとんどの環境では、これ は大きな問題にはなりません。ただし、インデックスがアプリケーションによって実際に使用されて おり、ただ容量を取っていることがないよう確認する必要があります。 トピック • インデックスの作成 (p. 37) • インデックスのクエリの実行およびスキャン (p. 39) インデックスの作成 SQL リレーショナルデータベースでは、インデックスは、テーブルの異なる列に対して高速にクエリを実 行できるデータ構造です。 CREATE INDEXSQL ステートメントを使用して、既存のテーブルにイン デックスが追加し、インデックスを作成する列を指定します。 インデックスの作成後は、通常どおり テーブルのデータにクエリを実行できますが、テーブル全体をスキャンする代わりに、テーブルの指 定された行を迅速に検索するため、データベースがインデックスを使用することができます。 インデックスの作成後は、データベースが維持します。 テーブルのデータを変更した場合は、イン デックスが自動的に変更され、テーブル内の変更を反映します。 MySQL では、このようなインデックスを作成できます。 CREATE INDEX GenreAndPriceIndex ON Music (genre, price); DynamoDB DynamoDB では、同様の目的のため、セカンダリインデックス を作成し、使用できます。 DynamoDB のインデックスはリレーショナルな対応物とは異なります。 セカンダリインデックス を 作成すると、パーティションキーおよびソートキーのように、キー属性を指定する必要があります。 セカンダリインデックス を作成した後、テーブルを使ってするのと同じように、Query を実行または Scan できます。 DynamoDB に、クエリオプティマイザはありませんので、セカンダリインデックス は、Query を実行するか、Scan するときにのみ使用されます。 DynamoDB では、次の 2 種類のインデックスをサポートしています。 API Version 2012-08-10 37 Amazon DynamoDB 開発者ガイド インデックス管理 • グローバルセカンダリインデックス - インデックスのプライマリキーは、テーブルからの任意の 2 つの属性になります。 • ローカルセカンダリインデックス - インデックスのパーティション キーは、テーブルのパーティ ションキーと同じである必要があります。 ただし、ソートキーは、他の任意の属性にすることがで きます。 DynamoDB を使えば、セカンダリインデックス のデータは結果的にテーブルと整合性が取れます。 テーブルまたは local secondary index. での強い整合性を持つ Query または Scan アクションをリク エストできます。 ただし、グローバルセカンダリインデックスは結果整合性のみをサポートします。 UpdateTable アクションを使用し、GlobalSecondaryIndexUpdates: を指定して、既存のテーブ ルに グローバルセカンダリインデックス を追加できます。 { TableName: "Music", AttributeDefinitions:[ {AttributeName: "Genre", AttributeType: "S"}, {AttributeName: "Price", AttributeType: "N"} ], GlobalSecondaryIndexUpdates: [ { Create: { IndexName: "GenreAndPriceIndex", KeySchema: [ {AttributeName: "Genre", KeyType: "HASH"}, //Partition key {AttributeName: "Price", KeyType: "RANGE"}, //Sort key ], Projection: { "ProjectionType": "ALL" }, ProvisionedThroughput: { "ReadCapacityUnits": 1,"WriteCapacityUnits": 1 } } } ] } UpdateTable に以下のパラメーターを提供する必要があります。 • TableName - インデックスが関連付けられるテーブル。 • AttributeDefinitions - インデックスのキースキーマ属性用のデータ型。 • GlobalSecondaryIndexUpdates - 作成するインデックスに関する詳細。 • IndexName - インデックスの名前。 • KeySchema - インデックスプライマリキーに使用する属性。 • Projection - テーブルからインデックスにコピーされる属性。 この場合、ALL は、すべての属 性がコピーされることを意味します。 • ProvisionedThroughput - このインデックスに必要な 1 秒あたりの読み取り/書き込み数。 (こ れは、テーブルのプロビジョニングされたスループット設定とは異なります。) このオペレーションの一部は、テーブルから新しいインデックスにデータをバックフィリングするこ とを含みます。 バックフィリング中、テーブルは使用可能なままになります。 ただし、インデックス は Backfilling 属性が true から false に変わるまで、準備ができていません。 DescribeTable ア クションを使用して、この属性を表示できます。 API Version 2012-08-10 38 Amazon DynamoDB 開発者ガイド インデックス管理 Note UpdateTable を使用するコードサンプルに関しては、Amazon DynamoDB 入門ガイド を参 照してください。 インデックスのクエリの実行およびスキャン SQL リレーショナルデータベースでは、インデックスを直接使用しません。 代わりに、SELECT ステート メントの発行により、テーブルでクエリを実行し、クエリオプティマイザは任意のインデックスを利 用できます。 クエリオプティマイザは、使用できるインデックスを評価し、クエリを高速化するためにそれらを使 用できるかを決定するリレーショナルデータベース管理システム (RDBMS) のコンポーネントです。 クエリを高速化するためにインデックスが使用できる場合、RDBMS は最初にインデックスにアクセ スし、それを使用してテーブルのデータを特定します。 GenreAndPriceIndex を使用してパフォーマンスを向上できる SQL ステートメントを次に示します。 ここでは、音楽テーブルに十分なデータがあり、クエリオプティマイザが、テーブル全体にスキャン するのではなく、このインデックスを使用することを前提にします。 /* All of the rock songs */ SELECT * FROM Music WHERE Genre = 'Rock'; /* All of the cheap country songs */ SELECT Artist, SongTitle, Price FROM Music WHERE Genre = 'Country' AND Price < 0.50; DynamoDB DynamoDB では、テーブルで実行するのと同じように、インデックスに対して直接 Query オペレー ションを実行します。 TableName と IndexName の両方を指定する必要があります。 以下に、DynamoDB の GenreAndPriceIndex に対するクエリをいくつか示します。 (このインデック スのキースキーマは、ジャンルと価格で構成されています。) // All of the rock songs { TableName: "Music", IndexName: "GenreAndPriceIndex", KeyConditionExpression: "Genre = :genre", ExpressionAttributeValues: { ":genre": "Rock" }, }; // All of the cheap country songs { TableName: "Music", API Version 2012-08-10 39 Amazon DynamoDB 開発者ガイド テーブルのデータ変更 IndexName: "GenreAndPriceIndex", KeyConditionExpression: "Genre = :genre and Price < :price", ExpressionAttributeValues: { ":genre": "Country", ":price": 0.50 }, ProjectionExpression: "Artist, SongTitle, Price" }; この例では ProjectionExpression を使用して、属性すべてではなく、一部のみを結果に表示する ことを示します。 また、テーブルで実行するのと同じように、セカンダリインデックス で Scan オペレーションを実行 できます。 次に示すのは、GenreAndPriceIndex に対するスキャンです。 // Return all of the data in the index { TableName: "Music", IndexName: "GenreAndPriceIndex" } テーブルのデータ変更 SQL 言語はデータ変更のための UPDATE ステートメントを提供します。 DynamoDB は、UpdateItem オペレーションを使用して、同じようなタスクを実行します。 SQL SQL では、UPDATE ステートメントを使用して、1 つ以上の行を変更します。 SET 句は、1 つ以上の 行に新しい値を指定し、WHERE 句は変更する行を決定します。 例を示します。 UPDATE Music SET RecordLabel = 'Global Records' WHERE Artist = 'No One You Know' AND SongTitle = 'Call Me Today'; WHERE 句に行が一致しない場合、UPDATE ステートメントは何も実行しません。 DynamoDB DynamoDB では、UpdateItem アクションを使用して、単一の項目を変更します。 (複数の項目を変 更する場合は、複数の UpdateItem オペレーションを使用する必要があります。) 例を示します。 { TableName: "Music", Key: { "Artist":"No One You Know", "SongTitle":"Call Me Today" }, UpdateExpression: "SET RecordLabel = :label", ExpressionAttributeValues: { ":label": "Global Records" } API Version 2012-08-10 40 Amazon DynamoDB 開発者ガイド テーブルのデータ変更 } 変更する項目の Key 属性と、属性値を指定する UpdateExpression を指定する必要があります。 UpdateItem は、個々の属性を置き換えるのではなく、項目全体を置き換えます。 UpdateItem は、「アップサート」操作のように動作します。項目はテーブルにある場合更新されま すが、更新されない場合は、新しい項目が追加されます (挿入)。 UpdateItem は、条件付き書き込みをサポートしており、特定の ConditionExpression が true と 評価された場合のみ、オペレーションが成功します。 たとえば、次の UpdateItem アクションは、 曲の価格が 2.00 以上でない限り、更新を実行しません。 { TableName: "Music", Key: { "Artist":"No One You Know", "SongTitle":"Call Me Today" }, UpdateExpression: "SET RecordLabel = :label", ConditionExpression: "Price >= :p", ExpressionAttributeValues: { ":label": "Global Records", ":p": 2.00 } } UpdateItem はまた、アトミックカウンター、または増加減少する数値型の属性をサポートしていま す。 アトミックカウンターは多くの点で SQL データベースのシーケンスジェネレーター、IDENTITY 列、または自動インクリメントフィールドと似ています。 曲が再生された回数を追跡するために新しい属性 (Plays) を初期化する UpdateItem アクションの例 を次に示します。 { TableName: "Music", Key: { "Artist":"No One You Know", "SongTitle":"Call Me Today" }, UpdateExpression: "SET Plays = :val", ExpressionAttributeValues: { ":val": 0 }, ReturnValues: "UPDATED_NEW" } ReturnValues パラメーターは、更新された任意の属性の新しい値を返す、UPDATED_NEW に設定さ れています。 この場合は、0 (ゼロ) を返します。 ユーザーがこの曲を再生するたびに、次の UpdateItem アクションを使用して Plays を 1 ずつ増分で きます。 { TableName: "Music", Key: { "Artist":"No One You Know", API Version 2012-08-10 41 Amazon DynamoDB 開発者ガイド テーブルからデータを削除する "SongTitle":"Call Me Today" }, UpdateExpression: "SET Plays = Plays + :incr", ExpressionAttributeValues: { ":incr": 1 }, ReturnValues: "UPDATED_NEW" } Note UpdateItem を使用したコードサンプルについては、Amazon DynamoDB 入門ガイド を参照 してください。 テーブルからデータを削除する SQL では、DELETE ステートメントは、テーブルから 1 つ以上の行を削除します。 DynamoDB は、DeleteItem オペレーションを使用して、一度に 1 つの項目を削除します。 SQL SQL では、DELETE ステートメントを使用して、1 つ以上の行を削除します。 WHERE 句は、変更する 行を決定します。 例を示します。 DELETE FROM Music WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World'; WHERE 句を変更して、複数行を削除できます。 たとえば、次に示すように、特定のアーティストのす べての曲を削除できます。 DELETE FROM Music WHERE Artist = 'The Acme Band' Note WHERE 句を省略すると、データベースはテーブルからすべての行を削除しようとします。 DynamoDB DynamoDB では、DeleteItem アクションを使用して、テーブルからデータを一度に 1 項目ずつ削除 します。 項目のプライマリキー値を指定する必要があります。 例を示します。 { TableName: "Music", Key: { Artist: "The Acme Band", SongTitle: "Look Out, World" } } Note DeleteItem に加えて、Amazon DynamoDB は、同時に複数の項目を削除するための BatchWriteItem アクションをサポートします。 API Version 2012-08-10 42 Amazon DynamoDB 開発者ガイド テーブルの削除 DeleteItem は、条件付き書き込みをサポートしており、特定の ConditionExpression が true と評価された場合のみ、オペレーションが成功します。 たとえば、次の DeleteItem アクションは RecordLabel 属性がある場合のみ項目を削除します。 { TableName: "Music", Key: { Artist: "The Acme Band", SongTitle: "Look Out, World" }, ConditionExpression: "attribute_exists(RecordLabel)" } Note DeleteItem を使用したコードサンプルについては、Amazon DynamoDB 入門ガイド を参照 してください。 テーブルの削除 SQL では、DROP TABLE ステートメントを使用して、テーブルを削除します。 DynamoDB で は、DeleteTable オペレーションを使用します。 SQL 不要になったテーブルを完全に廃棄する場合、SQL の DROP TABLE ステートメントを使用します。 DROP TABLE Music; テーブルは削除された後、復元できません。 (一部のリレーショナルデータベースは DROP TABLE オ ペレーションを取消すことができますが、これはベンダー固有の機能であり、一般的には実装されて いません。) DynamoDB DynamoDB には、同様のアクションがあります。DeleteTable 次の例では、テーブルは完全に削除 されます。 { TableName: "Music" } Note DeleteTable を使用したコードサンプルについては、Amazon DynamoDB 入門ガイド を参 照してください。 API Version 2012-08-10 43 Amazon DynamoDB 開発者ガイド DynamoDB (ダウンロード可 能バージョン) のセットアップ DynamoDB のセットアップ Amazon DynamoDB ウェブサービスに加え、AWS では、コンピュータでローカルに実行できるダウ ンロード可能なバージョンの DynamoDB を提供しています。DynamoDB (ダウンロード可能または ウェブサービス) をセットアップするには、次のセクションを参照してください。 トピック • DynamoDB (ダウンロード可能バージョン) のセットアップ (p. 44) • DynamoDB (ウェブサービス) のセットアップ (p. 48) DynamoDB (ダウンロード可能バージョン) の セットアップ ダウンロード可能なバージョンの DynamoDB では、実際に Amazon DynamoDB ウェブサービスにア クセスせずに、アプリケーションを記述できます。代わりに、データベースはコンピュータ上で自己 完結型となります。 このローカルバージョンの DynamoDB により、プロビジョニングされたスループット、データスト レージ、およびデータ転送料金を節約できます。 また、アプリケーションを開発している間インター ネットに接続しておく必要はありません。 ただし、本稼働環境でアプリケーションをデプロイする場 合、Amazon DynamoDB ウェブサービスを使用できるように簡単な調整を加えることができます。 トピック • DynamoDB のダウンロードと実行 (p. 44) • ローカルエンドポイントの設定 (p. 46) • 使用に関する注意事項 (p. 47) DynamoDB のダウンロードと実行 ダウンロード可能なバージョンの DynamoDB は、実行可能な .jar ファイルとして提供されます。 Windows、Linux、Mac OS X、および Java をサポートする他のプラットフォームで動作します。以 下のステップに従って DynamoDB をコンピューターにダウンロードして実行します。 1. 以下のリンクから無料で DynamoDB をダウンロードします。 API Version 2012-08-10 44 Amazon DynamoDB 開発者ガイド DynamoDB のダウンロードと実行 • .tar.gz 形式: https://s3-us-west-2.amazonaws.com/dynamodb-local/dynamodb_local_latest.tar.gz • .zip 形式: https://s3-us-west-2.amazonaws.com/dynamodb-local/dynamodb_local_latest.zip Important ダウンロード可能なバージョンの DynamoDB は他の場所で入手できる場合もあります が、最新バージョンであることは保証されません。確実に最新バージョンを入手するに は、上に示したいずれかのリンクを使用します。 お使いのコンピュータ上の DynamoDB では、Java Runtime Environment (JRE) バージョ ン 6.x 以降が必要です。それよりも古い JRE バージョンでは動作しません。DynamoDB (ダウンロード可能バージョン) は、AWS Toolkit for Eclipse の一部としても入手できま す。詳細については、「AWS Toolkit for Eclipse」を参照してください。 2. アーカイブをダウンロードしたら、内容を抽出し、抽出されたディレクトリを任意の場所にコ ピーします。 3. コンピュータで DynamoDB を開始するには、コマンドプロンプトウィンドウを開 き、DynamoDBLocal.jar を抽出したディレクトリに移動し、次のコマンドを入力します。 java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar sharedDb DynamoDB が実行中のウィンドウに、ときどき診断メッセージが表示されます。 DynamoDB は、停止するまで受信リクエストを処理します。DynamoDB を停止するには、コマ ンドプロンプトウィンドウで Ctrl+C を入力します。 コマンドラインオプション DynamoDB コンピュータの実行は次のコマンドラインオプションを使用します : • -cors value - JavaScript で CORS (Cross-Origin Resource Sharing) のサポートを有効にします。 特定のドメインのカンマ区切りの "許可" リストを指定する必要があります。-cors のデフォルト設 定は、パブリックアクセスを許可するアスタリスク(*)です。 • -dbPath value – DynamoDB がそのデータベースファイルを書き込むディレクトリ。このオ プションを指定しない場合、ファイルは現在のディレクトリに書き込まれます。-dbPath と inMemory の両方を同時に指定することはできません。 • -delayTransientStatuses - DynamoDB で特定のオペレーションの遅延を発生させま す。DynamoDB は、テーブルやインデックスでの作成/更新/削除オペレーションなど、一部のタ スクをほぼ瞬時に実行できます。ただし、実際の DynamoDB サービスでは、それらのタスクには より多くの時間が必要です。このパラメーターを設定すると、DynamoDB は Amazon DynamoDB ウェブサービスの動作をより正確にシミュレートできます(現在、このパラメータではステータス が CREATING または DELETING のグローバルセカンダリインデックスに対してのみ遅延が発生し ます)。 • -help — 使用方法の概要とオプションを出力します。 • -inMemory — DynamoDB は、データベースファイルを使用する代わりにメモリで実行されま す。DynamoDB を停止したとき、保存されるデータはありません。-dbPath と -inMemory の両方 を同時に指定することはできません。 • -optimizeDbBeforeStartup — コンピュータで DynamoDB を開始する前に、基になるデータ ベーステーブルを最適化します。このパラメータを使用するときは、-dbPath も指定する必要があ ります。 • -port value – DynamoDB がアプリケーションと通信するために使用するポート番号。このオプ ションを指定しない場合、デフォルトポートは 8000 になります。 API Version 2012-08-10 45 Amazon DynamoDB 開発者ガイド ローカルエンドポイントの設定 Note DynamoDB は、デフォルトではポート 8000 を使用します。ポート 8000 を使用できない場 合、このコマンドにより例外がスローされます。-port オプションを使用すると、異なる ポート番号を指定できます。DynamoDB ランタイムオプション (-port) の詳細なリストを 表示するには、次のコマンドを入力します。 java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar help • -sharedDb - DynamoDB は、認証情報とリージョンごとに別のファイルを使用する代わりに、単一 のデータベースファイルを使用します。-sharedDb を指定すると、すべての DynamoDB クライア ントは、リージョンと認証情報の設定にかかわらず、テーブルの同じセットを操作します。 ローカルエンドポイントの設定 AWS SDK およびツールは、デフォルトで Amazon DynamoDB ウェブサービスのエンドポイントを使 用します。 ローカルで DynamoDB を実行しながら AWS SDKとツールを使用するには、ローカルエ ンドポイントを指定する必要があります: http://localhost:8000 AWS Command Line Interface AWS CLI を使って、コンピュータで実行中の DynamoDB を操作できます。 たとえば、テーブルの作 成とサンプルデータのロード (p. 166) の手順すべてを AWS CLI を使って実行できます。 ローカルで実行中の DynamoDB にアクセスするには、AWS CLI で --endpoint-url パラメーター を使用します。 次の例では、AWS CLI を使用して、コンピュータにある DynamoDB のテーブルを一 覧表示します。 aws dynamodb list-tables --endpoint-url http://localhost:8000 Note AWS CLI はデフォルトのエンドポイントとしてダウンロード可能なバージョンの DynamoDB を使用できません。このため、各 CLI コマンドで --endpoint-url を指定する必要がありま す。 AWS SDK エンドポイントを指定する方法は、使用しているプログラミング言語と AWS Software Development Kit (SDK) によって異なります。 以下のセクションでは、各種言語でこれを行う方法について説明し ます。 • Java: AWS リージョンとエンドポイントの設定 (p. 172) • .NET: AWS リージョンとエンドポイントの設定 (p. 175) • PHP: AWS リージョンとエンドポイントを設定 (p. 176) Note 他のプログラミング言語の例については、Amazon DynamoDB 入門ガイド を参照してくださ い。 入門ガイドにあるコード例はすべて、ダウンロード可能なバージョンの DynamoDB を使 用しています。 API Version 2012-08-10 46 Amazon DynamoDB 開発者ガイド 使用に関する注意事項 使用に関する注意事項 エンドポイントを除き、システムの DynamoDB で実行するアプリケーションは Amazon DynamoDB ウェブサービスでも動作します。ただし、以下に注意する必要があります。 • -sharedDb オプションを使用すると、DynamoDB は shared-local-instance.db という名前の単一の データベースファイルを作成します。DynamoDB に接続するすべてのプログラムはこのファイルに アクセスします。このファイルを削除すると、保存されたすべてのデータを失うことになります。 • -sharedDb を省略する場合のデータベースファイルの名前は、myaccesskeyid_region.db で、アプ リケーション設定に表示されるとおりの AWS アクセスキー ID とリージョンが使用されます。この ファイルを削除すると、保存されたすべてのデータを失うことになります。 • -inMemory オプションを使用する場合、DynamoDB はデータベースファイルの書き込みを行いま せん。代わりに、すべてのデータがメモリに書き込まれ、DynamoDB を終了するときにデータは保 存されません。 • -optimizeDbBeforeStartup オプションを使用する場合は、-dbPath パラメータも指定 し、DynamoDB がそのデータベースファイルを見つけられるようにする必要があります。 • DynamoDB 用の AWS SDK では、アプリケーション設定でアクセスキーの値と AWS リージョン の値を指定する必要があります。-sharedDb または -inMemory オプションを使用していない限 り、DynamoDB はこれらの値を使用してローカルデータベースファイルに名前を付けます。 ローカルに実行するためにこれらが有効な AWS 値である必要はありませんが、使用しているエン ドポイントを変更するだけで、クラウドでコードを後で実行できるように、有効な値を使用するこ とをお勧めします。 ローカルで実行される DynamoDB と Amazon DynamoDB ウェブサービスの違い ダウンロード可能なバージョンの DynamoDB は、できるだけ密接に Amazon DynamoDB ウェブサー ビスをエミュレートしようとします。ただし、これは以下のように Amazon DynamoDB サービスとは 異なります。 • リージョンと個別の AWS アカウントは、クライアントレベルでサポートされません。 • プロビジョニングされたスループット設定は無視されます。ただし、この設定は CreateTable オ ペレーションで必要です。 CreateTable の場合、プロビジョニングされた読み込みおよび書き込 みスループットに対して任意の数値を指定できます。ただし、この数値は使用されません。1 日に 何回でも UpdateTable を呼び出すことができます。ただし、プロビジョニングされたスループッ ト値の変更は無視されます。 • 読み込みおよび書き込みオペレーションの速度は、コンピュータの速度によってのみ制限を受け ます。CreateTable、UpdateTable、および DeleteTable オペレーションはすぐに実行されま す。テーブルの状態は常に ACTIVE です。テーブルやグローバルセカンダリインデックスでプロビ ジョニングされたスループット設定のみを変更する UpdateTable オペレーションは、すぐに発生 します。UpdateTable オペレーションがグローバルセカンダリインデックスを作成または削除す る場合、それらのインデックスは、通常の状態(CREATING や DELETING など)に移行してから ACTIVE 状態になります。この間、テーブルは ACTIVE のままになります。 • 読み込みオペレーションには結果整合性があります。ただし、コンピュータで実行されている DynamoDB の速度が原因で、実際には、ほとんどの読み込みに強い整合性があるように見えます。 • 消費されたキャパシティーユニットは追跡されません。オペレーションレスポンスでは、キャパシ ティーユニットの代わりに、null が返されます。 • 項目コレクションのメトリクスは追跡されず、項目コレクションのサイズも同様です。オペレー ションレスポンスでは、項目コレクションのメトリクスの代わりに、null が返されます。 • DynamoDB では、結果セットごとに、返されるデータに 1 MB の制限があります。 DynamoDB ウェブサービスはこの制限を適用し、ダウンロード可能バージョンの DynamoDB も同様です。た だし、インデックスのクエリを実行しているとき、DynamoDB サービスは、射影されたキーと属性 API Version 2012-08-10 47 Amazon DynamoDB 開発者ガイド DynamoDB (ウェブサービス) のセットアップ のサイズだけを計算します。一方で、ダウンロード可能バージョンの DynamoDB は、項目全体の サイズを計算します。 • DynamoDB ストリーム を使用している場合、シャードが作成される速度が異なる可能性がありま す。DynamoDB ウェブサービスでは、シャードの作成動作はテーブルパーティションアクティビ ティの影響を部分的に受けます。一方、DynamoDB をローカルに実行する場合にはテーブルパー ティションがありません。 どちらの場合も、シャードはエフェメラルのため、アプリケーションが シャードの動作の影響を受けることはありません。 DynamoDB (ウェブサービス) のセットアップ DynamoDB ウェブサービスを使用するには: 1. AWS にサインアップする (p. 48) 2. AWS アクセスキー ID およびシークレットアクセスキーの取得 (p. 48) (プログラムで DynamoDB にアクセスするために使用)。 Note DynamoDB コンソールのみを使用して DynamoDB とやり取りする場合、アクセスキー ID やシークレットアクセスキーは必要なく、「コンソールを使用する (p. 50)」に進むこと ができます。 AWS にサインアップする DynamoDB を使用するには、AWS アカウントが必要です。アカウントを持っていない場合は、サイ ンアップ時に作成するための画面が表示されます。サインアップした AWS サービスの料金は、その サービスを使用しない限り発生することはありません。 AWS にサインアップするには 1. https://aws.amazon.com/ を開き、[AWS アカウントの作成] を選択します。 2. オンラインの手順に従います。 サインアップ手順の一環として、通話呼び出しを受け取り、電話のキーパッドを用いて PIN を入 力することが求められます。 AWS アクセスキー ID およびシークレットアクセス キーの取得 DynamoDB ウェブサービスを使用するには、事前に AWS アクセスキーおよびシークレットキーを取 得する必要があります。 アクセスキー ID とシークレットアクセスキーを取得するには アクセスキーはアクセスキー ID と秘密アクセスキーからなり、AWS に対するプログラムによるリク エストに署名するときに使用されます。アクセスキーがない場合は、AWS マネジメントコンソール を使用して作成することができます。AWS ルートアカウントのアクセスキーの代わりに、IAM のアク セスキーを使用することをお勧めします。IAM では、AWS アカウントでの AWS サービスとリソース へのアクセスを安全に制御できます。 API Version 2012-08-10 48 Amazon DynamoDB 開発者ガイド AWS アクセスキー ID および シークレットアクセスキーの取得 Note アクセスキーを作成するには、必要な IAM アクションを実行するアクセス許可が必要です。 詳細については、『IAM ユーザーガイド』の「パスワードポリシーと認証情報を管理する IAM ユーザーアクセス許可の付与」を参照してください。 1. 2. IAM コンソールを開きます。 ナビゲーションペインで [Users] を選択します。 3. IAM のユーザー名 (チェックボックスではありません) を選択します。 4. 5. [Security Credentials] タブを選択し、次に [Create Access Key] を選択します。 アクセスキーを参照するには、[Show User Security Credentials] を選択します。認証情報は以下 のようになります。 • アクセスキー ID:AKIAIOSFODNN7EXAMPLE • シークレットアクセスキー: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY 6. [Download Credentials] を選択し、安全な場所にキーを保存します。 秘密キーは AWS マネジメントコンソール ではもう確認できなくなります。コピーは 1 つだ けです。アカウントを保護するために秘密キーは内緒にしておき、メールでも送信しないで ください。また、所属している組織外にこの情報を公開してはいけません。もし AWS または Amazon.com を名乗る人物から問い合わせがあった場合でも、この情報は開示しないでくださ い。Amazon のスタッフまたは関係者がこの情報を尋ねることは決してありません。 関連トピック • IAM とは何ですか?」(IAM ユーザーガイド) • AWS セキュリティ認証情報(AWS General Reference) API Version 2012-08-10 49 Amazon DynamoDB 開発者ガイド コンソールを使用する DynamoDB へのアクセス コンソール、CLI、または API を使用して DynamoDB にアクセスできます。 トピック • コンソールを使用する (p. 50) • CLI の使用 (p. 58) • API の使用 (p. 61) コンソールを使用する DynamoDB AWS マネジメントコンソールには、https://console.aws.amazon.com/dynamodb/home か らアクセスできます。コンソールでは次のことが可能です。 • テーブルを作成、更新、削除する。スループットカリキュレーターでは、利用率に関する情報を入 力すると、リクエストが必要になるキャパシティーユニットの見積りが得られる。 • テーブルに保存されている項目を表示し、項目の追加、更新、削除を行う。 • テーブルのクエリを行う。 • テーブルの容量の利用率をモニタリングするアラームを設定する。 • CloudWatch のリアルタイムグラフで、テーブルの主要なモニタリングメトリクスを表示する。 • 各テーブルに対して設定されているアラームを表示し、カスタムアラームを作成する。 コンソールには、最初のテーブルの作成を求める初期画面が表示されます。 API Version 2012-08-10 50 Amazon DynamoDB 開発者ガイド コンソールを使用する コンソールでテーブルを作成するための詳細な手順については、「テーブルの作成とサンプルデータ のロード (p. 166)」を参照してください。 テーブルを表示するには、コンソールの左側のナビゲーションペインから、[Tables] を選択します。 項目を操作するには、テーブル名の 1 つを選択し、[Items] タブを選択します。ここでテーブルのクエ リを行うこともできます。詳細については、「項目と属性を操作する (p. 52)」を参照してくださ い。 API Version 2012-08-10 51 Amazon DynamoDB 開発者ガイド 項目と属性を操作する 項目と属性を操作する トピック • 項目の追加 (p. 52) • 項目の削除 (p. 54) • 項目の更新 (p. 55) • 項目のコピー (p. 55) DynamoDB コンソールを使用して、テーブルの項目を追加、変更、削除できます。 項目の追加 1. コンソールの左側のナビゲーションペインから、[Tables] を選択します。 2. 対象のテーブル名を選択し、[Items] タブを選択します。次のスクリーンショットでは、[Reply] テーブルが表示されています。 3. [Create Item] を選択します。 [Create item] ウィンドウでは、必要なプライマリキー属性値を入力することができます。テーブ ルにセカンダリインデックスがある場合は、インデックスプライマリキーの値も入力する必要が あります。 次のスクリーンショットは、Reply テーブル (Id および ReplyDateTime) のプライマリキー属性を 示しています。テーブル (PostedBy-Message-Index) にグローバルセカンダリインデックスがあ るため、そのプライマリキー属性 (PostedBy および Message) も必要です。 API Version 2012-08-10 52 Amazon DynamoDB 開発者ガイド 項目と属性を操作する 4. さらに属性を追加するには、[Message] の左側にあるアクションメニューを選択します。アク ションメニューで、[Append] を選択し、目的のデータ型を選択します。 API Version 2012-08-10 53 Amazon DynamoDB 開発者ガイド 項目と属性を操作する 表示されたフィールドに新しい属性の名前と値を入力します。 さらに属性を追加する場合は、必要な回数だけこの手順を繰り返します。 5. 項目の設定が完了したら、[Save] を選択して新しい項目をテーブルに追加します。 項目の削除 1. コンソールの左側のナビゲーションペインから、[Tables] を選択します。 2. 対象のテーブル名を選択し、[Items] タブを選択します。 3. 削除する 1 つ以上の項目を選択し、[Actions | Delete] を選択します。 API Version 2012-08-10 54 Amazon DynamoDB 開発者ガイド 項目と属性を操作する 4. [Delete Item?] ダイアログボックスで、[Yes, Delete] を選択します。 項目の更新 1. コンソールの左側のナビゲーションペインから、[Tables] を選択します。 2. 対象のテーブル名を選択し、[Items] タブを選択します。 3. 更新する項目を選択し、[Actions | Edit] を選択します。 4. [Edit Item] ウィンドウで、目的の属性または値を変更します。 5. 項目の設定が完了したら、[Save] を選択して項目をテーブルに書き込みます。 項目のコピー 既存の項目を選択してコピーし、コピーされた項目を新しいプライマリキーとともに保存できます。 1. コンソールの左側のナビゲーションペインから、[Tables] を選択します。 2. 対象のテーブル名を選択し、[Items] タブを選択します。 3. コピーする項目を選択し、[Actions | Duplicate] を選択します。 4. [Copy Item] ウィンドウで、目的の属性または値を変更します。 API Version 2012-08-10 55 Amazon DynamoDB 開発者ガイド テーブルを監視する テーブルのプライマリキー属性用に、別の値を選択する必要があります。セカンダリインデック スが存在する場合、インデックスのプライマリキー属性の値も選択する必要があります。 5. 項目の設定が完了したら、[Save] を選択して項目をテーブルに書き込みます。 テーブルを監視する 選択したテーブルの CloudWatch メトリクスを表示するには、[Metrics] タブを選択します 。 任意のグラフを選択すると、特定のメトリクスについて詳しく調べることができます。 [Metrics] ページには、テーブルのパフォーマンスのわかりやすい概要が表示されます。テーブル に関連付けられたその他のメトリクスを表示するには、[View all CloudWatch metrics] を選択して CloudWatch コンソールに移動します。 DynamoDB の CloudWatch メトリクスの詳細については、「Amazon DynamoDB のモニタリン グ (p. 495)」を参照してください。 API Version 2012-08-10 56 Amazon DynamoDB 開発者ガイド CloudWatch アラームを設定する CloudWatch アラームを設定する DynamoDB コンソールを使用して、テーブルの CloudWatch アラームを作成および管理できま す。CloudWatch アラームは、プロビジョニングされたスループット設定を長時間超えているテーブ ルなど、注意が必要になる可能性があるイベントについて通知します。 テーブルの CloudWatch アラームに対応するには、[Alarms] タブを選択します。 このページでは、テーブルの既存の CloudWatch アラームを変更するか、[Create alarm] を選択して新 しい CloudWatch アラームを作成できます。 CloudWatch アラームは、特定の CloudWatch メトリックスが特定の期間のしきい値に達したときに トリガーされます。 アラームの設定の詳細については、CloudWatch コンソールで CloudWatch ヘルプを参照する か、CloudWatch ドキュメントを参照してください。 DynamoDB ストリーム とトリガーの管理 テーブルで DynamoDB ストリーム を有効または無効にできます。これを行うには、[Overview] タブ に移動し、[Manage Stream] を選択します。 Note DynamoDB ストリーム および AWS Lambda トリガーの詳細については、「DynamoDB スト リーム を使用したテーブルアクティビティのキャプチャ (p. 426)」 を参照してください。 API Version 2012-08-10 57 Amazon DynamoDB 開発者ガイド CLI の使用 [Manage Stream] ウィンドウでは、このテーブルのストリームを有効にできます。 また、ストリーム に表示されるデータ変更に関する詳細レベルを選択することもできます。 すでにテーブルでストリームが有効になっている場合、[Manage Stream] ウィンドウで、これを無効 にできます。 [Triggers] タブでは、AWS Lambda 関数をテーブルのストリーム (有効になっている場合) と関連付け ることができます。このタブを使用して、対象となるイベントがテーブルのストリームに表示される たびに呼び出される既存の Lambda 関数を選択 (または新しい関数を作成) します。 CLI の使用 AWS Command Line Interface (AWS CLI) を使用すると、複数の AWS のサービスをコマンドライン から制御したり、スクリプトで自動化したりできます。テーブルの作成など、その場限りのオペレー ションに AWS CLI を使用できます。また、ユーティリティスクリプト内に DynamoDB オペレーショ ンを埋め込むときにも使用できます。 コンピュータで AWS CLI を設定する前に、AWS アクセスキー ID とシークレットキーを最初に入手 します。詳細については、「AWS アクセスキー ID およびシークレットアクセスキーの取得 (p. 48)」 を参照してください。 API Version 2012-08-10 58 Amazon DynamoDB 開発者ガイド AWS CLI のダウンロードと設定 DynamoDB AWS CLI で使用できるすべてのコマンドの完全な一覧については、http:// docs.aws.amazon.com/cli/latest/reference/dynamodb/index.html を参照してください。 トピック • AWS CLI のダウンロードと設定 (p. 59) • DynamoDB での AWS CLI の使用 (p. 59) • ダウンロード可能な DynamoDB での AWS CLI の使用 (p. 60) AWS CLI のダウンロードと設定 AWS CLI は、http://aws.amazon.com/cli で入手でき、Windows、Mac、または Linux で動作しま す。AWS CLI をダウンロードした後でインストールし、設定するには、次の操作を実行します。 1. 2. AWS Command Line Interface ユーザーガイド に移動します。 AWS CLI をインストールし、AWS CLI を設定する手順に従います。 DynamoDB での AWS CLI の使用 コマンドラインの形式は、DynamoDB オペレーション名の後に、そのオペレーションのパラメーター が続きます。 AWS CLI では、パラメータ値の短縮構文および JSON をサポートしています。 たとえば、次のコマンドでは、Music という名前のテーブルを作成します。パーティションキーは Artist で、ソートキーは SongTitle です。(読みやすくするために、このセクションの長いコマンド は、複数の行に分かれています)。 aws dynamodb create-table \ --table-name Music \ --attribute-definitions \ AttributeName=Artist,AttributeType=S \ AttributeName=SongTitle,AttributeType=S \ --key-schema AttributeName=Artist,KeyType=HASH AttributeName=SongTitle,KeyType=RANGE \ --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 次のコマンドでは、新しい項目をテーブルに追加します。この例では、短縮構文と JSON を組み合わ せて使用しています。 aws dynamodb put-item \ --table-name Music \ --item \ '{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"}, "AlbumTitle": {"S": "Somewhat Famous"}}' \ --return-consumed-capacity TOTAL aws dynamodb put-item \ --table-name Music \ --item \ '{"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}, "AlbumTitle": {"S": "Songs About Life"}}' \ --return-consumed-capacity TOTAL aws dynamodb put-item \ --table-name Music \ --item '{ \ API Version 2012-08-10 59 Amazon DynamoDB 開発者ガイド ダウンロード可能な DynamoDB での AWS CLI の使用 "Artist": {"S": "Acme Band"}, \ "SongTitle": {"S": "Happy Day"}, \ "AlbumTitle": {"S": "Songs About Life"} }' \ --return-consumed-capacity TOTAL コマンドラインで、有効な JSON を作成するのは難しい場合があります。ただし、AWS CLI は、JSON ファイルを読み込むことができます。たとえば、key-conditions.json という名前のファイ ルに格納されている次の JSON スニペットがあるとします。 { "Artist": { "AttributeValueList": [ { "S": "No One You Know" } ], "ComparisonOperator": "EQ" }, "SongTitle": { "AttributeValueList": [ { "S": "Call Me Today" } ], "ComparisonOperator": "EQ" } } 次のように、AWS CLI を使用して、Query リクエストを発行できます。この例では、keyconditions.json ファイルの内容は、--key-conditions パラメータに使用されます。 aws dynamodb query --table-name Music --key-conditions file://keyconditions.json DynamoDB で AWS CLI を使用する方法に関するドキュメントについては、http:// docs.aws.amazon.com/cli/latest/reference/dynamodb/index.html を参照してください。 ダウンロード可能な DynamoDB での AWS CLI の使 用 AWS CLI は、コンピュータで実行中の DynamoDB を操作できます。これを有効にするには、各コマ ンドに --endpoint-url パラメーターを追加します。 --endpoint-url http://localhost:8000 次の例では、AWS CLI を使用して、ローカルデータベースのテーブルを一覧表示します。 aws dynamodb list-tables --endpoint-url http://localhost:8000 DynamoDB がデフォルト(8000)以外のポート番号を使用している場合、それに応じて -endpoint-url 値を変更する必要があります。 Note AWS CLI はデフォルトのエンドポイントとしてダウンロード可能なバージョンの DynamoDB を使用できません。このため、各コマンドで --endpoint-url を指定する必要があります。 API Version 2012-08-10 60 Amazon DynamoDB 開発者ガイド API の使用 API の使用 AWS マネジメントコンソールおよび AWS コマンドラインインターフェイスを使用して、DynamoDB をインタラクティブに操作できます。ただし、DynamoDB を最大限に活用するためには、AWS SDK を使用してアプリケーションコードを記述できます。詳細については、「DynamoDB および AWS SDK を使用したプログラミング (p. 62)」を参照してください。 API Version 2012-08-10 61 Amazon DynamoDB 開発者ガイド DynamoDB の AWS SDK サポートの概要 DynamoDB および AWS SDK を使 用したプログラミング この章では、開発者に関連するトピックを取り上げます。代わりにコードサンプルを実行する場合 は、「この開発者ガイドのコードサンプルの実行 (p. 165)」を参照してください。 トピック • DynamoDB の AWS SDK サポートの概要 (p. 62) • プログラム用インターフェイス (p. 64) • DynamoDB 低レベル API (p. 68) • エラー処理 (p. 72) • DynamoDB 用の高レベルプログラミングインターフェイス (p. 78) • この開発者ガイドのコードサンプルの実行 (p. 165) DynamoDB の AWS SDK サポートの概要 次の図は、AWS SDK を使用する DynamoDB アプリケーションプログラミングの概要を示していま す。 API Version 2012-08-10 62 Amazon DynamoDB 開発者ガイド DynamoDB の AWS SDK サポートの概要 1. 使用しているプログラミング言語用の AWS SDK を使用してアプリケーションを作成します。AWS SDK は、さまざまな言語で利用できます。詳細なリストについては、「Tools for Amazon Web Services」を参照してください。 2. 各 AWS SDK には、DynamoDB を使用するために 1 つ以上のプログラムインターフェイスが用意 されています。使用可能なインターフェイスは、使用するプログラミング言語および AWS SDK に よって異なります。 3. AWS SDK は低レベル DynamoDB API で使用するための HTTP(S) リクエストを構築します。 4. AWS SDK は、DynamoDB エンドポイントにリクエストを送信します。 5. DynamoDB は、リクエストを実行します。リクエストが成功した場合、DynamoDB により応答 コード HTTP 200 (OK) が返されます。リクエストが失敗した場合、DynamoDB により HTTP エ ラーコードとエラーメッセージが返されます。 6. AWS SDK は、応答を処理し、アプリケーションに反映させます。 各 AWS SDK は、次のものを含むアプリケーションに重要なサービスを提供しています。 • HTTP(S) リクエストをフォーマットし、リクエストパラメーターをシリアル化します。 • 各リクエストの暗号署名を生成します。 • リクエストを DynamoDB エンドポイントに送信し、DynamoDB からのレスポンスを受信します。 • これらのレスポンスから結果を抽出します。 • エラーが発生した場合には、基本的な再試行ロジックを実行します。 これらのタスクのコードを書く必要はありません。 API Version 2012-08-10 63 Amazon DynamoDB 開発者ガイド プログラム用インターフェイス Note インストール手順とドキュメントを含む、AWS SDK の詳細については、「アマゾン ウェブ サービスのツール」を参照してください。 プログラム用インターフェイス すべての AWS SDK には、DynamoDB を使用するために 1 つ以上のプログラムインターフェイスが 用意されています。これらのインターフェイスは、シンプルな低レベルの DynamoDB ラッパーから オブジェクト指向永続化層までを含みます。利用できるインターフェイスは、使用するプログラミン グ言語および AWS SDK によって異なります。 以下のセクションでは、AWS SDK for Java を例として使用し、利用できるインターフェイスの一部 を取り上げています。(すべての AWS SDK ですべてのインターフェイスが使用できるわけではありま せん)。 トピック • 低レベル インターフェイス (p. 64) • ドキュメント インターフェイス (p. 65) • オブジェクト永続性インターフェイス (p. 66) 低レベル インターフェイス すべての言語固有の AWS SDK には、低レベルの DynamoDB API リクエストとよく似たメソッドを 持つ、DynamoDB の低レベルインターフェイスが用意されています。 API Version 2012-08-10 64 Amazon DynamoDB 開発者ガイド ドキュメント インターフェイス 場合によっては、属性のデータ型を、data type descriptors (p. 71) を使用して、文字列を S あるい は数字を N などのように指定する必要があります。 Note 低レベルインターフェイスは、すべての言語固有 AWS SDK で使用できます。 次の Java プログラムには、AWS SDK for Java の低レベルインターフェイスを使用します。プログラ ムは Music テーブル内の曲の GetItem リクエストを発行し、曲がリリースされた年を出力します。 com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient クラスは、DynamoDB 低レベ ルインターフェイスを実装します。 package com.amazonaws.codesamples; import java.util.HashMap; import import import import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.model.AttributeValue; com.amazonaws.services.dynamodbv2.model.GetItemRequest; com.amazonaws.services.dynamodbv2.model.GetItemResult; public class MusicLowLevelDemo { public static void main(String[] args) { AmazonDynamoDBClient client = new AmazonDynamoDBClient(); HashMap<String, AttributeValue> key = new HashMap<String, AttributeValue>(); key.put("Artist", new AttributeValue().withS("No One You Know")); key.put("SongTitle", new AttributeValue().withS("Call Me Today")); GetItemRequest request = new GetItemRequest() .withTableName("Music") .withKey(key); try { GetItemResult result = client.getItem(request); if (result != null) { AttributeValue year = result.getItem().get("Year"); System.out.println("The song was released in " + year.getN()); } else { System.out.println("No matching song was found"); } } catch (Exception e) { System.err.println("Unable to retrieve data: "); System.err.println(e.getMessage()); } } } ドキュメント インターフェイス 多くの AWS SDK には、ドキュメント インターフェイスがあり、テーブルおよびインデックスでデー タプレーンオペレーション (作成、読み込み、更新、削除) を実行できます。ドキュメント インター API Version 2012-08-10 65 Amazon DynamoDB 開発者ガイド オブジェクト永続性インターフェイス フェイスに、data type descriptors (p. 71) を指定する必要はありません。データ型は、データその もののセマンティクスによって暗示されます。これらの AWS SDK には、JSON ドキュメントとネイ ティブな DynamoDB データ型を簡単に変換できるメソッドが用意されています。 Note ドキュメントインターフェイスは、AWS SDK for Java、.NET、Node.js、およびブラウザの JavaScript で使用できます。 次の Java プログラムには、AWS SDK for Java のデータ型ドキュメント インターフェイスを使用し ます。プログラムは Music テーブルを表す Table オブジェクトを作成し、オブジェクトが曲を取得 する GetItem を使用するようにします。その後、プログラムは、その曲がリリースされた年を出力 します。 com.amazonaws.services.dynamodbv2.document.DynamoDB クラスは、DynamoDB ドキュメン ト インターフェイスを実装します。DynamoDB が低レベルクライアント (AmazonDynamoDBClient) にラッパーとしてどのように機能するかに注意してください。 package com.amazonaws.codesamples.gsg; import import import import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.GetItemOutcome; com.amazonaws.services.dynamodbv2.document.Table; public class MusicDocumentDemo { public static void main(String[] args) { AmazonDynamoDBClient client = new AmazonDynamoDBClient(); DynamoDB docClient = new DynamoDB(client); Table table = docClient.getTable("Music"); GetItemOutcome outcome = table.getItemOutcome( "Artist", "No One You Know", "SongTitle", "Call Me Today"); int year = outcome.getItem().getInt("Year"); System.out.println("The song was released in " + year); } } オブジェクト永続性インターフェイス AWS SDK の一部には、直接データプレーンオペレーションを実行しない、オブジェクト永続性イン ターフェイスが用意されています。代わりに、DynamoDB テーブルおよびインデックスに項目を表す オブジェクト作成し、これらのオブジェクトとのみやり取りします。これにより、データベース中心 のコードではなく、オブジェクト中心のコードを記述できます。 Note オブジェクト永続性インターフェイスは、AWS SDK for Java および AWS SDK for .NET で 使用できます。詳細については、「DynamoDB 用の高レベルプログラミングインターフェイ ス (p. 78)」を参照してください。 API Version 2012-08-10 66 Amazon DynamoDB 開発者ガイド オブジェクト永続性インターフェイス 次の Java プログラムは、DynamoDBMapper という AWS SDK for Java のオブジェクト永続性イン ターフェイスを使用します。MusicItem クラスは、Music テーブル内の項目を表します。 package com.amazonaws.codesamples; import import import import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; @DynamoDBTable(tableName="Music") public class MusicItem { private String artist; private String songTitle; private String albumTitle; private int year; @DynamoDBHashKey(attributeName="Artist") public String getArtist() { return artist;} public void setArtist(String artist) {this.artist = artist;} @DynamoDBRangeKey(attributeName="SongTitle") public String getSongTitle() { return songTitle;} public void setSongTitle(String songTitle) {this.songTitle = songTitle;} @DynamoDBAttribute(attributeName = "AlbumTitle") public String getAlbumTitle() { return albumTitle;} public void setAlbumTitle(String albumTitle) {this.albumTitle = albumTitle;} @DynamoDBAttribute(attributeName = "Year") public int getYear() { return year; } public void setYear(int year) { this.year = year; } } 次に、MusicItem オブジェクトをインスタンス化し、DynamoDBMapper の load() メソッドを使用 して曲を取得できます。その後、プログラムは、その曲がリリースされた年を出力します。 com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper クラス は、DynamoDB オブジェクト永続性インターフェイスを実行します。DynamoDBMapper が低レベル クライアント (AmazonDynamoDBClient) にラッパーとしてどのように機能するかに注意してくださ い。 package com.amazonaws.codesamples; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; public class MusicMapperDemo { public static void main(String[] args) { AmazonDynamoDBClient client = new AmazonDynamoDBClient(); DynamoDBMapper mapper = new DynamoDBMapper(client); MusicItem keySchema = new MusicItem(); keySchema.setArtist("No One You Know"); API Version 2012-08-10 67 Amazon DynamoDB 開発者ガイド DynamoDB 低レベル API keySchema.setSongTitle("Call Me Today"); try { MusicItem result = mapper.load(keySchema); if (result != null) { System.out.println( "The song was released in "+ result.getYear()); } else { System.out.println("No matching song was found"); } } catch (Exception e) { System.err.println("Unable to retrieve data: "); System.err.println(e.getMessage()); } } } DynamoDB 低レベル API トピック • リクエストの形式 (p. 70) • レスポンスの形式 (p. 70) • データ型記述子 (p. 71) • 数値データ (p. 72) • バイナリデータ (p. 72) API Version 2012-08-10 68 Amazon DynamoDB 開発者ガイド DynamoDB 低レベル API DynamoDB 低レベル API は、Amazon DynamoDB 用のプロトコルレベルのインターフェイスです。 このレベルでは、すべての HTTP リクエストは、適切な形式で有効なデジタル署名がある必要があり ます。 AWS SDK は、低レベル DynamoDB API リクエストをユーザーに代わって作成し、DynamoDB から のレスポンスを処理します。 これにより、低レベルの詳細ではなく、アプリケーションロジックに専 念することができます。 ただし、低レベル DynamoDB API の動作方法についての基本的な知識も役 立ちます。 低レベル DynamoDB API の詳細については、Amazon DynamoDB API Reference を参照してくださ い。 Note DynamoDB ストリーム には、DynamoDB とは別に独自の低レベル API があり、AWS SDK で完全にサポートされています。 詳細については、「DynamoDB ストリーム を使用したテーブルアクティビティのキャプ チャ (p. 426)」を参照してください。低レベルの DynamoDB ストリーム API について は、DynamoDB ストリーム API リファレンス を参照してください 低レベル DynamoDB API は、ワイヤプロトコル形式として、JavaScript Object Notation (JSON) を使 用しています。 JSON では、データ値とデータ構造が両方同時にわかるように、データが階層で示さ れます。 名前と値のペアは、name:value の形式で定義されます。データ階層は、名前と値のペアを ブラケットで囲み、ネストする形で定義します。 API Version 2012-08-10 69 Amazon DynamoDB 開発者ガイド リクエストの形式 DynamoDB は、ストレージ形式としてではなく、トランスポートプロトコルとしてのみ、JSON を使 用しています。 AWS SDK は、DynamoDB へのデータ送信に JSON を使用し、DynamoDB は JSON で応答しますが、DynamoDB が JSON 形式でデータを永続的に保存することはありません。 Note JSON に関する詳細については、JSON.org のウェブサイト 「JSON の入門」 を参照してく ださい。 リクエストの形式 DynamoDB 低レベル API は、HTTP POST リクエストを入力として受け付けます。 AWS SDK はこれ らのリクエストを作成します。 ペットという名のテーブルに、AnimalType (パーティションキー)、Name (ソートキー) によって構成 されるキースキーマがあるとします。 これらの属性は両方とも文字列型になります。 ペットからある 項目を取り出すために、AWS SDKは次に示すようなリクエストを作成します。 POST / HTTP/1.1 Host: dynamodb.<region>.<domain>; Accept-Encoding: identity Content-Length: <PayloadSizeBytes> User-Agent: <UserAgentString> Content-Type: application/x-amz-json-1.0 Authorization: AWS4-HMAC-SHA256 Credential=<Credential>, SignedHeaders=<Headers>, Signature=<Signature> X-Amz-Date: <Date> X-Amz-Target: DynamoDB_20120810.GetItem { "TableName": "Pets", "Key": { "AnimalType": {"S": "Dog"}, "Name": {"S": "Fido"} } } このリクエストに関して以下の点に注意してください。 • Authorization ヘッダーには、DynamoDB がリクエストを認証するのに必要な情報が含まれてい ます。 詳細については、『アマゾン ウェブ サービス全般のリファレンス』 の 「AWS API リクエ ストの署名」 と 「署名バージョン 4 の署名プロセス」 を参照してください。 • X-Amz-Target ヘッダーには、DynamoDB オペレーションの名前が含まれます : GetItem。 (これ は、低レベル API バージョンと共に示されます。この場合は 20120810 となります。) • リクエストのペイロード (本文) には、JSON 形式で、オペレーションのパラメーターが含まれま す。 GetItem オペレーションでは、パラメーターは TableName と Key です。 レスポンスの形式 リクエストを受け取ったら、DynamoDB が処理しレスポンスを返します。 上に示したリクエストに 対して、HTTP レスポンスペイロードには、この例のようにオペレーションからの結果が含まれます: HTTP/1.1 200 OK x-amzn-RequestId: <RequestId> x-amz-crc32: <Checksum> API Version 2012-08-10 70 Amazon DynamoDB 開発者ガイド データ型記述子 Content-Type: application/x-amz-json-1.0 Content-Length: <PayloadSizeBytes> Date: <Date> { "Item": { "Age": {"N": "8"}, "Colors": { "L": [ {"S": "White"}, {"S": "Brown"}, {"S": "Black"} ] }, "Name": {"S": "Fido"}, "Vaccinations": { "M": { "Rabies": { "L": [ {"S": "2009-03-17"}, {"S": "2011-09-21"}, {"S": "2014-07-08"} ] }, "Distemper": {"S": "2015-10-13"} } }, "Breed": {"S": "Beagle"}, "AnimalType": {"S": "Dog"} } } この時点で、AWS SDK は、さらに処理するためにアプリケーションに応答データを返します。 Note DynamoDB がリクエストを処理できない場合、HTTP エラーコードとメッセージを返しま す。 AWS SDK は、これらを例外の形でアプリケーションに伝達します。 詳細については、 「エラー処理 (p. 72)」を参照してください。 データ型記述子 低レベル DynamoDB API のプロトコルは、各属性がデータ型記述子に伴われる必要があります。 データ型記述子は、各属性を解釈する方法を DynamoDB に伝えるトークンです。 リクエストの形式 (p. 70)とレスポンスの形式 (p. 70)には、データ型記述子が使用されている例 が示されています。 GetItem リクエストは、ペットキースキーマ属性AnimalType と Name のため の S を文字列で指定します。 GetItem レスポンスには、文字列 (S)、数値 (N)、マップ (M)、リスト (L) の属性のあるペット項目が含まれます。 DynamoDB データ型記述子の一覧を次に示します。 • S – 文字列 • N – 数値 • B – バイナリ • BOOL – Boolean • NULL – Null API Version 2012-08-10 71 Amazon DynamoDB 開発者ガイド 数値データ • M – マップ • L – リスト • SS – 文字列セット • NN – 数値セット • BB – バイナリセット Note DynamoDB データ型の詳細な説明については、データ型 (p. 12) を参照してください。 数値データ プログラミング言語により、提供される JSON のサポートのレベルが異なります。 場合によって は、JSONドキュメントを検証し解析するにあたり、サードパーティーのライブラリを使用すること もできます。 JSON Number 型に基づいて構築されたサードパーティーライブラリもあり、int や long、または double など独自の型を提供しています。 ただし、では他のデータ型に正確にマッピングされない DynamoDB; のネイティブ数値データ型が使用されるため、このようなデータ型の区別が競合の原因 になる可能性があります。 加えて、多くの JSON ライブラリでは固定精度の数値は処理されず、小数 点を含む数字列は自動的に倍精度浮動小数点データ型であると推定されます。 これらの問題を解決するために、DynamoDB ではデータ損失のない単一の数値型が用意されていま す。誤って倍精度の値に暗黙的変換が行われないように、DynamoDB では数値のデータ転送には文字 列が使用されます。 この方法によって、01、2、03 などの値を適切な順序で配置するなど、適切な並 べ替えセマンティクスを維持しながら、柔軟に属性値を更新することが可能になります。 数値の精度がアプリケーションにとって重要な場合は、数値を文字列に変換してから、DynamoDB に 渡します。 バイナリデータ DynamoDB ではバイナリ属性がサポートされています。ただし JSON では、ネイティブではバ イナリデータのエンコードがサポートされていません。リクエストでバイナリデータを送信す るには、Base64 形式でエンコードする必要があります。 DynamoDB はリクエストを受け取る と、Base64 データをバイナリに復号します。 DynamoDB で使用される Base64 エンコーディングスキームは、Internet Engineering Task Force (IETF) のウェブサイト RFC 4648 に記載されています。 エラー処理 このセクションでは、ランタイムエラーとその処理方法について説明します。 また、DynamoDB 特 有のエラーメッセージとコードについて説明します。 トピック • エラーコンポーネント (p. 73) • エラーメッセージおよびコード (p. 73) • アプリケーションのエラー処理 (p. 76) • エラーの再試行とエクスポネンシャルバックオフ (p. 76) • バッチオペレーションとエラー処理 (p. 77) API Version 2012-08-10 72 Amazon DynamoDB 開発者ガイド エラーコンポーネント エラーコンポーネント プログラムがリクエストを送信すると、DynamoDB は処理を試行します。 リクエストが成功した場 合、DynamoDB は要求されたオペレーションからの結果とともに、成功の HTTP ステータスコード (200 OK) を返します。 リクエストが正常に行われなかった場合、DynamoDB はエラーを返します。 それぞれのエラーに は、次の三つのコンポーネントがあります: • HTTP ステータスコード (400 など)。 • 例外の名前 (ResourceNotFoundException など)。 • エラーメッセージ (Requested resource not found: Table: tablename not found な ど)。 AWS SDK によりアプリケーションにエラーが伝達されるため、適切なアクションを実行できます。 たとえば、Java プログラムでは、 ResourceNotFoundException を処理する try-catch ロジック を記述できます。 AWS SDK を使用していない場合は、DynamoDB からの低レベルのレスポンスの内容も解析する必要 があります。 以下に、そのようなレスポンスの例を示します。 HTTP/1.1 400 Bad Request x-amzn-RequestId: LDM6CJP8RMQ1FHKSC1RBVJFPNVV4KQNSO5AEMF66Q9ASUAAJG Content-Type: application/x-amz-json-1.0 Content-Length: 240 Date: Thu, 15 Mar 2012 23:56:23 GMT {"__type":"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException", "message":"Requested resource not found: Table: tablename not found"} エラーメッセージおよびコード DynamoDB によって返される例外のリストを HTTP ステータスコードごとに次に示します。 再試 行してもいいですかがはいであれば、同じリクエストを再度送信できます。 再試行してもいいです かがいいえであれば、新しいリクエストを送信する前に、クライアント側で問題を修正する必要があ ります。 HTTP ステータスコード 400 HTTP ステータスコード400は、認証の失敗、必須パラメーターの欠落、またはテーブルにプロビジョ ニングされているスループットの超過などのリクエストに関連した問題があることを示しています。 リクエストを再度送信する前に、アプリケーションで問題を修正する必要があります。 AccessDeniedException メッセージ: アクセスが拒否されました。 クライアントがリクエストに正しく署名しませんでした。AWS SDKを使用する場合、リクエスト は自動的に署名されます。それ以外の場合、AWS General Reference にある「Signature Version 4 Signing Process」を参照してください。 再試行してもいいですか。 いいえ ConditionalCheckFailedException メッセージ: 条件付きリクエストが失敗しました。 API Version 2012-08-10 73 Amazon DynamoDB 開発者ガイド エラーメッセージおよびコード false と評価された条件を指定しました。 たとえば、項目に条件付き更新を実行しようとしたかも しれませんが、属性の実際の値は、条件の予期される値と一致しませんでした。 再試行してもいいですか。 いいえ IncompleteSignatureException メッセージ: リクエストの署名が AWS 基準に適合しません。 リクエストの署名に、必要なすべての要素が含まれていませんでした。 AWS SDKを使用する 場合、リクエストは自動的に署名されます。それ以外の場合、AWS General Reference にある 「Signature Version 4 Signing Process」を参照してください。 再試行してもいいですか。 いいえ ItemCollectionSizeLimitExceededException メッセージ : コレクションサイズが超過しました。 local secondary indexがあるテーブルの場合、同じパーティションキー値を持つ項目のグループ が、10 GB の最大サイズ制限を超過しました。項目コレクションの詳細については、「項目コレ クション (p. 391)」を参照してください。 再試行してもいいですか。 はい LimitExceededException メッセージ : 特定のサブスクライバに対するオペレーションが多すぎます。 同時オペレーションのコントロールプレーンが多すぎます。 CREATING、DELETINGまた はUPDATINGの状態のテーブルやインデックスの累積数が、10 を超えることはできません。 再試行してもいいですか。 はい MissingAuthenticationTokenException メッセージ : リクエストには、有効な(登録済みの)AWS Access Key ID が含まれている必要が あります。 リクエストに、必要な認証ヘッダーが含まれていないか、または正しい形式ではありません。 「DynamoDB 低レベル API (p. 68)」を参照してください。 再試行してもいいですか。 いいえ ProvisionedThroughputExceededException メッセージ : 1 つのテーブルまたは 1 つ以上のグローバルセカンダリインデックスのプロビジョ ンドスループットが許容されている最大値を超えました。 プロビジョンドスループットと消費ス ループットのパフォーマンスメトリクスを表示するには、「Amazon CloudWatch console」を参 照してください。 例: リクエストの頻度が多すぎます。DynamoDB の AWS SDK は、この例外を受け取ったリクエ ストを自動的に再試行します。リクエストは最終的に成功しますが、再試行キューが大きすぎて 終了しない場合もあります。exponential backoff (p. 76) を使用して、リクエストの頻度を少な くします。 再試行してもいいですか。 はい ResourceInUseException メッセージ : 変更しようとしているリソースは使用中です。 API Version 2012-08-10 74 Amazon DynamoDB 開発者ガイド エラーメッセージおよびコード 例: 既存のテーブルを再作成しようとしたか、CREATING 状態にあるテーブルを削除しようとしま した。 再試行してもいいですか。 いいえ ResourceNotFoundException メッセージ : リクエストされたリソースは存在しません。 例: リクエストされたテーブルが存在しないか、ごく初期の CREATING 状態にあります。 再試行してもいいですか。 いいえ ThrottlingException メッセージ : リクエストの速度が、許容されているスループットを超えています。 CreateTable、UpdateTable、DeleteTable オペレーションの実行が速すぎる場合、次の例外 が返されることがあります。 再試行してもいいですか。 はい UnrecognizedClientException メッセージ : アクセスキー ID またはセキュリティトークンが無効です。 リクエスト署名が間違っています。最も可能性の高い原因は、AWS アクセスキー ID またはシー クレットキーが無効であることです。 再試行してもいいですか。 はい ValidationException メッセージ : 発生した特定のエラーにより異なります このエラーは、必須パラメータが指定されていない、値が範囲外である、データ型が一致しな い、などいくつかの理由で発生します。エラーメッセージに、エラーを引き起こしたリクエスト の特定部分に関する詳細が含まれています。 再試行してもいいですか。 いいえ HTTP ステータスコード 5xx HTTP ステータスコード 5xx は、アマゾン ウェブ サービスで解決する必要のある問題を示していま す。 これは一時的なエラーかもしれず、その場合はリクエストを再試行することで成功する場合があ ります。 それ以外の場合、サービスに運用上の問題があるかどうかを確認するために、「AWS サー ビス状態ダッシュボード」を参照してください。 内部サーバーエラー (HTTP 500) DynamoDB でリクエストを処理できませんでした。 再試行してもいいですか。 はい Note 項目の操作中に内部サーバーエラーが発生することがあります。これはテーブルの存続期 間中に発生すると予想されます。失敗したリクエストは速やかに再試行できます。 Service Unavailable (HTTP 503) DynamoDB は現在利用できません。 (これは一時的な状態です。) API Version 2012-08-10 75 Amazon DynamoDB 開発者ガイド アプリケーションのエラー処理 再試行してもいいですか。 はい アプリケーションのエラー処理 アプリケーションをスムーズに実行するには、エラーを見つけ、エラーに対応するロジックを組み込 む必要があります。 一般的な方法には、try-catchブロックやif-thenステートメントの使用など があります。 AWS SDK は独自に再試行とエラーチェックを実行します。AWS SDK の使用中にエラーが発生した 場合は、エラーコードと説明が問題のトラブルシューティングに役立ちます。 また、レスポンスにRequest IDが表示されます。 Request IDは、AWS サポートを使用して問題を 診断することが必要な場合に便利です。 次の Java コードスニペットは、DynamoDB テーブルから項目の削除を試み、基本的なエラー処理を 実行します。 (この場合、ユーザーにはリクエストが失敗したとだけ通知されます)。 Table table = dynamoDB.getTable("Movies"); try { Item item = table.getItem("year", 1978, "title", "Superman"); if (item != null) { System.out.println("Result: " + item); } else { //No such item exists in the table System.out.println("Item not found"); } } catch (AmazonServiceException ase) { System.err.println("Could not complete operation"); System.err.println("Error Message: " + ase.getMessage()); System.err.println("HTTP Status: " + ase.getStatusCode()); System.err.println("AWS Error Code: " + ase.getErrorCode()); System.err.println("Error Type: " + ase.getErrorType()); System.err.println("Request ID: " + ase.getRequestId()); } catch (AmazonClientException ace) { System.err.println("Internal error occured communicating with DynamoDB"); System.out.println("Error Message: " + ace.getMessage()); } このコードスニペットでは、try-catchの構成は二つの異なるタイプの例外を処理します: • AmazonServiceException — クライアントリクエストが DynamoDB に正しく送信された が、DynamoDB がリクエストを処理できず、代わりにエラーレスポンスを返した場合にスローされ ます。 • AmazonClientException — クライアントがサービスからレスポンスを取得できなかったか、ク ライアントがサービスからレスポンスを解析できなかった場合にスローされます。 エラーの再試行とエクスポネンシャルバックオフ 特定のリクエストの処理中には、DNS サーバー、スイッチ、ロードバランサーなど、ネットワーク上 のさまざまなコンポーネントが原因でエラーが発生する可能性があります。ネットワーク環境内でこ れらのエラー応答を処理する一般的な手法としては、クライアントアプリケーションに再試行を実装 する方法が挙げられます。この手法によってアプリケーションの信頼性が向上し、開発者のオペレー ションコストが軽減されます。 API Version 2012-08-10 76 Amazon DynamoDB 開発者ガイド バッチオペレーションとエラー処理 各 AWS SDK は、自動的に再試行ロジックを実装しています。 必要に応じて再試行パラメーターを変 更できます。 たとえば、エラーが発生したら再試行が許可されない、Fail-Fast 方式を要求する Java アプリケーションについて考えてみましょう。 AWS SDK for Java では、ClientConfiguration ク ラスを使用して maxErrorRetry の値を 0 に設定することで、再試行を無効にできます。 詳細につい ては、AWS SDK ドキュメントのご使用のプログラミング言語の項目を参照してください AWS SDK を使用していない場合は、サーバーエラー (5xx) を受け取る元のリクエストを再試 行する必要があります。ただし、クライアントエラー (4xx、ThrottlingException または ProvisionedThroughputExceededException 以外) は、再試行する前にリクエスト自体を修正し て問題を解決する必要があることを示しています。 単純な再試行に加えて、各 AWS SDK は効果的なフロー制御を行うために、エクスポネンシャルバッ クオフアルゴリズムを実装します。エクスポネンシャルバックオフは、再試行間の待機時間を累進的 に長くして、連続的なエラー応答を受信するという概念に基づいています。たとえば、1 回目の再試 行の前に最大 50 ミリ秒、2 回目の前に最大 100 ミリ秒、3 回目の前に最大 200 ミリ秒のようになり ます。ただし 1 分を経過してもリクエストが成功しない場合は、問題の原因はリクエストの速度では なく、プロビジョニングしたスループットをリクエストのサイズが超えたためである可能性がありま す。1 分程度で再試行が停止するように最大回数を設定します。リクエストが失敗した場合は、プロ ビジョニングしたスループットオプションを調べてください。詳細については、「テーブルの操作の ガイドライン (p. 566)」を参照してください。 Note AWS SDK には自動再試行ロジックとエクスポネンシャルバックオフが実装されています。 ほとんどのエクスポネンシャルバックオフアルゴリズムは、衝突の連続を防ぐためにジッター (ランダ ム化された遅延) を使用します。この場合は、そうした衝突を回避しようとしていないので、乱数を使 用する必要はありません。ただし、同時クライアントを使用すると、ジッターはリクエストを迅速に 処理する助けになります。詳細については、「Exponential Backoff and Jitter」のブログ投稿を参照し てください。 バッチオペレーションとエラー処理 DynamoDB 低レベル API は、バッチオペレーションの読み書きをサポートします。 BatchGetItem は、1 つ以上のテーブルからの項目の読み込み、BatchWriteItem は、1 つ以上のテーブルでの 項目の入力や削除に使用します。 これらのバッチオペレーションはバッチ以外の DynamoDB オペ レーションのラッパーとして実装されています。 つまり、BatchGetItem は、バッチの項目ごとに GetItem を一度呼び出します。 同様に、BatchWriteItem は、DeleteItem または PutItem を必 要に応じてバッチの項目ごとに呼び出します。 バッチオペレーションではバッチの個々のリクエストのエラーが許容されます。たとえば、5 つの項 目を読み込む BatchGetItem リクエストの場合を考えます。基礎となる GetItem リクエストの一部 が失敗した場合でも、BatchGetItem オペレーション全体が失敗することはありません。 一方、5 つ の項目の読み込みがすべて失敗した場合は、BatchGetItem 全体が失敗します。 バッチオペレーションでは、失敗した個々のリクエストについて情報が返されるため、問題を診断 し、オペレーションを再試行できます。BatchGetItem の場合、問題のあるテーブルとプライマリ キーがリクエストの UnprocessedKeys パラメーターで返されます。BatchWriteItem の場合、同 様の情報は UnprocessedItems で返されます。 読み込みまたは書き込みの失敗の原因として最も可能性が高いのは、帯域幅調整で す。BatchGetItem の場合、バッチリクエストの 1 つ以上のテーブルに、オペレーションをサポート するための十分なプロビジョンド読み込みキャパシティーがなくなります。BatchWriteItem の場 合、1 つ以上のテーブルに、十分なプロビジョンド書き込みキャパシティーがなくなります。 DynamoDB によって未処理の項目が返された場合は、それらの項目に対してバッチオペレーションを 再試行する必要があります。ただし、エクスポネンシャルバックオフアルゴリズムを使用することを 強くお勧めします。すぐにバッチオペレーションを再試行した場合、基礎となる読み込みまたは書き API Version 2012-08-10 77 Amazon DynamoDB 開発者ガイド DynamoDB 用の高レベルプロ グラミングインターフェイス 込みリクエストはやはり、個々のテーブルに対する帯域幅調整により失敗することがあります。エク スポネンシャルバックオフアルゴリズムを使用してバッチオペレーションを遅らせた場合は、バッチ の個々のリクエストが成功する可能性がはるかに高くなります。 DynamoDB 用の高レベルプログラミングイン ターフェイス AWS SDK は、Amazon DynamoDB を操作するための低レベルインターフェイスをアプリケーション に提供します。このクライアント側の クラスとメソッドは、低レベルの DynamoDB API に直接対応 しています。ただし、多くの開発者は、複雑なデータ型をデータベーステーブルの項目にマッピング する必要があるときに、切断、つまり "インピーダンス不整合" を感じています。低レベルデータベー ス インターフェイスでは、開発者は、データベーステーブルからオブジェクトデータを読み込むまた は書き込むメソッド、およびその反対の読み込みまたは書き込みを行うメソッドを記述する必要があ ります。オブジェクト型とデータベーステーブルの組み合わせごとに別途必要なコードの量は、対処 しきれないほど多いように思われます。 開発を簡素化するために、AWS SDK for Java と AWS SDK for .NET には、高レベルの抽象化を備え た別のインターフェイスが用意されています。DynamoDB 用の高レベルインターフェイスにより、プ ログラムのオブジェクトと、そのオブジェクトのデータを格納するデータベーステーブルとの間の関 係を定義できます。このマッピングを定義した後に、save、load、delete などの単純なオブジェク トメソッドを呼び出すと、下位の低レベル DynamoDB オペレーションが自動的に呼び出されます。 これにより、データベース中心のコードではなく、オブジェクト中心のコードを記述できます。 DynamoDB 用の高レベルプログラミングインターフェイスは、AWS SDK for Java と AWS SDK for .NET に用意されています。 Java • Java: DynamoDBMapper (p. 78) .NET • .NET ドキュメントモデル (p. 116) • .NET: オブジェクト永続性モデル (p. 138) Java: DynamoDBMapper トピック • サポートされているデータの種類 (p. 81) • DynamoDB 用の Java 注釈 (p. 82) • DynamoDBMapper クラス (p. 87) • DynamoDBMapper のオプションの設定 (p. 94) • 例: CRUD オペレーション (p. 95) • 例: バッチ書き込みオペレーション (p. 97) • 例: クエリおよびスキャン (p. 102) • バージョン番号を使用したオプティミスティックロック (p. 110) • 任意データのマッピング (p. 112) AWS SDK for Java は DynamoDBMapper クラスを提供し、クライアント側クラスを DynamoDB テー ブルにマッピングできるようにします。DynamoDBMapper を使用するには、DynamoDB テーブル内 API Version 2012-08-10 78 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper の項目と、コードの対応するオブジェクトインスタンス間の関係を定義します。DynamoDBMapper ク ラスでは、テーブルへのアクセス、さまざまな作成、読み取り、更新、削除 (CRUD) オペレーション の実行、およびクエリを行うことができます。 Note DynamoDBMapperクラスでは、テーブルを作成、更新、または削除することはできません。 これらのタスクを実行するには、代わりに低レベル SDK for Java インターフェイスを使用し ます。詳細については、「テーブルの操作 : Java (p. 186)」を参照してください。 SDK for Java には一連の注釈タイプが用意されているので、クラスをテーブルにマッピングできま す。たとえば、Id がパーティションキーになった ProductCatalog テーブルがあるとします。 ProductCatalog(Id, ...) 次の Java コードに示すように、クライアントアプリケーション内のクラスを ProductCatalog テーブ ルにマッピングすることができます。このコードスニペットでは、CatalogItem という名前の Plain Old Java Object (POJO) を定義しています。このオブジェクトは、注釈を使用して、オブジェクト フィールドを DynamoDB 属性名にマッピングします。 package com.amazonaws.codesamples; import java.util.Set; import import import import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIgnore; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; @DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { private private private private private Integer id; String title; String ISBN; Set<String> bookAuthors; String someProp; @DynamoDBHashKey(attributeName="Id") public Integer getId() { return id;} public void setId(Integer id) {this.id = id;} @DynamoDBAttribute(attributeName="Title") public String getTitle() {return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="ISBN") public String getISBN() { return ISBN; } public void setISBN(String ISBN) { this.ISBN = ISBN; } @DynamoDBAttribute(attributeName = "Authors") public Set<String> getBookAuthors() { return bookAuthors; } public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; } @DynamoDBIgnore public String getSomeProp() { return someProp;} API Version 2012-08-10 79 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper public void setSomeProp(String someProp) {this.someProp = someProp;} } 前述のコードでは、@DynamoDBTable 注釈によって、CatalogItem クラスが ProductCatalog テー ブルにマッピングされています。個々のクラスインスタンスは、テーブル内の項目として格納できま す。クラス定義では、@DynamoDBHashKey 注釈によって Id プロパティがプライマリキーにマッピン グされます。 デフォルトでは、クラスプロパティはテーブル内の同じ名前属性にマッピングされます。プロパティ Title および ISBN は、テーブル内の同じ名前属性にマッピングされます。 対応する項目の属性名に一致しないクラスプロパティ名を定義した場合は、@DynamoDBAttribute 注釈を明示的に追加して、マッピングを指定する必要があります。前述の例では、各プロパティに @DynamoDBAttribute 注釈を追加することで、プロパティ名が「テーブルの作成とサンプルデータ のロード (p. 166)」で作成したテーブルに確実に一致し、このガイド内の他のコード例で使用されて いる属性名との整合性がとられています。 クラス定義には、テーブル内のどの属性にもマッピングされないプロパティを含めることもで きます。これらのプロパティを特定するには、@DynamoDBIgnore 注釈を追加します。前述 の例では、SomeProp プロパティが @DynamoDBIgnore 注釈によってマーキングされていま す。CatalogItem インスタンスをテーブルにアップロードしたとき、DynamoDBMapper インスタン スに SomeProp プロパティは追加されません。また、このマッパーは、テーブルから項目を取り出す ときにこの属性を返しません。 マッピングクラスを定義した後で、DynamoDBMapper メソッドを使用して、そのクラスのインスタン スを Catalog テーブルの対応する項目に書き込むことができます。次のコードスニペットは、この手 法を示しています。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(new ProfileCredentialsProvider()); DynamoDBMapper mapper = new DynamoDBMapper(client); CatalogItem item = new CatalogItem(); item.setId(102); item.setTitle("Book 102 Title"); item.setISBN("222-2222222222"); item.setBookAuthors(new HashSet<String>(Arrays.asList("Author 1", "Author 2"))); item.setSomeProp("Test"); mapper.save(item); 次のコードスニペットでは、項目を取り出し、その属性の一部にアクセスする方法を示します。 CatalogItem partitionKey = new CatalogItem(); partitionKey.setId(102); DynamoDBQueryExpression<CatalogItem> queryExpression = new DynamoDBQueryExpression<CatalogItem>() .withHashKeyValues(partitionKey); List<CatalogItem> itemList = mapper.query(CatalogItem.class, queryExpression); for (int i = 0; i < itemList.size(); i++) { System.out.println(itemList.get(i).getTitle()); System.out.println(itemList.get(i).getBookAuthors()); API Version 2012-08-10 80 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper } DynamoDBMapper は、Java 内で DynamoDB データを操作するための直観的で自然な方法を提供しま す。また、オプティミスティックロック、自動生成されるパーティションキーとソートキーの値、オ ブジェクトのバージョニングなど、複数の組み込み機能があります。 サポートされているデータの種類 このセクションでは、サポートされているプリミティブな Java データ型、コレクション、および任 意データ型について説明します。 DynamoDB では、次のプリミティブなデータ型とプリミティブなラッパークラスがサポートされてい ます。 • String • Boolean, boolean • Byte, byte • Date(ISO8601 ミリ秒精度文字列、UTC に転換) • Calendar(ISO8601 ミリ秒精度文字列、UTC に転換) • Long, long • Integer, int • Double, double • Float, float • BigDecimal • BigInteger DynamoDB では、Java Set コレクションタイプがサポートされています。マッピングされているコレ クションのプロパティが Set ではない場合には、例外がスローされます。 次の表に、前述の Java 型が DynamoDB 型にどのようにマッピングされるかを示します。 Java 型 DynamoDB の型 すべての数値型 N(数値型) 文字列 S (文字列型) Boolean N (数値型)、0 または 1。 または、@DynamoDBNativeBooleanType を 使用して Java のブール型を DynamoDB BOOL データ型にマッピングできます。詳細について は、「DynamoDB 用の Java 注釈 (p. 82)」を 参照してください。 ByteBuffer B(バイナリ型) 日付 S(文字列型)。Date の値は、ISO-8601 形式の 文字列として格納されます。 Set コレクション型 SS(文字列セット)型、NS(数値セット)型、 または BS(バイナリセット)型。 また、SDK for Java は DynamoDB 用の任意のデータ型のマッピングもサポートしています。たとえ ば、クライアントで独自の複合型を定義できます。複合型に対して DynamoDBMarshaller インター API Version 2012-08-10 81 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper フェイスと @DynamoDBMarshalling 注釈を使用して、マッピングを記述します (任意データのマッ ピング (p. 112))。 DynamoDB 用の Java 注釈 このセクションでは、クラスとプロパティをテーブルと属性にマッピングするときに使用できる注釈 について説明します。 対応する Javadoc ドキュメントについては、「AWS SDK for Java API Reference」の「Annotation Types Summary」を参照してください。 Note 次の注釈では、DynamoDBTable と DynamoDBHashKey だけが必須です。 トピック • DynamoDBAttribute (p. 82) • DynamoDBAutoGeneratedKey (p. 82) • DynamoDBDocument (p. 83) • DynamoDBHashKey (p. 84) • DynamoDBIgnore (p. 85) • DynamoDBIndexHashKey (p. 85) • DynamoDBIndexRangeKey (p. 85) • DynamoDBMarshalling (p. 85) • DynamoDBNativeBoolean (p. 85) • DynamoDBRangeKey (p. 86) • DynamoDBTable (p. 86) • DynamoDBVersionAttribute (p. 87) DynamoDBAttribute テーブルの属性にプロパティをマッピングします。デフォルトでは、各クラスのプロパティ が、同じ名前の項目属性にマッピングされます。ただし名前が同じでない場合は、この注釈を 使用して属性にプロパティをマッピングすることができます。次の Java コードスニペットで は、DynamoDBAttribute によって、BookAuthors プロパティがテーブル内の 属性名にマッピング されています。Authors @DynamoDBAttribute(attributeName = "Authors") public List<String> getBookAuthors() { return BookAuthors; } public void setBookAuthors(List<String> BookAuthors) { this.BookAuthors = BookAuthors; } DynamoDBMapper では、テーブルにオブジェクトを保存する際に、 を属性名として使用していま す。Authors DynamoDBAutoGeneratedKey パーティションキーまたはソートキーのプロパティは、自動生成済みとしてマーキングされま す。DynamoDBMapper は、これらの属性を保存するときにランダムな UUID を生成します。String プ ロパティには、自動生成済みのキーとしてマーキングできます。 次のスニペットは、自動生成されたキーの使用方法を示しています。 @DynamoDBTable(tableName="AutoGeneratedKeysExample") API Version 2012-08-10 82 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper public class AutoGeneratedKeys { private String id; private String payload; @DynamoDBHashKey(attributeName = "Id") @DynamoDBAutoGeneratedKey public String getId() { return id; } public void setId(String id) { this.id = id; } @DynamoDBAttribute(attributeName="payload") public String getPayload() { return this.payload; } public void setPayload(String payload) { this.payload = payload; } public static void saveItem() { AutoGeneratedKeys obj = new AutoGeneratedKeys(); obj.setPayload("abc123"); // id field is null at this point DynamoDBMapper mapper = new DynamoDBMapper(dynamoDBClient); mapper.save(obj); System.out.println("Object was saved with id " + obj.getId()); } } DynamoDBDocument DynamoDB ドキュメントとしてシリアル化できるクラスを示します。 たとえば、JSON ドキュメントをマップ型 (M) の DynamoDB 属性にマッピングしたいとします。次の コードスニペットでは、マップ型の入れ子の属性 (Pictures) を含む項目を定義します。 public class ProductCatalogItem { private Integer id; //partition key private Pictures pictures; /* ...other attributes omitted... */ @DynamoDBHashKey(attributeName="Id") public Integer getId() { return id;} public void setId(Integer id) {this.id = id;} @DynamoDBAttribute(attributeName="Pictures") public Pictures getPictures() { return pictures;} public void setPictures(Pictures pictures) {this.pictures = pictures;} // Additional properties go here. @DynamoDBDocument public static class Pictures { private String frontView; private String rearView; private String sideView; @DynamoDBAttribute(attributeName = "FrontView") public String getFrontView() { return frontView; } public void setFrontView(String frontView) { this.frontView = frontView; } API Version 2012-08-10 83 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper @DynamoDBAttribute(attributeName = "RearView") public String getRearView() { return rearView; } public void setRearView(String rearView) { this.rearView = rearView; } @DynamoDBAttribute(attributeName = "SideView") public String getSideView() { return sideView; } public void setSideView(String sideView) { this.sideView = sideView; } } } 次に、次のコードスニペットに示すように、新しい ProductCatalog 項目を、Pictures とともに保存で きます。 ProductCatalogItem item = new ProductCatalogItem(); Pictures pix = new Pictures(); pix.setFrontView("http://example.com/products/206_front.jpg"); pix.setRearView("http://example.com/products/206_rear.jpg"); pix.setSideView("http://example.com/products/206_left_side.jpg"); item.setPictures(pix); item.setId(123); mapper.save(item); その結果、ProductCatalog 項目は次のようになります (JSON 形式)。 { "Id" : 123 "Pictures" : { "SideView" : "http://example.com/products/206_left_side.jpg", "RearView" : "http://example.com/products/206_rear.jpg", "FrontView" : "http://example.com/products/206_front.jpg" } } DynamoDBHashKey テーブルのパーティションキーにクラスプロパティをマッピングします。このプロパティは、スカ ラー文字列型、数値型、バイナリ型のいずれかである必要があります。コレクション型は使用できま せん。 Id がプライマリキーである ProductCatalog テーブルがあるとします。次の Java コードスニペット では、CatalogItem クラスを定義し、その Id プロパティを @DynamoDBHashKey タグを使用して ProductCatalog テーブルのプライマリキーにマッピングしています。 @DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { private Integer Id; @DynamoDBHashKey(attributeName="Id") public Integer getId() { return Id; API Version 2012-08-10 84 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper } public void setId(Integer Id) { this.Id = Id; } // Additional properties go here. } DynamoDBIgnore DynamoDBMapper インスタンスに対して、関連するプロパティを無視するように指示します。テーブ ルにデータを保存する場合、DynamoDBMapper ではこのプロパティがテーブルに保存されません。 DynamoDBIndexHashKey グローバルセカンダリインデックスのパーティションキーにクラスプロパティをマッピングします。 このプロパティは、スカラー文字列型、数値型、バイナリ型のいずれかである必要があります。コレ クション型は使用できません。 この注釈は、グローバルセカンダリインデックスの Query を実行する必要がある場合に使用しま す。インデックス名(globalSecondaryIndexName)を指定する必要があります。クラスプロ パティの名前がインデックスのパーティションキーと異なる場合、そのインデックス属性の名前 (attributeName) も指定する必要があります。 DynamoDBIndexRangeKey グローバルセカンダリインデックスまたはlocal secondary indexのソートキーにクラスプロパティを マッピングします。このプロパティは、スカラー文字列型、数値型、バイナリ型のいずれかである必 要があります。コレクション型は使用できません。 この注釈は、local secondary indexまたはグローバルセカンダリインデックスの Query を実行 し、インデックスキーを使用して結果を絞り込む必要がある場合に使用します。インデックス名 (globalSecondaryIndexName または localSecondaryIndexName)を指定する必要がありま す。クラスプロパティの名前がインデックスのソートキーと異なる場合、そのインデックス属性の名 前 (attributeName) も指定する必要があります。 DynamoDBMarshalling カスタムマーシャラーを使用するクラスプロパティを識別します。この注釈を DynamoDBMarshaller クラスと一緒に使用すると、独自の任意のデータ型を DynamoDB によって ネイティブにサポートされているデータ型にマッピングできます。詳細については、「任意データの マッピング (p. 112)」を参照してください。 DynamoDBNativeBoolean クラスの boolean (または Boolean) 属性を、ネイティブな DynamoDB BOOL データ型として扱うこ とを示します。 たとえば、CatalogItem を使用して、ProductCatalog テーブルに項目をマッピングするこ とができます。属性 (InStock) の 1 つをブール型としてモデリングするには、次のように DynamoDBNativeBoolean 注釈を使用します。 @DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { private String Id; private Boolean inStock; API Version 2012-08-10 85 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper @DynamoDBHashKey(attributeName="Id") // Getters and setters for Id go here @DynamoDBNativeBoolean @DynamoDBAttribute(attributeName = "InStock") public boolean getInStock() { return inStock; } public void setInStock(boolean inStock) { this.inStock = inStock; } // Additional properties go here. } Note 以前のバージョンの DynamoDBMapper で、ブール属性は DynamoDB の Number データ型 (N) として表され、1 は true、0 は false と解釈されました。テーブルからデータを読み込むす べてのアプリケーションが、更新されたバージョンの DynamoDBMapper を使用していない限 り、DynamoDBNativeBoolean の注釈を使用しないでください。 DynamoDBRangeKey テーブルのソートキーにクラスプロパティをマッピングします。このプロパティは、スカラー文字列 型、数値型、バイナリ型のいずれかである必要があります。コレクション型は使用できません。 プライマリキーが複合の場合 (パーティションキーとソートキー)、このタグを使用して、クラス フィールドをソートキーにマッピングできます。たとえば、フォーラムスレッドからの返信を格納す る Reply テーブルがあるとします。各スレッドには多数の返信がある可能性があります。したがって このテーブルのプライマリキーは、ThreadId と ReplyDateTime の両方になります。ThreadId がパー ティションキーで、ReplyDateTime がソートキーです。次の Java コードスニペットでは、Reply ク ラスを定義して Reply テーブルにマッピングしています。ここでは、@DynamoDBHashKey タグと @DynamoDBRangeKey タグの両方を使用して、プライマリキーにマッピングされるクラスプロパティ を識別しています。 @DynamoDBTable(tableName="Reply") public class Reply { private Integer id; private String replyDateTime; @DynamoDBHashKey(attributeName="Id") public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @DynamoDBRangeKey(attributeName="ReplyDateTime") public String getReplyDateTime() { return replyDateTime; } public void setReplyDateTime(String replyDateTime) { this.replyDateTime = replyDateTime; } // Additional properties go here. } DynamoDBTable DynamoDB でターゲットテーブルを識別します。たとえば次の Java コードスニペットで は、Developer クラスを定義して、DynamoDB の People テーブルにマッピングしています。 @DynamoDBTable(tableName="People") public class Developer { ...} API Version 2012-08-10 86 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper @DynamoDBTable 注釈は継承できます。Developer クラスから継承された新しいクラスも、People テーブルにマッピングされます。たとえば、Developer クラスから継承された Lead クラスを作成し たとします。Developer クラスを People テーブルにマッピングしたことで、Lead クラスオブジェ クトも同じテーブルに格納されます。 @DynamoDBTable もオーバーライドできます。デフォルトで Developer クラスから継承された新し いクラスは、同じ People テーブルにマッピングされます。ただし、このデフォルトのマッピングは オーバーライドできます。たとえば、Developer クラスから継承したクラスを作成した場合には、次 の Java コードスニペットに示すように、@DynamoDBTable 注釈を追加することで、別のテーブルに 明示的にマッピングできます。 @DynamoDBTable(tableName="Managers") public class Manager extends Developer { ...} DynamoDBVersionAttribute オプティミスティックロックのバージョン番号を格納するためのクラスプロパティを識別しま す。DynamoDBMapper は、新しい項目を保存するときにこのプロパティにバージョン番号を割り当 てます。バージョン番号は項目を更新するたびに増えていきます。サポートされているのは番号によ るスカラー型だけです。データ型の詳細については、「データ型 (p. 12)」を参照してください。バー ジョニングの詳細については、「バージョン番号を使用したオプティミスティックロック (p. 110)」 を参照してください。 DynamoDBMapper クラス DynamoDBMapper クラスは、DynamoDB のエントリポイントです。このクラスから DynamoDB エ ンドポイントにアクセスして、各種のテーブル内のデータにアクセスし、項目に対してさまざまな CRUD オペレーションを実行し、テーブルに対するクエリやスキャンを実行することができます。こ のクラスは、DynamoDB を操作するために以下のメソッドを提供します。 対応する Javadoc ドキュメントについては、『AWS SDK for Java API Reference』の 「DynamoDBMapper」を参照してください。 トピック • save (p. 88) • load (p. 88) • delete (p. 88) • query (p. 88) • queryPage (p. 90) • scan (p. 90) • scanPage (p. 91) • parallelScan (p. 91) • batchSave (p. 92) • batchLoad (p. 92) • batchDelete (p. 92) • batchWrite (p. 93) • count (p. 93) • generateCreateTableRequest (p. 93) • createS3Link (p. 93) • getS3ClientCache (p. 94) API Version 2012-08-10 87 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper save 指定したオブジェクトがテーブルに保存されます。このメソッドで必要なパラメータは、保存するオ ブジェクトだけです。DynamoDBMapperConfig オブジェクトを使用して、オプションの設定パラ メータを入力できます。 同じプライマリキーを持つ項目が存在しない場合は、このメソッドによってテーブル内に新しい項 目が作成されます。同じプライマリキーを持つ項目が存在する場合は、その既存の項目が更新されま す。パーティションキーとソートキーが String 型で、@DynamoDBAutoGeneratedKey によって注釈 が付けられている場合、初期化しなければ、ランダムな UUID (Universally Unique Identifier) が与えら れます。@DynamoDBVersionAttribute によって注釈が付けられたバージョンフィールドは、バー ジョンが 1 ずつ増えていきます。さらに、バージョンフィールドが更新されるかキーが生成される と、オペレーションの結果として、渡されたオブジェクトが更新されます。 デフォルトでは、マッピングされたクラスプロパティに対応する属性だけが更新されます。項目に含 まれるその他の既存の属性は更新されません。ただし、SaveBehavior.CLOBBER を指定すると、項 目が完全に上書きされるようにすることができます。 mapper.save(obj, new DynamoDBMapperConfig(DynamoDBMapperConfig.SaveBehavior.CLOBBER)); バージョニングを有効にした場合は、クライアント側とサーバー側で項目のバージョンが一致する必 要があります。ただし、SaveBehavior.CLOBBER オプションを使用する場合は、バージョンを一致 させる必要はありません。バージョニングの詳細については、「バージョン番号を使用したオプティ ミスティックロック (p. 110)」を参照してください。 load テーブルから項目を取り出します。取り出す項目のプライマリキーを入力する必要がありま す。DynamoDBMapperConfig オブジェクトを使用して、オプションの設定パラメータを入力できま す。たとえば次の Java ステートメントに示すように、オプションで強力な整合性のある読み込みを リクエストして、このメソッドによって最新の項目の値だけを取り出すようにすることができます。 CatalogItem item = mapper.load(CatalogItem.class, item.getId(), new DynamoDBMapperConfig(DynamoDBMapperConfig.ConsistentReads.CONSISTENT)); デフォルトでは、DynamoDB では結果整合性のある値を持つ項目が返されます。DynamoDB の結果 整合性モデルの詳細については、「読み込み整合性 (p. 16)」を参照してください。 delete テーブルから項目を削除します。マッピングされたクラスのオブジェクトインスタンスを渡す必要が あります。 バージョニングを有効にした場合は、クライアント側とサーバー側で項目のバージョンが一致する必 要があります。ただし、SaveBehavior.CLOBBER オプションを使用する場合は、バージョンを一致 させる必要はありません。バージョニングの詳細については、「バージョン番号を使用したオプティ ミスティックロック (p. 110)」を参照してください。 query テーブルまたはセカンダリインデックスのクエリを実行します。複合プライマリキー (パーティショ ンキーおよびソートキー) が存在する場合にのみ、テーブルまたはインデックスにクエリを実行できま す。このメソッドでは、ソートキーに適用されるパーティションキー値とクエリフィルタを指定する 必要があります。フィルタ式には、条件と値が含まれています。 API Version 2012-08-10 88 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper フォーラムスレッドの返信を格納する Reply というテーブルがあるとします。各スレッドの件名 については、0 以上の返信を受け取ることができます。Reply テーブルのプライマリキーは、Id および ReplyDateTime フィールドで構成されます。Id がプライマリキーのパーティションキー で、ReplyDateTime がソートキーです。 Reply ( Id, ReplyDateTime, ... ) ここで、Reply クラスと DynamoDB の対応する Reply テーブル間のマッピングを作成したとします。 次の Java コードスニペットでは、DynamoDBMapper を使用して特定のスレッド件名に対する過去 2 週間のすべての返信を検索しています。 String forumName = "DynamoDB"; String forumSubject = "DynamoDB Thread 1"; String partitionKey = forumName + "#" + forumSubject; long twoWeeksAgoMilli = (new Date()).getTime() - (14L*24L*60L*60L*1000L); Date twoWeeksAgo = new Date(); twoWeeksAgo.setTime(twoWeeksAgoMilli); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); String twoWeeksAgoStr = df.format(twoWeeksAgo); Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":v1", new AttributeValue().withS(partitionKey)); eav.put(":v2",new AttributeValue().withS(twoWeeksAgoStr.toString())); DynamoDBQueryExpression<Reply> queryExpression = new DynamoDBQueryExpression<Reply>() .withKeyConditionExpression("Id = :v1 and ReplyDateTime > :v2") .withExpressionAttributeValues(eav); List<Reply> latestReplies = mapper.query(Reply.class, queryExpression); このクエリでは、Reply オブジェクトのコレクションが返されます。 デフォルトでは、query メソッドによって、「遅延ロード」されたコレクションが返されます。最初 に結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われ ます。一致するすべての項目は、latestReplies コレクションを反復的に処理するだけで取得でき ます。 インデックスにクエリを実行するには、最初にインデックスをマッパークラスとしてモデリングする 必要があります。Reply テーブルに、PostedBy-Message-Index という名前のグローバルセカンダリ インデックスがあるとします。このインデックスのパーティションキーは PostedBy キーで、ソート キーは Message です。インデックス内の項目のクラス定義は次のようになります。 @DynamoDBTable(tableName="Reply") public class PostedByMessage { private String postedBy; private String message; @DynamoDBIndexHashKey(globalSecondaryIndexName = "PostedBy-MessageIndex", attributeName = "PostedBy") public String getPostedBy() { return postedBy; } public void setPostedBy(String postedBy) { this.postedBy = postedBy; } @DynamoDBIndexRangeKey(globalSecondaryIndexName = "PostedBy-MessageIndex", attributeName = "Message") API Version 2012-08-10 89 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } // Additional properties go here. } @DynamoDBTable 注釈は、このインデックスが Reply テーブルに関連付けられていることを示 します。@DynamoDBIndexHashKey 注釈はインデックスのパーティションキー (PostedBy) を示 し、@DynamoDBIndexRangeKey はインデックスのソートキー (Message) を示します。 ここで、DynamoDBMapper を使用してインデックスにクエリを実行し、特定のユーザーによって 投稿されたメッセージのサブセットを取得できます。クエリを実行するインデックスを DynamoDB に知らせるため、withIndexName を指定する必要があります。次のコードスニペットでは、グ ローバルセカンダリインデックスにクエリを実行します。グローバルセカンダリインデックスは結 果的に整合性のある読み込みをサポートしますが、強い整合性のある読み込みをサポートしないた め、withConsistentRead(false) を指定する必要があります。 HashMap<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":v1", new AttributeValue().withS("User A")); eav.put(":v2", new AttributeValue().withS("DynamoDB")); DynamoDBQueryExpression<PostedByMessage> queryExpression = new DynamoDBQueryExpression<PostedByMessage>() .withIndexName("PostedBy-Message-Index") .withConsistentRead(false) .withKeyConditionExpression("PostedBy = :v1 and begins_with(Message, :v2)") .withExpressionAttributeValues(eav); List<PostedByMessage> iList = queryExpression); mapper.query(PostedByMessage.class, このクエリでは、PostedByMessage オブジェクトのコレクションが返されます。 queryPage テーブルまたはセカンダリインデックスのクエリを実行し、一致する結果を 1 ページ返しま す。query メソッドと同様、パーティションキー値とソートキー属性に適用されるクエリフィルタを 指定する必要があります。ただし、queryPage では、データの最初の "ページ"、つまり、1 MB 内に 収まるデータ量だけが返されます。 scan テーブル全体またはセカンダリインデックスがスキャンされます。オプションで FilterExpression を指定して結果セットをフィルタリングできます。 フォーラムスレッドの返信を格納する Reply というテーブルがあるとします。各スレッドの件名 については、0 以上の返信を受け取ることができます。Reply テーブルのプライマリキーは、Id および ReplyDateTime フィールドで構成されます。Id がプライマリキーのパーティションキー で、ReplyDateTime がソートキーです。 Reply ( Id, ReplyDateTime, ... ) Reply テーブルに Java クラスをマッピングした場合は、DynamoDBMapper を使用してテーブルをス キャンできます。たとえば、以下の Java コードスニペットは、Reply テーブル全体をスキャンし、 特定の年の返信のみを返します。 API Version 2012-08-10 90 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper HashMap<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":v1", new AttributeValue().withS("2015")); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withFilterExpression("begins_with(ReplyDateTime,:v1)") .withExpressionAttributeValues(eav); List<Reply> replies = mapper.scan(Reply.class, scanExpression); デフォルトでは、scan メソッドによって、「遅延ロード」されたコレクションが返されます。最初に 結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われま す。一致するすべての項目は、replies コレクションを反復的に処理するだけで取得できます。 インデックスをスキャンするには、最初にインデックスをマッパークラスとしてモデリングする必要 があります。Reply テーブルに、PostedBy-Message-Index という名前のグローバルセカンダリイン デックスがあるとします。このインデックスのパーティションキーは PostedBy キーで、ソートキー は Message です。このインデックスのマッパークラスを「query (p. 88)」セクションに示しま す。ここで、@DynamoDBIndexHashKey および @DynamoDBIndexRangeKey 注釈を使用して、イン デックスパーティションキーとソートキーを指定します。 次のコードスニペットは、PostedBy-Message-Index をスキャンします。スキャンフィルタを使用し ないので、インデックス内のすべての項目が返されます。 DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withIndexName("PostedBy-Message-Index") .withConsistentRead(false); List<PostedByMessage> indexItems = mapper.scan(PostedByMessage.class, scanExpression); Iterator<PostedByMessage> indexItems = iList.iterator(); scanPage テーブルまたはセカンダリインデックスがスキャンされ、一致する結果が 1 ページ返されます。scan メソッドと同様に、オプションで FilterExpression を指定して結果セットをフィルタリングでき ます。ただし、scanPage では、データの最初の "ページ"、つまり、1 MB 内に収まるデータ量だけが 返されます。 parallelScan テーブルまたはセカンダリインデックス全体の並列スキャンが実行されます。テーブルの論理セグメ ントの数と、結果をフィルタするスキャン式を指定します。parallelScan では、スキャンタスク が複数のワーカーに分割され、論理セグメントごとに 1 つのワーカーが割り当てられます。ワーカー は、データを並列に処理し、結果を返します。 次の Java コードスニペットでは、Product テーブルに対して並列スキャンを実行します。 int numberOfThreads = 4; Map<String, AttributeValue> eav = new HashMap<String, AttributeValue> (); eav.put(":n", new AttributeValue().withN("100")); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withFilterExpression("Price >= :n") .withExpressionAttributeValues(eav); API Version 2012-08-10 91 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper List<Product> scanResult = mapper.parallelScan(Product.class, scanExpression, numberOfThreads); parallelScan の使い方を示す Java コードサンプルについては、「例: クエリおよびスキャ ン (p. 102)」を参照してください。 batchSave AmazonDynamoDB.batchWriteItem メソッドに対する 1 つ以上の呼び出しを使用して、1 つ以上の テーブルにオブジェクトを保存します。このメソッドでは、トランザクション保証はなされません。 次の Java コードスニペットでは、2 つの項目(書籍)が ProductCatalog テーブルに保存されていま す。 Book book1 = new Book(); book1.id = 901; book1.productCategory = "Book"; book1.title = "Book 901 Title"; Book book2 = new Book(); book2.id = 902; book2.productCategory = "Book"; book2.title = "Book 902 Title"; mapper.batchSave(Arrays.asList(book1, book2)); batchLoad テーブルのプライマリキーを使用して、1 つ以上のテーブルから複数の項目を取り出します。 次の Java コードスニペットでは、2 つの異なるテーブルから 2 つの項目を取り出します。 ArrayList<Object> itemsToGet = new ArrayList<Object>(); ForumItem forumItem = new ForumItem(); forumItem.setForumName("Amazon DynamoDB"); itemsToGet.add(forumItem); ThreadItem threadItem = new ThreadItem(); threadItem.setForumName("Amazon DynamoDB"); threadItem.setSubject("Amazon DynamoDB thread 1 message text"); itemsToGet.add(threadItem); Map<String, List<Object>> items = mapper.batchLoad(itemsToGet); batchDelete AmazonDynamoDB.batchWriteItem メソッドに対する 1 つ以上の呼び出しを使用して、1 つ以上 のテーブルからオブジェクトを削除します。このメソッドでは、トランザクション保証はなされませ ん。 次の Java コードスニペットでは、2 つの項目(書籍)が ProductCatalog テーブルから削除されてい ます。 Book book1 = mapper.load(Book.class, 901); Book book2 = mapper.load(Book.class, 902); mapper.batchDelete(Arrays.asList(book1, book2)); API Version 2012-08-10 92 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper batchWrite AmazonDynamoDB.batchWriteItem メソッドに対する 1 つ以上の呼び出しを使用して、1 つ以上の テーブルに対してオブジェクトの保存および削除を行います。このメソッドではトランザクション保 証はなされず、バージョニング(条件付き入力または削除)もサポートされません。 次の Java コードスニペットでは、新しい項目が Forum テーブルと Thread テーブルに書き込ま れ、ProductCatalog テーブルから項目が削除されています。 // Create a Forum item to save Forum forumItem = new Forum(); forumItem.name = "Test BatchWrite Forum"; // Create a Thread item to save Thread threadItem = new Thread(); threadItem.forumName = "AmazonDynamoDB"; threadItem.subject = "My sample question"; // Load a ProductCatalog item to delete Book book3 = mapper.load(Book.class, 903); List<Object> objectsToWrite = Arrays.asList(forumItem, threadItem); List<Book> objectsToDelete = Arrays.asList(book3); mapper.batchWrite(objectsToWrite, objectsToDelete); count 指定されたスキャン式の値を求め、一致する項目数を返します。項目データは返されません。 generateCreateTableRequest DynamoDB テーブルを表す POJO クラスを解析し、そのテーブルの CreateTableRequest を返し ます。 createS3Link Amazon S3 のオブジェクトへのリンクを作成します。バケット名とキー名を指定する必要がありま す。キー名によって、バケット内のオブジェクトを一意に識別します。 createS3Link を使用するには、マッパークラスでゲッターメソッドとセッターメソッドを定義する 必要があります。次のコードスニペットでは、これを示しており、新しい属性とゲッター/セッターメ ソッドを CatalogItem クラスに追加しています。 @DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { ... public S3Link productImage; .... @DynamoDBAttribute(attributeName = "ProductImage") public S3Link getProductImage() { return productImage; } public void setProductImage(S3Link productImage) { API Version 2012-08-10 93 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper this.productImage = productImage; } ... } 次の Java コードでは、Product テーブルに書き込まれる新しい項目を定義しています。この項目に は、製品イメージへのリンクがあり、そのイメージデータは Amazon S3 にアップロードされていま す。 CatalogItem item = new CatalogItem(); item.id = 150; item.title = "Book 150 Title"; String myS3Bucket = "myS3bucket"; String myS3Key = "productImages/book_150_cover.jpg"; item.setProductImage(mapper.createS3Link(myS3Bucket, myS3Key)); item.getProductImage().uploadFrom(new File("/file/path/book_150_cover.jpg")); mapper.save(item); S3Link クラスには、他にも、Amazon S3 のオブジェクトを操作するためのさまざまなメソッドが用 意されています。詳細については、「Javadocs for S3Link」を参照してください。 getS3ClientCache Amazon S3 にアクセスするための基礎となる S3ClientCache を返します。S3ClientCache は、AmazonS3Client オブジェクトのスマートマップです。複数のクライアントがある場 合、S3ClientCache によって、リージョン別にクライアントを整理しやすくなり、新しい Amazon S3 クライアントをオンデマンドで作成できます。 DynamoDBMapper のオプションの設定 DynamoDBMapper のインスタンスを作成すると、そのインスタンスには、特定のデフォルトの動作が あります。DynamoDBMapperConfig クラスを使用して、このデフォルトの動作をオーバーライドで きます。 次のコードスニペットでは、カスタム設定を使用して DynamoDBMapper を作成します。 ClasspathPropertiesFileCredentialsProvider cp = new ClasspathPropertiesFileCredentialsProvider(); AmazonDynamoDBClient client = new AmazonDynamoDBClient(cp); DynamoDBMapperConfig mapperConfig = new DynamoDBMapperConfig( DynamoDBMapperConfig.SaveBehavior.CLOBBER, DynamoDBMapperConfig.ConsistentReads.CONSISTENT, null, //TableNameOverride - leaving this at default setting DynamoDBMapperConfig.PaginationLoadingStrategy.EAGER_LOADING ); DynamoDBMapper mapper = new DynamoDBMapper(client, mapperConfig, cp); 詳細については、「AWS SDK for Java API Reference」の「DynamoDBMapperConfig」を参照してく ださい。 API Version 2012-08-10 94 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper DynamoDBMapperConfig のインスタンスに対して、次の引数を指定できます。 • DynamoDBMapperConfig.ConsistentReads 列挙値: • EVENTUAL – マッパーインスタンスは、結果整合性のある読み込みリクエストを使用します。 • CONSISTENT – マッパーインスタンスは、強力な整合性のある読み込みリクエストを使用しま す。このオプションの設定は、load、query、または scan オペレーションに対して使用でき ます。強力な整合性のある読み込みは、パフォーマンスと請求に関連しています。詳細について は、DynamoDB の製品の詳細ページを参照してください。 マッパーインスタンスに読み込み整合性の設定を指定しない場合、デフォルトは EVENTUAL になり ます。 • DynamoDBMapperConfig.PaginationLoadingStrategy 列挙値 – query または scan からの結 果など、ページ分割されたデータのリストをマッパーインスタンスが処理する方法を制御します。 • LAZY_LOADING – マッパーインスタンスは、可能な限りデータをロードし、ロードされたすべて の結果をメモリに維持します。 • EAGER_LOADING – マッパーインスタンスは、リストが初期化されるとすぐにデータをロードし ます。 • ITERATION_ONLY – イテレータを使用する場合にのみ、リストから読み込むことができます。反 復中、リストは、前のすべての結果をクリアしてから、次のページをロードすることで、最大 1 ページのロードされた結果をメモリに維持するようにします。つまり、リストを反復できるのは 1 回だけです。メモリのオーバーヘッドを低減するために、大きい項目を処理するときにこの方 法を使用することをお勧めします。 マッパーインスタンスにページ分割ロードの方法を指定しない場合、デフォルトは LAZY_LOADING になります。 • DynamoDBMapperConfig.SaveBehavior 列挙値 – 保存オペレーション中にマッパーインスタン スが属性を処理する方法を指定します。 • UPDATE – 保存オペレーション中、すべてのモデル化された属性は更新され、モデル化されていな い属性は影響を受けません。プリミティブな数値型(byte、int、long)は 0 に設定されます。オ ブジェクト型は null に設定されます。 • CLOBBER – 保存オペレーション中、モデル化されていない属性も含め、すべての属性をクリア し、置き換えます。このオペレーションは、項目を削除し、再作成することで実行されます。ま た、バージョン付きフィールドの制約は無視されます。 マッパーインスタンスに保存動作を指定しない場合、デフォルトは UPDATE になります。 • DynamoDBMapperConfig.TableNameOverride オブジェクト – クラスの DynamoDBTable 注釈 によって指定されたテーブル名を無視し、代わりに、提供する別のテーブル名を使用するように マッパーインスタンスに指示します。これは、実行時にデータを複数のテーブルに分割する場合に 役立ちます。 必要に応じて、オペレーションごとに DynamoDBMapper のデフォルトの設定オブジェクトをオー バーライドできます。 例: CRUD オペレーション 次の Java コード例では、Id、Title、ISBN、および Authors プロパティを指定して、CatalogItem クラスを宣言しています。これらのプロパティは、注釈を使用して、DynamoDB の ProductCatalog テーブルにマッピングされています。このコード例では、次に DynamoDBMapper を使用して、書籍 オブジェクトを保存し、取り出し、更新し、書籍項目を削除します。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセク ションに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード 済みであることを前提としています。 API Version 2012-08-10 95 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper 以下の例を実行するための詳しい手順については、「Java コードサンプル (p. 171)」を参照 してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.datamodeling; import import import import java.io.IOException; java.util.Arrays; java.util.HashSet; java.util.Set; import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; public class DynamoDBMapperCRUDExample { static AmazonDynamoDBClient client = new AmazonDynamoDBClient(new ProfileCredentialsProvider()); public static void main(String[] args) throws IOException { testCRUDOperations(); System.out.println("Example complete!"); } @DynamoDBTable(tableName="ProductCatalog") public static class CatalogItem { private Integer id; private String title; private String ISBN; private Set<String> bookAuthors; //Partition key @DynamoDBHashKey(attributeName="Id") public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @DynamoDBAttribute(attributeName="Title") public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="ISBN") public String getISBN() { return ISBN; } public void setISBN(String ISBN) { this.ISBN = ISBN;} @DynamoDBAttribute(attributeName = "Authors") public Set<String> getBookAuthors() { return bookAuthors; } public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; } @Override public String toString() { API Version 2012-08-10 96 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper return "Book [ISBN=" + ISBN + ", bookAuthors=" + bookAuthors + ", id=" + id + ", title=" + title + "]"; } } private static void testCRUDOperations() { CatalogItem item = new CatalogItem(); item.setId(601); item.setTitle("Book 601"); item.setISBN("611-1111111111"); item.setBookAuthors(new HashSet<String>(Arrays.asList("Author1", "Author2"))); // Save the item (book). DynamoDBMapper mapper = new DynamoDBMapper(client); mapper.save(item); // Retrieve the item. CatalogItem itemRetrieved = mapper.load(CatalogItem.class, 601); System.out.println("Item retrieved:"); System.out.println(itemRetrieved); // Update the item. itemRetrieved.setISBN("622-2222222222"); itemRetrieved.setBookAuthors(new HashSet<String>(Arrays.asList("Author1", "Author3"))); mapper.save(itemRetrieved); System.out.println("Item updated:"); System.out.println(itemRetrieved); // Retrieve the updated item. DynamoDBMapperConfig config = new DynamoDBMapperConfig(DynamoDBMapperConfig.ConsistentReads.CONSISTENT); CatalogItem updatedItem = mapper.load(CatalogItem.class, 601, config); System.out.println("Retrieved the previously updated item:"); System.out.println(updatedItem); // Delete the item. mapper.delete(updatedItem); // Try to retrieve deleted item. CatalogItem deletedItem = mapper.load(CatalogItem.class, updatedItem.getId(), config); if (deletedItem == null) { System.out.println("Done - Sample item is deleted."); } } } 例: バッチ書き込みオペレーション 次の Java コード例では、Book、Forum、Thread、および Reply クラスが宣言さ れ、DynamoDBMapper クラスを使用して、DynamoDB テーブルにマッピングされています。 API Version 2012-08-10 97 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper このコードは、以下のバッチ書き込みオペレーションを示しています。 • ProductCatalog テーブルに書籍項目を入力する batchSave • ProductCatalog テーブルから項目を削除する batchDelete • Forum および Thread テーブルに対して項目を入力または削除する batchWrite この例で使用されているテーブルの詳細については、「テーブルの作成とサンプルデータのロー ド (p. 166)」を参照してください。次のサンプルをテストするための詳しい手順については、 「Java コードサンプル (p. 171)」を参照してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.datamodeling; import import import import import import java.text.SimpleDateFormat; java.util.ArrayList; java.util.Arrays; java.util.HashSet; java.util.List; java.util.Set; import import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; public class DynamoDBMapperBatchWriteExample { static AmazonDynamoDBClient client = new AmazonDynamoDBClient(new ProfileCredentialsProvider()); static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MMdd'T'HH:mm:ss.SSS'Z'"); public static void main(String[] args) throws Exception { try { DynamoDBMapper mapper = new DynamoDBMapper(client); testBatchSave(mapper); testBatchDelete(mapper); testBatchWrite(mapper); System.out.println("Example complete!"); } catch (Throwable t) { System.err.println("Error running the DynamoDBMapperBatchWriteExample: " + t); t.printStackTrace(); } } private static void testBatchSave(DynamoDBMapper mapper) { API Version 2012-08-10 98 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper Book book1 = new Book(); book1.id = 901; book1.inPublication = true; book1.ISBN = "902-11-11-1111"; book1.pageCount = 100; book1.price = 10; book1.productCategory = "Book"; book1.title = "My book created in batch write"; Book book2 = new Book(); book2.id = 902; book2.inPublication = true; book2.ISBN = "902-11-12-1111"; book2.pageCount = 200; book2.price = 20; book2.productCategory = "Book"; book2.title = "My second book created in batch write"; Book book3 = new Book(); book3.id = 903; book3.inPublication = false; book3.ISBN = "902-11-13-1111"; book3.pageCount = 300; book3.price = 25; book3.productCategory = "Book"; book3.title = "My third book created in batch write"; System.out.println("Adding three books to ProductCatalog table."); mapper.batchSave(Arrays.asList(book1, book2, book3)); } private static void testBatchDelete(DynamoDBMapper mapper) { Book book1 = mapper.load(Book.class, 901); Book book2 = mapper.load(Book.class, 902); System.out.println("Deleting two books from the ProductCatalog table."); mapper.batchDelete(Arrays.asList(book1, book2)); } private static void testBatchWrite(DynamoDBMapper mapper) { // Create Forum item to save Forum forumItem = new Forum(); forumItem.name = "Test BatchWrite Forum"; forumItem.threads = 0; forumItem.category = "Amazon Web Services"; // Create Thread item to save Thread threadItem = new Thread(); threadItem.forumName = "AmazonDynamoDB"; threadItem.subject = "My sample question"; threadItem.message = "BatchWrite message"; List<String> tags = new ArrayList<String>(); tags.add("batch operations"); tags.add("write"); threadItem.tags = new HashSet<String>(tags); // Load ProductCatalog item to delete API Version 2012-08-10 99 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper Book book3 = mapper.load(Book.class, 903); List<Object> objectsToWrite = Arrays.asList(forumItem, threadItem); List<Book> objectsToDelete = Arrays.asList(book3); DynamoDBMapperConfig config = new DynamoDBMapperConfig(DynamoDBMapperConfig.SaveBehavior.CLOBBER); mapper.batchWrite(objectsToWrite, objectsToDelete, config); } @DynamoDBTable(tableName="ProductCatalog") public static class Book { private int id; private String title; private String ISBN; private int price; private int pageCount; private String productCategory; private boolean inPublication; //Partition key @DynamoDBHashKey(attributeName="Id") public int getId() { return id; } public void setId(int id) { this.id = id; } @DynamoDBAttribute(attributeName="Title") public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="ISBN") public String getISBN() { return ISBN; } public void setISBN(String ISBN) { this.ISBN = ISBN; } @DynamoDBAttribute(attributeName="Price") public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @DynamoDBAttribute(attributeName="PageCount") public int getPageCount() { return pageCount; } public void setPageCount(int pageCount) { this.pageCount = pageCount;} @DynamoDBAttribute(attributeName="ProductCategory") public String getProductCategory() { return productCategory; } public void setProductCategory(String productCategory) { this.productCategory = productCategory; } @DynamoDBAttribute(attributeName="InPublication") public boolean getInPublication() { return inPublication; } public void setInPublication(boolean inPublication) { this.inPublication = inPublication; } @Override public String toString() { return "Book [ISBN=" + ISBN + ", price=" + price + ", product category=" + productCategory + ", id=" + id + ", title=" + title + "]"; } API Version 2012-08-10 100 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper } @DynamoDBTable(tableName="Reply") public static class Reply { private String id; private String replyDateTime; private String message; private String postedBy; //Partition key @DynamoDBHashKey(attributeName="Id") public String getId() { return id; } public void setId(String id) { this.id = id; } //Sort key @DynamoDBRangeKey(attributeName="ReplyDateTime") public String getReplyDateTime() { return replyDateTime; } public void setReplyDateTime(String replyDateTime) { this.replyDateTime = replyDateTime; } @DynamoDBAttribute(attributeName="Message") public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @DynamoDBAttribute(attributeName="PostedBy") public String getPostedBy() { return postedBy; } public void setPostedBy(String postedBy) { this.postedBy = postedBy;} } @DynamoDBTable(tableName="Thread") public static class Thread { private String forumName; private String subject; private String message; private String lastPostedDateTime; private String lastPostedBy; private Set<String> tags; private int answered; private int views; private int replies; //Partition key @DynamoDBHashKey(attributeName="ForumName") public String getForumName() { return forumName; } public void setForumName(String forumName) { this.forumName = forumName; } //Sort key @DynamoDBRangeKey(attributeName="Subject") public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } @DynamoDBAttribute(attributeName="Message") public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @DynamoDBAttribute(attributeName="LastPostedDateTime") API Version 2012-08-10 101 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper public String getLastPostedDateTime() { return lastPostedDateTime; } public void setLastPostedDateTime(String lastPostedDateTime) { this.lastPostedDateTime = lastPostedDateTime; } @DynamoDBAttribute(attributeName="LastPostedBy") public String getLastPostedBy() { return lastPostedBy; } public void setLastPostedBy(String lastPostedBy) { this.lastPostedBy = lastPostedBy;} @DynamoDBAttribute(attributeName="Tags") public Set<String> getTags() { return tags; } public void setTags(Set<String> tags) { this.tags = tags; } @DynamoDBAttribute(attributeName="Answered") public int getAnswered() { return answered; } public void setAnswered(int answered) { this.answered = answered; } @DynamoDBAttribute(attributeName="Views") public int getViews() { return views; } public void setViews(int views) { this.views = views; } @DynamoDBAttribute(attributeName="Replies") public int getReplies() { return replies; } public void setReplies(int replies) { this.replies = replies; } } @DynamoDBTable(tableName="Forum") public static class Forum { private String name; private String category; private int threads; //Partition key @DynamoDBHashKey(attributeName="Name") public String getName() { return name; } public void setName(String name) { this.name = name; } @DynamoDBAttribute(attributeName="Category") public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } @DynamoDBAttribute(attributeName="Threads") public int getThreads() { return threads; } public void setThreads(int threads) { this.threads = threads;} } } 例: クエリおよびスキャン API Version 2012-08-10 102 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper このセクションの Java コード例では、次のクラスを定義して、DynamoDB 内のテーブルにマッピン グしています。サンプルテーブル作成の詳細については、「テーブルの作成とサンプルデータのロー ド (p. 166)」を参照してください。 • Book クラスは ProductCatalog テーブルにマッピングされます。 • Forum、Thread、および Reply クラスは、同じ名前テーブルにマッピングされます。 この例では DynamoDBMapper インスタンスを使用して、さらに次のクエリとスキャンオペレーショ ンを実行しています。 • Id によって書籍を取得します。 ProductCatalog テーブルでは Id がプライマリキーになっています。プライマリキーの一部にソート キーは含まれていません。したがって、テーブルのクエリを行うことはできません。項目は Id 値を 使用して取得できます。 • Reply テーブルに対して次のクエリを実行します。 Reply テーブルのプライマリキーは、Id と ReplyDateTime 属性で構成されていま す。ReplyDateTime はソートキーです。したがってこのテーブルではクエリを実行できます。 • 過去 15 日間に投稿されたフォーラムスレッドに対する返信を検索する • 特定の日付範囲の間に投稿されたフォーラムスレッドに対する返信を検索する • ProductCatalog テーブルをスキャンし、価格が指定した値より低い書籍を検索します。 パフォーマンス上の理由から、スキャンオペレーションではなくクエリを使用するようにしてくだ さい。ただし、場合によってはテーブルをスキャンする必要があります。データ入力エラーがあ り、書籍の価格の 1 つが 0 未満に設定されたとします。この例では、ProductCategory テーブルを スキャンして、価格が 0 未満である書籍項目(ProductCategory は書籍)を検索しています。 • ProductCatalog テーブルのパラレルスキャンを実行して特定のタイプの自転車を検索します。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセク ションに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード 済みであることを前提としています。 以下の例を実行するための詳しい手順については、「Java コードサンプル (p. 171)」を参照 してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.datamodeling; import import import import import import import java.text.SimpleDateFormat; java.util.Date; java.util.HashMap; java.util.List; java.util.Map; java.util.Set; java.util.TimeZone; import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; API Version 2012-08-10 103 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; import com.amazonaws.services.dynamodbv2.model.AttributeValue; public class DynamoDBMapperQueryScanExample { static AmazonDynamoDBClient client = new AmazonDynamoDBClient(new ProfileCredentialsProvider()); public static void main(String[] args) throws Exception { try { DynamoDBMapper mapper = new DynamoDBMapper(client); // Get a book - Id=101 GetBook(mapper, 101); // Sample forum and thread to test queries. String forumName = "Amazon DynamoDB"; String threadSubject = "DynamoDB Thread 1"; // Sample queries. FindRepliesInLast15Days(mapper, forumName, threadSubject); FindRepliesPostedWithinTimePeriod(mapper, forumName, threadSubject); // Scan a table and find book items priced less than specified value. FindBooksPricedLessThanSpecifiedValue(mapper, "20"); // Scan a table with multiple threads and find bicycle items with a specified bicycle type int numberOfThreads = 16; FindBicyclesOfSpecificTypeWithMultipleThreads(mapper, numberOfThreads, "Road"); System.out.println("Example complete!"); } catch (Throwable t) { System.err.println("Error running the DynamoDBMapperQueryScanExample: " + t); t.printStackTrace(); } } private static void GetBook(DynamoDBMapper mapper, int id) throws Exception { System.out.println("GetBook: Get book Id='101' "); System.out.println("Book table has no sort key. You can do GetItem, but not Query."); Book book = mapper.load(Book.class, 101); System.out.format("Id = %s Title = %s, ISBN = %s %n", book.getId(), book.getTitle(), book.getISBN() ); } private static void FindRepliesInLast15Days(DynamoDBMapper mapper, API Version 2012-08-10 104 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper String forumName, String threadSubject) throws Exception { System.out.println("FindRepliesInLast15Days: Replies within last 15 days."); String partitionKey = forumName + "#" + threadSubject; long twoWeeksAgoMilli = (new Date()).getTime() (15L*24L*60L*60L*1000L); Date twoWeeksAgo = new Date(); twoWeeksAgo.setTime(twoWeeksAgoMilli); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MMdd'T'HH:mm:ss.SSS'Z'"); dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); String twoWeeksAgoStr = dateFormatter.format(twoWeeksAgo); Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":val1", new AttributeValue().withS(partitionKey)); eav.put(":val2", new AttributeValue().withS(twoWeeksAgoStr.toString())); DynamoDBQueryExpression<Reply> queryExpression = new DynamoDBQueryExpression<Reply>() .withKeyConditionExpression("Id = :val1 and ReplyDateTime > :val2") .withExpressionAttributeValues(eav); List<Reply> latestReplies = mapper.query(Reply.class, queryExpression); for (Reply reply : latestReplies) { System.out.format("Id=%s, Message=%s, PostedBy=%s %n, ReplyDateTime=%s %n", reply.getId(), reply.getMessage(), reply.getPostedBy(), reply.getReplyDateTime() ); } } private static void FindRepliesPostedWithinTimePeriod( DynamoDBMapper mapper, String forumName, String threadSubject) throws Exception { String partitionKey = forumName + "#" + threadSubject; System.out.println("FindRepliesPostedWithinTimePeriod: Find replies for thread Message = 'DynamoDB Thread 2' posted within a period."); long startDateMilli = (new Date()).getTime() (14L*24L*60L*60L*1000L); // Two weeks ago. long endDateMilli = (new Date()).getTime() - (7L*24L*60L*60L*1000L); // One week ago. SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MMdd'T'HH:mm:ss.SSS'Z'"); dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); String startDate = dateFormatter.format(startDateMilli); String endDate = dateFormatter.format(endDateMilli); API Version 2012-08-10 105 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":val1", new AttributeValue().withS(partitionKey)); eav.put(":val2", new AttributeValue().withS(startDate)); eav.put(":val3", new AttributeValue().withS(endDate)); DynamoDBQueryExpression<Reply> queryExpression = new DynamoDBQueryExpression<Reply>() .withKeyConditionExpression("Id = :val1 and ReplyDateTime between :val2 and :val3") .withExpressionAttributeValues(eav); List<Reply> betweenReplies = mapper.query(Reply.class, queryExpression); for (Reply reply : betweenReplies) { System.out.format("Id=%s, Message=%s, PostedBy=%s %n, PostedDateTime=%s %n", reply.getId(), reply.getMessage(), reply.getPostedBy(), reply.getReplyDateTime() ); } } private static void FindBooksPricedLessThanSpecifiedValue( DynamoDBMapper mapper, String value) throws Exception { System.out.println("FindBooksPricedLessThanSpecifiedValue: Scan ProductCatalog."); Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":val1", new AttributeValue().withN(value)); eav.put(":val2", new AttributeValue().withS("Book")); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withFilterExpression("Price < :val1 and ProductCategory = :val2") .withExpressionAttributeValues(eav); List<Book> scanResult = mapper.scan(Book.class, scanExpression); for (Book book : scanResult) { System.out.println(book); } } private static void FindBicyclesOfSpecificTypeWithMultipleThreads( DynamoDBMapper mapper, int numberOfThreads, String bicycleType) throws Exception { System.out.println("FindBicyclesOfSpecificTypeWithMultipleThreads: Scan ProductCatalog With Multiple Threads."); Map<String, AttributeValue> eav = new HashMap<String, AttributeValue> (); eav.put(":val1", new AttributeValue().withS("Bicycle")); eav.put(":val2", new AttributeValue().withS(bicycleType)); API Version 2012-08-10 106 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withFilterExpression("ProductCategory = :val1 and BicycleType = :val2") .withExpressionAttributeValues(eav); List<Bicycle> scanResult = mapper.parallelScan(Bicycle.class, scanExpression, numberOfThreads); for (Bicycle bicycle : scanResult) { System.out.println(bicycle); } } @DynamoDBTable(tableName="ProductCatalog") public static class Book { private int id; private String title; private String ISBN; private int price; private int pageCount; private String productCategory; private boolean inPublication; @DynamoDBHashKey(attributeName="Id") public int getId() { return id; } public void setId(int id) { this.id = id; } @DynamoDBAttribute(attributeName="Title") public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="ISBN") public String getISBN() { return ISBN; } public void setISBN(String ISBN) { this.ISBN = ISBN; } @DynamoDBAttribute(attributeName="Price") public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @DynamoDBAttribute(attributeName="PageCount") public int getPageCount() { return pageCount; } public void setPageCount(int pageCount) { this.pageCount = pageCount;} @DynamoDBAttribute(attributeName="ProductCategory") public String getProductCategory() { return productCategory; } public void setProductCategory(String productCategory) { this.productCategory = productCategory; } @DynamoDBAttribute(attributeName="InPublication") public boolean getInPublication() { return inPublication; } public void setInPublication(boolean inPublication) { this.inPublication = inPublication; } @Override public String toString() { return "Book [ISBN=" + ISBN + ", price=" + price + ", product category=" + productCategory + ", id=" + id + ", title=" + title + "]"; API Version 2012-08-10 107 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper } } @DynamoDBTable(tableName="ProductCatalog") public static class Bicycle { private int id; private String title; private String description; private String bicycleType; private String brand; private int price; private List<String> color; private String productCategory; @DynamoDBHashKey(attributeName="Id") public int getId() { return id; } public void setId(int id) { this.id = id; } @DynamoDBAttribute(attributeName="Title") public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="Description") public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @DynamoDBAttribute(attributeName="BicycleType") public String getBicycleType() { return bicycleType; } public void setBicycleType(String bicycleType) { this.bicycleType = bicycleType; } @DynamoDBAttribute(attributeName="Brand") public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } @DynamoDBAttribute(attributeName="Price") public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @DynamoDBAttribute(attributeName="Color") public List<String> getColor() { return color; } public void setColor(List<String> color) { this.color = color; } @DynamoDBAttribute(attributeName="ProductCategory") public String getProductCategory() { return productCategory; } public void setProductCategory(String productCategory) { this.productCategory = productCategory; } @Override public String toString() { return "Bicycle [Type=" + bicycleType + ", color=" + color + ", price=" + price + ", product category=" + productCategory + ", id=" + id + ", title=" + title + "]"; } } API Version 2012-08-10 108 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper @DynamoDBTable(tableName="Reply") public static class Reply { private String id; private String replyDateTime; private String message; private String postedBy; //Partition key @DynamoDBHashKey(attributeName="Id") public String getId() { return id; } public void setId(String id) { this.id = id; } //Range key @DynamoDBRangeKey(attributeName="ReplyDateTime") public String getReplyDateTime() { return replyDateTime; } public void setReplyDateTime(String replyDateTime) { this.replyDateTime = replyDateTime; } @DynamoDBAttribute(attributeName="Message") public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @DynamoDBAttribute(attributeName="PostedBy") public String getPostedBy() { return postedBy; } public void setPostedBy(String postedBy) { this.postedBy = postedBy;} } @DynamoDBTable(tableName="Thread") public static class Thread { private String forumName; private String subject; private String message; private String lastPostedDateTime; private String lastPostedBy; private Set<String> tags; private int answered; private int views; private int replies; //Partition key @DynamoDBHashKey(attributeName="ForumName") public String getForumName() { return forumName; } public void setForumName(String forumName) { this.forumName = forumName; } //Range key @DynamoDBRangeKey(attributeName="Subject") public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } @DynamoDBAttribute(attributeName="Message") public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @DynamoDBAttribute(attributeName="LastPostedDateTime") public String getLastPostedDateTime() { return lastPostedDateTime; } API Version 2012-08-10 109 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper public void setLastPostedDateTime(String lastPostedDateTime) { this.lastPostedDateTime = lastPostedDateTime; } @DynamoDBAttribute(attributeName="LastPostedBy") public String getLastPostedBy() { return lastPostedBy; } public void setLastPostedBy(String lastPostedBy) { this.lastPostedBy = lastPostedBy;} @DynamoDBAttribute(attributeName="Tags") public Set<String> getTags() { return tags; } public void setTags(Set<String> tags) { this.tags = tags; } @DynamoDBAttribute(attributeName="Answered") public int getAnswered() { return answered; } public void setAnswered(int answered) { this.answered = answered; } @DynamoDBAttribute(attributeName="Views") public int getViews() { return views; } public void setViews(int views) { this.views = views; } @DynamoDBAttribute(attributeName="Replies") public int getReplies() { return replies; } public void setReplies(int replies) { this.replies = replies; } } @DynamoDBTable(tableName="Forum") public static class Forum { private String name; private String category; private int threads; @DynamoDBHashKey(attributeName="Name") public String getName() { return name; } public void setName(String name) { this.name = name; } @DynamoDBAttribute(attributeName="Category") public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } @DynamoDBAttribute(attributeName="Threads") public int getThreads() { return threads; } public void setThreads(int threads) { this.threads = threads;} } } バージョン番号を使用したオプティミスティックロック オプティミスティックロックとは、更新(または削除)しているクライアント側の項目 が、DynamoDB の項目と確実に同じになるようにするための方法です。この方法を使用すると、デー タベースの書き込みは、他のユーザーの書き込みによって上書きされないように保護されます。逆の 場合も同様に保護されます。 オプティミスティックロックを使用する場合、各項目には、バージョン番号として機能する属性があ ります。項目をテーブルから取り出すと、アプリケーションは、その項目のバージョン番号を記録し API Version 2012-08-10 110 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper ます。サーバー側のバージョン番号が変更されていない場合のみ、項目を更新できます。バージョン の不一致がある場合、他のユーザーが先に項目を変更したことを意味します。項目のバージョンが古 いため、更新は失敗します。その場合は、単純に更新をやり直します。もう一度項目を取り出して、 それを更新してください。オプティミスティックロックによって、他のユーザーが行った変更を誤っ て上書きしないようにすることができます。また、自分が行った変更を他のユーザーが誤って上書き しないようにすることもできます。 オプティミスティックロックをサポートするために、AWS SDK for Java では @DynamoDBVersionAttribute 注釈が提供されています。テーブルのマッピングクラスで、バー ジョン番号を保存する 1 つのプロパティを指定し、この注釈を使用してそのプロパティをマーキング します。オブジェクトを保存すると、DynamoDB テーブルの対応する項目に、バージョン番号を格納 する属性が作成されます。DynamoDBMapper では、最初にオブジェクトを保存したときにバージョン 番号が割り当てられ、項目を更新するたびにバージョン番号が自動的にインクリメントされます。更 新または削除リクエストは、クライアント側のオブジェクトのバージョンが、DynamoDB テーブルの 項目の対応するバージョン番号に一致する場合のみ成功します。 たとえば次の Java コードスニペットでは、複数のプロパティを持つ CatalogItem クラスを定義し ています。Version プロパティは @DynamoDBVersionAttribute 注釈でタグ付けされています。 @DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { private private private private private private Integer id; String title; String ISBN; Set<String> bookAuthors; String someProp; Long version; @DynamoDBHashKey(attributeName="Id") public Integer getId() { return id; } public void setId(Integer Id) { this.id = Id; } @DynamoDBAttribute(attributeName="Title") public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="ISBN") public String getISBN() { return ISBN; } public void setISBN(String ISBN) { this.ISBN = ISBN;} @DynamoDBAttribute(attributeName = "Authors") public Set<String> getBookAuthors() { return bookAuthors; } public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; } @DynamoDBIgnore public String getSomeProp() { return someProp;} public void setSomeProp(String someProp) {this.someProp = someProp;} @DynamoDBVersionAttribute public Long getVersion() { return version; } public void setVersion(Long version) { this.version = version;} } @DynamoDBVersionAttribute 注釈は、Long や Integer などの、null が許容された型を提供する プリミティブラッパークラスによって得られた、null が許容された型に適用できます。 API Version 2012-08-10 111 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper オプティミスティックロックは、次の DynamoDBMapper メソッドに対して次のような影響がありま す。 • save – 新しい項目に対して、DynamoDBMapper は初期バージョン番号 1 を割り当てます。項目を 取り出し、その項目の 1 つ以上のプロパティを更新して変更を保存する場合には、クライアント側 とサーバー側のバージョン番号が一致する場合のみ、保存が成功します。DynamoDBMapper によっ てバージョン番号が自動的にインクリメントされます。 • delete – delete メソッドは 1 つのオブジェクトをパラメータとして指定し、項目を削除する前に DynamoDBMapper がバージョンチェックを実行します。バージョンチェックは、リクエスト内で DynamoDBMapperConfig.SaveBehavior.CLOBBER を指定して無効にすることができます。 DynamoDBMapper 内のオプティミスティックロックの内部実装では、DynamoDB の条件付き更新 と条件付き削除サポートが使用されます。 オプティミスティックロックの無効化 オプティミスティックロックを無効にするには、DynamoDBMapperConfig.SaveBehavior 列挙値を UPDATE から CLOBBER に変更します。その場合は、バージョンチェックを省略する DynamoDBMapperConfig インスタンスを作成して、そのインスタンスをすべてのリクエストで使用 します。DynamoDBMapperConfig.SaveBehavior とその他のオプションの DynamoDBMapper パラ メータの詳細については、「DynamoDBMapper のオプションの設定 (p. 94)」を参照してくださ い。 ロック動作は、特定のオペレーションだけに設定することもできます。たとえば次の Java コードスニペットではDynamoDBMapper を使用してカタログ項目を保存していま す。オプションの DynamoDBMapperConfig パラメータを save メソッドに追加すること で、DynamoDBMapperConfig.SaveBehavior を指定しています。 DynamoDBMapper mapper = new DynamoDBMapper(client); // Load a catalog item. CatalogItem item = mapper.load(CatalogItem.class, 101); item.setTitle("This is a new title for the item"); ... // Save the item. mapper.save(item, new DynamoDBMapperConfig( DynamoDBMapperConfig.SaveBehavior.CLOBBER)); 任意データのマッピング サポートされている Java 型(「サポートされているデータの種類 (p. 81)」を参照)に加え て、DynamoDB 型に直接マッピングされない、アプリケーション内の型を使用できます。これらの 型をマッピングするには、複合型を文字列のインスタンスに、またその反対に変換する実装を指定 し、@DynamoDBTypeConverted 注釈を使用して複合型のアクセサーメソッドに注釈を付ける必要が あります。コンバーターコードは、オブジェクトが保存またはロードされるときにデータを変換しま す。これは、複合型を消費するすべてのオペレーションでも使用されます。クエリおよびスキャンオ ペレーション中にデータを比較する場合、その比較は DynamoDB に格納されているデータに対して 行われます。 たとえば、プロパティ Dimension(DimensionType 型)を定義する、次の CatalogItem クラスが あるとします。このプロパティには、項目の寸法として高さ、幅、厚さが格納されています。これら の項目の寸法を、DynamoDB に文字列(8.5x11x.05 など)として格納することを決定したとします。 次の例は、DimensionType オブジェクトを文字列に変換し、文字列を DimensionType に変換する コンバーターコードを示しています。 API Version 2012-08-10 112 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセク ションに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード 済みであることを前提としています。 以下の例を実行するための詳しい手順については、「Java コードサンプル (p. 171)」を参照 してください。 package com.amazonaws.codesamples.datamodeling; import import import import java.io.IOException; java.util.Arrays; java.util.HashSet; java.util.Set; import import import import import import import import import import import com.amazonaws.AmazonClientException; com.amazonaws.auth.AWSCredentials; com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.regions.Regions; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverted; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter; com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; public class DynamoDBMapperExample { static AmazonDynamoDBClient client; public static void main(String[] args) throws IOException { AWSCredentials credentials = null; try { credentials = new ProfileCredentialsProvider("default").getCredentials(); } catch (Exception e) { throw new AmazonClientException( "Cannot load the credentials from the credential profiles file. " + "Please make sure that your credentials file is at the correct " + "location, and is in valid format.", e); } // Set the AWS region you want to access. Regions usWest2 = Regions.US_WEST_2; client = new AmazonDynamoDBClient(credentials).withRegion(usWest2); DimensionType dimType = new DimensionType(); dimType.setHeight("8.00"); dimType.setLength("11.0"); dimType.setThickness("1.0"); Book book = new Book(); API Version 2012-08-10 113 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper book.setId(502); book.setTitle("Book 502"); book.setISBN("555-5555555555"); book.setBookAuthors(new HashSet<String>(Arrays.asList("Author1", "Author2"))); book.setDimensions(dimType); DynamoDBMapper mapper = new DynamoDBMapper(client); mapper.save(book); Book bookRetrieved = mapper.load(Book.class, 502); System.out.println("Book info: " + "\n" + bookRetrieved); bookRetrieved.getDimensions().setHeight("9.0"); bookRetrieved.getDimensions().setLength("12.0"); bookRetrieved.getDimensions().setThickness("2.0"); mapper.save(bookRetrieved); bookRetrieved = mapper.load(Book.class, 502); System.out.println("Updated book info: " + "\n" + bookRetrieved); } @DynamoDBTable(tableName="ProductCatalog") public static class Book { private int id; private String title; private String ISBN; private Set<String> bookAuthors; private DimensionType dimensionType; //Partition key @DynamoDBHashKey(attributeName = "Id") public int getId() { return id; } public void setId(int id) { this.id = id; } @DynamoDBAttribute(attributeName = "Title") public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="ISBN") public String getISBN() { return ISBN; } public void setISBN(String ISBN) { this.ISBN = ISBN;} @DynamoDBAttribute(attributeName = "Authors") public Set<String> getBookAuthors() { return bookAuthors; } public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; } @DynamoDBTypeConverted(converter = DimensionTypeConverter.class) @DynamoDBAttribute(attributeName = "Dimensions") public DimensionType getDimensions() { return dimensionType; } @DynamoDBAttribute(attributeName = "Dimensions") public void setDimensions(DimensionType dimensionType) { this.dimensionType = dimensionType; } @Override public String toString() { API Version 2012-08-10 114 Amazon DynamoDB 開発者ガイド Java: DynamoDBMapper return "Book [ISBN=" + ISBN + ", bookAuthors=" + bookAuthors + ", dimensionType= " + dimensionType.getHeight() + " X " + dimensionType.getLength() + " X " + dimensionType.getThickness() + ", Id=" + id + ", Title=" + title + "]"; } } static public class DimensionType { private String length; private String height; private String thickness; public String getLength() { return length; } public void setLength(String length) { this.length = length; } public String getHeight() { return height; } public void setHeight(String height) { this.height = height; } public String getThickness() { return thickness; } public void setThickness(String thickness) { this.thickness = thickness; } } // Converts the complex type DimensionType to a string and vice-versa. static public class DimensionTypeConverter implements DynamoDBTypeConverter<String,DimensionType> { @Override public String convert(DimensionType object) { DimensionType itemDimensions = (DimensionType)object; String dimension = null; try { if (itemDimensions != null) { dimension = String.format("%s x %s x %s", itemDimensions.getLength(), itemDimensions.getHeight(), itemDimensions.getThickness()); } } catch (Exception e) { e.printStackTrace(); } return dimension; } @Override public DimensionType unconvert(String s) { DimensionType itemDimension = new DimensionType(); try { if (s != null && s.length() !=0 ) { String[] data = s.split("x"); itemDimension.setLength(data[0].trim()); itemDimension.setHeight(data[1].trim()); itemDimension.setThickness(data[2].trim()); } } catch (Exception e) { e.printStackTrace(); } API Version 2012-08-10 115 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル return itemDimension; } } } .NET ドキュメントモデル トピック • ドキュメントモデルでサポートされていないオペレーション (p. 116) • AWS SDK for .NET ドキュメントモデルによる DynamoDB の項目の操作 (p. 116) • 項目の取得 – Table.GetItem (p. 119) • 項目の削除 – Table.DeleteItem (p. 121) • 項目の更新 – Table.UpdateItem (p. 121) • バッチ書き込み – 複数の項目の書き込みおよび削除 (p. 123) • 例: AWS SDK for .NET ドキュメントモデルを使用した CRUD オペレーション (p. 125) • 例: AWS SDK for .NET ドキュメントモデル API を使用したバッチオペレーション (p. 128) • AWS SDK for .NET ドキュメントモデルによる DynamoDB でのテーブルのクエリ (p. 130) AWS SDK for .NET では、低レベル DynamoDB オペレーションの一部をまとめるドキュメントモデ ルクラスを使用して、コーディングをさらに簡略化することができます。 ドキュメントモデルのプラ イマリクラスは Table と Document です。Table クラスでは、PutItem、GetItem、DeleteItem などのデータオペレーション方法を使用できます。Query および Scan メソッドも使用できま す。Document クラスは、テーブル内の単一の項目を表します。 前述のドキュメントモデルクラスは、Amazon.DynamoDBv2.DocumentModel 名前空間で使用できま す。 ドキュメントモデルでサポートされていないオペレーション ドキュメントモデルクラスは、テーブルの作成、更新、削除に使用することはできません。ただし、 ドキュメントモデルは、ほとんどの一般的なデータオペレーションをサポートしています。 AWS SDK for .NET ドキュメントモデルによる DynamoDB の 項目の操作 トピック • 項目の入力 – Table.PutItem メソッド (p. 117) • オプションパラメータの指定 (p. 119) ドキュメントモデルを使用してデータオペレーションを実行するには、最初に Table.LoadTable メソッドを呼び出して、特定のテーブルを表す Table クラスのインスタンスを作成します。次の C# コードスニペットでは、DynamoDB で ProductCatalog テーブルを表す Table オブジェクトを作成し ています。 Table table = Table.LoadTable(client, "ProductCatalog"); API Version 2012-08-10 116 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル Note 通常、LoadTable メソッドはアプリケーションの開始時に 1 回使用するだけです。このメ ソッドによって、DynamoDB へのラウンドトリップに DescribeTable 呼び出しが追加され るためです。 その後、テーブルオブジェクトを使用して、さまざまなデータオペレーションを実行することができ ます。これらのデータオペレーションは、それぞれ 2 つのタイプのオーバーロードがあります。1 つ は最小限必要なパラメータをとり、もう 1 つはそれに加えてオペレーション固有のオプション設定情 報をとります。たとえば項目を取り出すには、テーブルのプライマリキーの値を入力する必要があり ますが、その場合は次の GetItem オーバーロードを使用できます。 // Get the item from a table that has a primary key that is composed of only a partition key. Table.GetItem(Primitive partitionKey); // Get the item from a table whose primary key is composed of both a partition key and sort key. Table.GetItem(Primitive partitionKey, Primitive sortKey); これらのメソッドには、オプションパラメータを渡すこともできます。たとえば前述の GetItem では、すべての属性を含む項目全体が返されます。オプションで、取り出す属性のリストを指定す ることもできます。その場合は、オペレーション固有の設定オブジェクトパラメータをとる、次の GetItem オーバーロードを使用します。 // Configuration object that specifies optional parameters. GetItemOperationConfig config = new GetItemOperationConfig() { AttributesToGet = new List<string>() { "Id", "Title" }, }; // Pass in the configuration to the GetItem method. // 1. Table that has only a partition key as primary key. Table.GetItem(Primitive partitionKey, GetItemOperationConfig config); // 2. Table that has both a partition key and a sort key. Table.GetItem(Primitive partitionKey, Primitive sortKey, GetItemOperationConfig config); 設定オブジェクトを使用することで、特定の属性リストのリクエストやページサイズ(ページあたり の項目数)の指定など、複数のオプションパラメータを指定できます。それぞれのデータオペレー ションメソッドには、独自の設定クラスがあります。たとえば、GetItemOperationConfig クラ スでは GetItem オペレーションのオプションを指定し、PutItemOperationConfig クラスでは PutItem オペレーションのオプションパラメータを指定できます。 以下のセクションでは、Table クラスでサポートされているそれぞれのデータオペレーションについ て説明します。 項目の入力 – Table.PutItem メソッド PutItem メソッドは、入力された Document インスタンスをテーブルにアップロードします。 入力された Document で指定されているプライマリキーを持つ項目がテーブル内に存在する場合 は、PutItem オペレーションによって、既存の項目全体が置換されます。新しい項目は、PutItem メソッドに与えた Document オブジェクトと同じになります。つまり、元の項目にそれ以外の属性が 存在していたとしても、新しい項目内には存在しないことになります。次に、AWS SDK for .NET ド キュメントモデルを使用してテーブルに新しい項目を入力するステップを示します。 1. 項目を置くテーブル名を生成する Table.LoadTable メソッドを実行します。 API Version 2012-08-10 117 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル 2. 属性名と値のリストが含まれる、Document オブジェクトを作成します。 3. Document インスタンスをパラメータとして入力して、Table.PutItem を実行します。 次の C# コードスニペットは、前述のタスクの例です。この例では、ProductCatalog テーブルに項目 がアップロードされています。 Table table = Table.LoadTable(client, "ProductCatalog"); var book = new Document(); book["Id"] = 101; book["Title"] = "Book 101 Title"; book["ISBN"] = "11-11-11-11"; book["Authors"] = new List<string> { "Author 1", "Author 2" }; book["InStock"] = new DynamoDBBool(true); book["QuantityOnHand"] = new DynamoDBNull(); table.PutItem(book); 前述の例では、Document インスタンスは、数値型、文字列型、文字列セット型、ブール型、Null 型 の属性を持つ項目を作成します(Null は、この製品の QuantityOnHand が不明であることを示すた めに使用されます)。ブール値と Null の場合は、コンストラクタメソッドの DynamoDBBool および DynamoDBNull を使用します。 DynamoDB では、データ型のうちリスト型とマップ型は、他のデータ型で構成された要素を含むこと ができます。これらのデータ型をドキュメントモデル API にマッピングする方法を以下に示します。 • リスト - DynamoDBList コンストラクタを使用します。 • マップ - Document コンストラクタを使用します。 先にあげた例を修正して、項目にリスト属性を追加することができます。これを行うには、次のコー ドスニペットに示すように、DynamoDBList コンストラクタを使用します。 Table table = Table.LoadTable(client, "ProductCatalog"); var book = new Document(); book["Id"] = 101; /*other attributes omitted for brevity...*/ var relatedItems = new DynamoDBList(); relatedItems.Add(341); relatedItems.Add(472); relatedItems.Add(649); item.Add("RelatedItems", relatedItems); table.PutItem(book); 書籍にマップ属性を追加するには、別の Document を定義します。次のコードスニペットはそれを行 う方法を示しています。 Table table = Table.LoadTable(client, "ProductCatalog"); API Version 2012-08-10 118 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル var book = new Document(); book["Id"] = 101; /*other attributes omitted for brevity...*/ var pictures = new Document(); pictures.Add("FrontView", "http://example.com/products/101_front.jpg" ); pictures.Add("RearView", "http://example.com/products/101_rear.jpg" ); item.Add("Pictures", pictures); table.PutItem(book); これらの例は、導入事例: ProductCatalog 項目 (p. 210) に示された項目に基づいています。ドキュメ ントモデルを使用すると、導入事例の ProductReviews 属性のように複雑な入れ子になった属性を 作成することができます。 オプションパラメータの指定 PutItem オペレーションに PutItemOperationConfig パラメータを追加することで、オプション パラメータを設定できます。オプションパラメータの詳細なリストについては、PutItem を参照して ください。次の C# コードスニペットでは、ProductCatalog テーブルに項目が入力されています。次 のオプションパラメータが指定されています。 • 条件付き入力リクエストとする ConditionalExpression パラメータ。例では、置き換える項目 に ISBN 属性が存在し、それが特定の値でなくてはならないことを指定する式を作成します。 Table table = Table.LoadTable(client, "ProductCatalog"); var book = new Document(); book["Id"] = 555; book["Title"] = "Book 555 Title"; book["Price"] = "25.00"; book["ISBN"] = "55-55-55-55"; book["Name"] = "Item 1 updated"; book["Authors"] = new List<string> { "Author x", "Author y" }; book["InStock"] = new DynamoDBBool(true); book["QuantityOnHand"] = new DynamoDBNull(); // Create a condition expression for the optional conditional put operation. Expression expr = new Expression(); expr.ExpressionStatement = "ISBN = :val"; expr.ExpressionAttributeValues[":val"] = "55-55-55-55"; PutItemOperationConfig config = new PutItemOperationConfig() { // Optional parameter. ConditionalExpression = expr }; table.PutItem(book, config); 項目の取得 – Table.GetItem GetItem オペレーションでは、項目を Document インスタンスとして取り出します。次の C# コード スニペットに示すように、取り出す項目のプライマリキーを入力する必要があります。 API Version 2012-08-10 119 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル Table table = Table.LoadTable(client, "ProductCatalog"); Document document = table.GetItem(101); // Primary key 101. GetItem オペレーションを実行すると、項目のすべての属性が返され、デフォルトで結果整合性のあ る読み込み(「読み込み整合性 (p. 16)」を参照)が実行されます。 オプションパラメータの指定 GetItemOperationConfig パラメータを追加することで、GetItem オペレーションに追加オプショ ンを設定できます。オプションパラメータの詳細なリストについては、GetItem を参照してくださ い。次の C# コードスニペットでは、ProductCatalog テーブルから項目が取り出されています。次の オプションパラメータを使用して GetItemOperationConfig が指定されています。 • 指定された属性だけを取り出す AttributesToGet パラメータ。 • 指定されたすべての属性に対する最新の値をリクエストする ConsistentRead パラメータデータ の整合性の詳細については、「読み込み整合性 (p. 16)」を参照してください。 Table table = Table.LoadTable(client, "ProductCatalog"); GetItemOperationConfig config = new GetItemOperationConfig() { AttributesToGet = new List<string>() { "Id", "Title", "Authors", "InStock", "QuantityOnHand" }, ConsistentRead = true }; Document doc = table.GetItem(101, config); ドキュメントモデル API を使用して項目を取り出すと、返される Document オブジェクト内の個々の 要素にアクセスできます。 int id = doc["Id"].AsInt(); string title = doc["Title"].AsString(); List<string> authors = doc["Authors"].AsListOfString(); bool inStock = doc["InStock"].AsBoolean(); DynamoDBNull quantityOnHand = doc["QuantityOnHand"].AsDynamoDBNull(); リスト型またはマップ型の属性の場合に、属性をドキュメントモデル API にマッピングする方法を以 下に示します。 • リスト - AsDynamoDBList メソッドを使用します。 • マップ - AsDocument メソッドを使用します。 次のコードスニペットは、Document オブジェクトからリスト(RelatedItems)およびマップ (Pictures)を取得する方法を示します。 DynamoDBList relatedItems = doc["RelatedItems"].AsDynamoDBList(); Document pictures = doc["Pictures"].AsDocument(); API Version 2012-08-10 120 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル 項目の削除 – Table.DeleteItem DeleteItem オペレーションは、テーブルから項目を削除します。次の C# コードスニペットに示 すように、項目のプライマリキーをパラメータとして渡すことができます。また、すでに項目を読 み取っていて対応する Document オブジェクトを取得している場合には、それをパラメータとして DeleteItem メソッドに渡すこともできます。 Table table = Table.LoadTable(client, "ProductCatalog"); // Retrieve a book (a Document instance) Document document = table.GetItem(111); // 1) Delete using the Document instance. table.DeleteItem(document); // 2) Delete using the primary key. int partitionKey = 222; table.DeleteItem(partitionKey) オプションパラメータの指定 DeleteItemOperationConfig パラメータを追加することで、Delete オペレーションに追加オプ ションを設定できます。オプションパラメータの詳細なリストについては、DeleteTable を参照して ください。次の C# コードスニペットでは、以下の 2 つのオプションパラメータを指定します。 • ISBN 属性に特定の値が含まれている書籍項目が削除されるようにする ConditionalExpression パラメータ。 • 削除された項目が Delete メソッドによって返されることをリクエストする ReturnValues パラ メータ。 Table table = Table.LoadTable(client, "ProductCatalog"); int partitionKey = 111; Expression expr = new Expression(); expr.ExpressionStatement = "ISBN = :val"; expr.ExpressionAttributeValues[":val"] = "11-11-11-11"; // Specify optional parameters for Delete operation. DeleteItemOperationConfig config = new DeleteItemOperationConfig { ConditionalExpression = expr, ReturnValues = ReturnValues.AllOldAttributes // This is the only supported value when using the document model. }; // Delete the book. Document d = table.DeleteItem(partitionKey, config); 項目の更新 – Table.UpdateItem UpdateItem オペレーションは、既存の項目があればそれを更新します。プライマリキーが指定され ている項目がない場合は、UpdateItem オペレーションによって新しい項目が追加されます。 API Version 2012-08-10 121 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル UpdateItem オペレーションを使用して、既存の属性値を更新するか、既存のコレクションに新しい 属性を追加するか、既存のコレクションから属性を削除することができます。これらの更新は、更新 を記述する Document インスタンスを作成して実行します。 UpdateItem アクションは、以下のガイドラインに従います。 • 項目が存在しない場合、UpdateItem は入力で指定されたプライマリキーを使用して、新しい項目 を追加します。 • 項目が存在する場合、UpdateItem は次のように更新を適用します。 • 既存の属性値を更新に含まれる値に置き換えます。 • 入力で指定された属性が存在しない場合は、新しい属性を項目に追加します。 • 入力された属性値が null である場合は、属性を削除します。 Note この中間レベルの UpdateItem オペレーションでは、基層の DynamoDB オペレーションで サポートされている Add アクション (UpdateItem を参照) はサポートされていません。 Note PutItem オペレーション(項目の入力 – Table.PutItem メソッド (p. 117))でも更新を実行 できます。PutItem を呼び出して項目をアップロードするときにプライマリキーが存在する 場合は、PutItem オペレーションによって項目全体が置き換わります。既存の項目内に属性 があり、入力された Document でそれらの属性が指定されていない場合には、PutItem オペ レーションによってそれらの属性が削除されます。ただし、UpdateItem が更新するのは指 定された入力属性だけです。 その項目では、その他の既存の属性は変更されません。 AWS SDK for .NET ドキュメントモデルを使用して項目を更新するステップを以下に示します。 1. 更新オペレーションを実行するテーブルの名前を入力して、Table.LoadTable メソッドを実行し ます。 2. 実行するすべての更新を指定して、Document インスタンスを作成します。 既存の属性を削除するには、その属性値に null を指定します。 3. Table.UpdateItem メソッドを呼び出し、Document インスタンスを入力パラメータとして指定 します。 プライマリキーを、Document インスタンスで、または明示的にパラメータとして指定する必要が あります。 次の C# コードスニペットは、前述のタスクの例です。このコードサンプルでは、Book テーブル の項目が更新されています。UpdateItem オペレーションによって、既存の Authors 属性が更新さ れ、PageCount 属性が削除され、新しい属性 XYZ が追加されます。Document インスタンスには、 更新する書籍のプライマリキーが含まれています。 Table table = Table.LoadTable(client, "ProductCatalog"); var book = new Document(); // Set the attributes that you wish to update. book["Id"] = 111; // Primary key. // Replace the authors attribute. API Version 2012-08-10 122 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル book["Authors"] = new List<string> { "Author x", "Author y" }; // Add a new attribute. book["XYZ"] = 12345; // Delete the existing PageCount attribute. book["PageCount"] = null; table.Update(book); オプションパラメータの指定 UpdateItemOperationConfig パラメータを追加することで、UpdateItem オペレーションに追加 オプションを設定できます。オプションパラメータの詳細なリストについては、UpdateItem を参照し てください。 次の C# コードスニペットでは、書籍項目の価格が 25 に更新されています。次の 2 つのオプションパ ラメータが指定されています。 • 存在することが期待される Price 属性の値が 20 であることを指定する ConditionalExpression パラメータ。 • 更新された項目が返される UpdateItem オペレーションをリクエストする ReturnValues パラ メータ。 Table table = Table.LoadTable(client, "ProductCatalog"); string partitionKey = "111"; var book = new Document(); book["Id"] = partitionKey; book["Price"] = 25; Expression expr = new Expression(); expr.ExpressionStatement = "Price = :val"; expr.ExpressionAttributeValues[":val"] = 20"; UpdateOperationConfig config = new UpdateOperationConfig() { ConditionalExpression = expr, ReturnValues = ReturnValues.AllOldAttributes }; Document d1 = table.Update(book, config); バッチ書き込み – 複数の項目の書き込みおよび削除 バッチ書き込みは、複数の項目の書き込みと削除をバッチで行うことを意味します。このオペレー ションでは、単一の 呼び出しの 1 つ以上のテーブルから、複数の項目の書き込みと削除を行うことが できます。AWS SDK for .NET ドキュメントモデル API を使用して、テーブルで複数の項目の書き込 みまたは削除を行うステップを次に示します。 1. テーブルオブジェクトを作成するには、バッチオペレーションを実行するテーブルの名前を指定し て、Table.LoadTable メソッドを実行します。 2. 前述のステップで作成したテーブルインスタンスで CreateBatchWrite メソッドを実行 し、DocumentBatchWrite オブジェクトを作成します。 3. DocumentBatchWrite オブジェクトメソッドを使用して、アップロードまたは削除するドキュメ ントを指定します。 API Version 2012-08-10 123 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル 4. DocumentBatchWrite.Execute メソッドを呼び出してバッチオペレーションを実行します。 ドキュメントモデル API を使用する場合は、1 つのバッチに任意の数のオペレーションを指定 できます。ただし DynamoDB では、1 つのバッチ内のオペレーションの数と、1 つのバッチ オペレーションでのバッチの合計サイズが制限されています。制限の具体的な詳細について は、BatchWriteItem を参照してください。許可されている書き込みリクエスト数をバッチ書き込み リクエストが超えたこと、またはバッチの HTTP ペイロードサイズが BatchWriteItem で許可さ れている制限を超えたことをドキュメントモデル API が検出した場合には、バッチが複数の小さな バッチに分割されます。 さらに、バッチ書き込みに対する応答で、未処理の項目が返された場合に は、ドキュメントモデル API がそれら未処理の項目を使用して、別のバッチリクエストを自動的に 送信します。 次の C# コードスニペットは、前述のステップを示しています。このコードスニペットでは、バッチ 書き込みオペレーションを使用して、書籍項目のアップロードと別の書籍項目の削除という 2 つの書 き込みが実行されています。 Table productCatalog = Table.LoadTable(client, "ProductCatalog"); var batchWrite = productCatalog.CreateBatchWrite(); var book1 = new Document(); book1["Id"] = 902; book1["Title"] = "My book1 in batch write using .NET document model"; book1["Price"] = 10; book1["Authors"] = new List<string> { "Author 1", "Author 2", "Author 3" }; book1["InStock"] = new DynamoDBBool(true); book1["QuantityOnHand"] = 5; batchWrite.AddDocumentToPut(book1); // specify delete item using overload that takes PK. batchWrite.AddKeyToDelete(12345); batchWrite.Execute(); 実例については、「例: AWS SDK for .NET ドキュメントモデル API を使用したバッチオペレーショ ン (p. 128)」を参照してください。 バッチ書き込みオペレーションを使用すると、複数のテーブルで入力および削除オペレーションを実 行できます。AWS SDK for .NET ドキュメントモデルを使用して、複数のテーブルで複数の項目の書 き込みまたは削除を行うステップを次に示します。 1. 前述の手順で示したように、複数の項目の入力または削除を行う各テーブルについて DocumentBatchWrite インスタンスを作成します。 2. MultiTableDocumentBatchWrite のインスタンスを作成し、その中に個々の DocumentBatchWrite オブジェクトを追加します。 3. MultiTableDocumentBatchWrite.Execute メソッドを実行します。 次の C# コードスニペットは、前述のステップを示しています。このコードスニペットでは、バッチ 書き込みオペレーションを使用して、次の書き込みオペレーションを実行しています。 • Forum テーブル項目内に新しい項目を入力する • Thread テーブル内に項目を入力し、同じテーブルから項目を削除する // 1. Specify item to add in the Forum table. API Version 2012-08-10 124 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル Table forum = Table.LoadTable(client, "Forum"); var forumBatchWrite = forum.CreateBatchWrite(); var forum1 = new Document(); forum1["Name"] = "Test BatchWrite Forum"; forum1["Threads"] = 0; forumBatchWrite.AddDocumentToPut(forum1); // 2a. Specify item to add in the Thread table. Table thread = Table.LoadTable(client, "Thread"); var threadBatchWrite = thread.CreateBatchWrite(); var thread1 = new Document(); thread1["ForumName"] = "Amazon S3 forum"; thread1["Subject"] = "My sample question"; thread1["Message"] = "Message text"; thread1["KeywordTags"] = new List<string>{ "Amazon S3", "Bucket" }; threadBatchWrite.AddDocumentToPut(thread1); // 2b. Specify item to delete from the Thread table. threadBatchWrite.AddKeyToDelete("someForumName", "someSubject"); // 3. Create multi-table batch. var superBatch = new MultiTableDocumentBatchWrite(); superBatch.AddBatch(forumBatchWrite); superBatch.AddBatch(threadBatchWrite); superBatch.Execute(); 例: AWS SDK for .NET ドキュメントモデルを使用した CRUD オペレーション 次の C# コード例は、次のアクションを実行します。 • ProductCatalog テーブルで書籍項目を作成します。 • 書籍項目を取り出します。 • 書籍項目を更新します。このコード例は、新しい属性を追加して既存の属性を更新する、通常の更 新を示しています。また、既存の価格とコードで指定されている価格が一致する場合のみ書籍の価 格を更新する、条件付き更新も示しています。 • 書籍項目を削除します。 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照 してください。 using using using using using using System; System.Collections.Generic; System.Linq; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DocumentModel; Amazon.Runtime; namespace com.amazonaws.codesamples { class MidlevelItemCRUD { API Version 2012-08-10 125 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); private static string tableName = "ProductCatalog"; // The sample uses the following id PK value to add book item. private static int sampleBookId = 555; static void Main(string[] args) { try { Table productCatalog = Table.LoadTable(client, tableName); CreateBookItem(productCatalog); RetrieveBook(productCatalog); // Couple of sample updates. UpdateMultipleAttributes(productCatalog); UpdateBookPriceConditionally(productCatalog); // Delete. DeleteBook(productCatalog); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } // Creates a sample book item. private static void CreateBookItem(Table productCatalog) { Console.WriteLine("\n*** Executing CreateBookItem() ***"); var book = new Document(); book["Id"] = sampleBookId; book["Title"] = "Book " + sampleBookId; book["Price"] = 19.99; book["ISBN"] = "111-1111111111"; book["Authors"] = new List<string> { "Author 1", "Author 2", "Author 3" }; book["PageCount"] = 500; book["Dimensions"] = "8.5x11x.5"; book["InPublication"] = new DynamoDBBool(true); book["InStock"] = new DynamoDBBool(false); book["QuantityOnHand"] = 0; productCatalog.PutItem(book); } private static void RetrieveBook(Table productCatalog) { Console.WriteLine("\n*** Executing RetrieveBook() ***"); // Optional configuration. GetItemOperationConfig config = new GetItemOperationConfig { AttributesToGet = new List<string> { "Id", "ISBN", "Title", "Authors", "Price" }, ConsistentRead = true }; API Version 2012-08-10 126 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル Document document = productCatalog.GetItem(sampleBookId, config); Console.WriteLine("RetrieveBook: Printing book retrieved..."); PrintDocument(document); } private static void UpdateMultipleAttributes(Table productCatalog) { Console.WriteLine("\n*** Executing UpdateMultipleAttributes() ***"); Console.WriteLine("\nUpdating multiple attributes...."); int partitionKey = sampleBookId; var book = new Document(); book["Id"] = partitionKey; // List of attribute updates. // The following replaces the existing authors list. book["Authors"] = new List<string> { "Author x", "Author y" }; book["newAttribute"] = "New Value"; book["ISBN"] = null; // Remove it. // Optional parameters. UpdateItemOperationConfig config = new UpdateItemOperationConfig { // Get updated item in response. ReturnValues = ReturnValues.AllNewAttributes }; Document updatedBook = productCatalog.UpdateItem(book, config); Console.WriteLine("UpdateMultipleAttributes: Printing item after updates ..."); PrintDocument(updatedBook); } private static void UpdateBookPriceConditionally(Table productCatalog) { Console.WriteLine("\n*** Executing UpdateBookPriceConditionally() ***"); int partitionKey = sampleBookId; var book = new Document(); book["Id"] = partitionKey; book["Price"] = 29.99; // For conditional price update, creating a condition expression. Expression expr = new Expression(); expr.ExpressionStatement = "Price = :val"; expr.ExpressionAttributeValues[":val"] = 19.00; // Optional parameters. UpdateItemOperationConfig config = new UpdateItemOperationConfig { ConditionalExpression = expr, ReturnValues = ReturnValues.AllNewAttributes }; Document updatedBook = productCatalog.UpdateItem(book, config); API Version 2012-08-10 127 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル Console.WriteLine("UpdateBookPriceConditionally: Printing item whose price was conditionally updated"); PrintDocument(updatedBook); } private static void DeleteBook(Table productCatalog) { Console.WriteLine("\n*** Executing DeleteBook() ***"); // Optional configuration. DeleteItemOperationConfig config = new DeleteItemOperationConfig { // Return the deleted item. ReturnValues = ReturnValues.AllOldAttributes }; Document document = productCatalog.DeleteItem(sampleBookId, config); Console.WriteLine("DeleteBook: Printing deleted just deleted..."); PrintDocument(document); } private static void PrintDocument(Document updatedDocument) { foreach (var attribute in updatedDocument.GetAttributeNames()) { string stringValue = null; var value = updatedDocument[attribute]; if (value is Primitive) stringValue = value.AsPrimitive().Value.ToString(); else if (value is PrimitiveList) stringValue = string.Join(",", (from primitive in value.AsPrimitiveList().Entries select primitive.Value).ToArray()); Console.WriteLine("{0} - {1}", attribute, stringValue); } } } } 例: AWS SDK for .NET ドキュメントモデル API を使用した バッチオペレーション トピック • 例: AWS SDK for .NET ドキュメントモデルを使用したバッチ書き込み (p. 128) 例: AWS SDK for .NET ドキュメントモデルを使用したバッチ書き込み 次の C# コード例は、単一のテーブルと複数のテーブルに対するバッチ書き込みオペレーションを示 しています。この例では次のタスクを実行しています。 • 単一のテーブルに対するバッチ書き込みを示すために、ProductCatalog テーブルに 2 つの項目を追 加しています。 • 複数のテーブルに対するバッチ書き込みを示すために、Forum テーブルと Thread テーブルの両方 に 1 つの項目を追加し、Thread テーブルから項目を削除しています。 API Version 2012-08-10 128 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル 「テーブルの作成とサンプルデータのロード (p. 166)」のステップに従っていれば、ProductCatalog テーブル、Forum テーブル、Thread テーブルは作成済みです。これらのサンプルテーブルは、プログ ラムで作成することもできます。詳細については、「AWS SDK for .NET を使用した、サンプルテー ブルの作成とデータのアップロード (p. 608)」を参照してください。次のサンプルをテストするため の詳しい手順については、「.NET コードサンプル (p. 173)」を参照してください。 using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DocumentModel; Amazon.Runtime; namespace com.amazonaws.codesamples { class MidLevelBatchWriteItem { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { SingleTableBatchWrite(); MultiTableBatchWrite(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void SingleTableBatchWrite() { Table productCatalog = Table.LoadTable(client, "ProductCatalog"); var batchWrite = productCatalog.CreateBatchWrite(); var book1 = new Document(); book1["Id"] = 902; book1["Title"] = "My book1 in batch write using .NET helper classes"; book1["ISBN"] = "902-11-11-1111"; book1["Price"] = 10; book1["ProductCategory"] = "Book"; book1["Authors"] = new List<string> { "Author 1", "Author 2", "Author 3" }; book1["Dimensions"] = "8.5x11x.5"; book1["InStock"] = new DynamoDBBool(true); book1["QuantityOnHand"] = new DynamoDBNull(); //Quantity is unknown at this time batchWrite.AddDocumentToPut(book1); // Specify delete item using overload that takes PK. batchWrite.AddKeyToDelete(12345); API Version 2012-08-10 129 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル Console.WriteLine("Performing batch write in SingleTableBatchWrite()"); batchWrite.Execute(); } private static void MultiTableBatchWrite() { // 1. Specify item to add in the Forum table. Table forum = Table.LoadTable(client, "Forum"); var forumBatchWrite = forum.CreateBatchWrite(); var forum1 = new Document(); forum1["Name"] = "Test BatchWrite Forum"; forum1["Threads"] = 0; forumBatchWrite.AddDocumentToPut(forum1); // 2a. Specify item to add in the Thread table. Table thread = Table.LoadTable(client, "Thread"); var threadBatchWrite = thread.CreateBatchWrite(); var thread1 = new Document(); thread1["ForumName"] = "S3 forum"; thread1["Subject"] = "My sample question"; thread1["Message"] = "Message text"; thread1["KeywordTags"] = new List<string> { "S3", "Bucket" }; threadBatchWrite.AddDocumentToPut(thread1); // 2b. Specify item to delete from the Thread table. threadBatchWrite.AddKeyToDelete("someForumName", "someSubject"); // 3. Create multi-table batch. var superBatch = new MultiTableDocumentBatchWrite(); superBatch.AddBatch(forumBatchWrite); superBatch.AddBatch(threadBatchWrite); Console.WriteLine("Performing batch write in MultiTableBatchWrite()"); superBatch.Execute(); } } } AWS SDK for .NET ドキュメントモデルによる DynamoDB で のテーブルのクエリ トピック • AWS SDK for .NET の Table.Query メソッド (p. 130) • AWS SDK for .NET の Table.Scan メソッド (p. 135) AWS SDK for .NET の Table.Query メソッド Query メソッドを使用すると、テーブルのクエリを行うことができます。複合プライマリキー (パー ティションキーおよびソートキー) があるテーブルにのみ、クエリを実行できます。テーブルのプライ マリキーがパーティションキーだけで構成されている場合、Query オペレーションはサポートされて いません。デフォルトでは、Query の内部で結果整合性のあるクエリが実行されます。 整合性モデル の詳細については、「読み込み整合性 (p. 16)」を参照してください。 API Version 2012-08-10 130 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル Query メソッドには 2 つのオーバーロードがあります。Query メソッドで最小限必要なパラメーター は、パーティションキーの値とソートキーフィルタです。次のオーバーロードを使用して、これら最 小限必要なパラメータを指定できます。 Query(Primitive partitionKey, RangeFilter Filter); たとえば次の C# コードスニペットでは、フォーラムで過去 15 日間に投稿されたすべての返信がクエ リされます。 string tableName = "Reply"; Table table = Table.LoadTable(client, tableName); DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15); RangeFilter filter = new RangeFilter(QueryOperator.GreaterThan, twoWeeksAgoDate); Search search = table.Query("DynamoDB Thread 2", filter); これによって Search オブジェクトが作成されます。ここで次の C# コードスニペットに示すよう に、Search.GetNextSet メソッドを反復的に呼び出して、一度に 1 ページずつ結果を取り出すこと ができます。このコードでは、クエリによって返される各項目の属性値が出力されます。 List<Document> documentSet = new List<Document>(); do { documentSet = search.GetNextSet(); foreach (var document in documentSet) PrintDocument(document); } while (!search.IsDone); private static void PrintDocument(Document document) { Console.WriteLine(); foreach (var attribute in document.GetAttributeNames()) { string stringValue = null; var value = document[attribute]; if (value is Primitive) stringValue = value.AsPrimitive().Value; else if (value is PrimitiveList) stringValue = string.Join(",", (from primitive in value.AsPrimitiveList().Entries select primitive.Value).ToArray()); Console.WriteLine("{0} - {1}", attribute, stringValue); } } オプションパラメータの指定 また、取り出す属性リスト、強力な整合性のある読み込み、ページサイズ、ページごとに返される項 目数などを指定する、Query のオプションパラメータを指定することもできます。 パラメータの詳細 なリストについては、Query を参照してください。オプションパラメータを指定するには、次のオー バーロードを使用して QueryOperationConfig オブジェクトを指定する必要があります。 API Version 2012-08-10 131 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル Query(QueryOperationConfig config); 前述の例でクエリを実行する(過去 15 日間に投稿されたフォーラムの返信を取り出す)とします。 ただし、特定の属性だけを取り出し、強力な整合性のある読み込みをリクエストする、オプションの クエリパラメータを指定するとします。次の C# コードスニペットでは、QueryOperationConfig オブジェクトを使用してリクエストを作成しています。 Table table = Table.LoadTable(client, "Reply"); DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15); QueryOperationConfig config = new QueryOperationConfig() { HashKey = "DynamoDB Thread 2", //Partition key AttributesToGet = new List<string> { "Subject", "ReplyDateTime", "PostedBy" }, ConsistentRead = true, Filter = new RangeFilter(QueryOperator.GreaterThan, twoWeeksAgoDate) }; Search search = table.Query(config); 例: Table.Query メソッドを使用したクエリ 次の C# コード例では、Table.Query メソッドを使用して次のサンプルクエリを実行しています。 • Reply テーブルに対して次のクエリが実行されています。 • 過去 15 日間に投稿されたフォーラムスレッドの返信を検索する。 このクエリは 2 回実行されます。最初の Table.Query の呼び出しの例では、必須のクエリパラ メータだけが指定されています。2 回目の Table.Query の呼び出しでは、オプションのクエリパ ラメータを指定して、強力な整合性のある読み込みと、取り出す属性のリストをリクエストして います。 • 特定の期間中に投稿されたフォーラムスレッドの返信を検索する。 このクエリでは Between クエリ演算子を使用して、2 つの日付間に投稿された返信が検索されま す。 • ProductCatalog テーブルから製品を取得する ProductCatalog テーブルにはパーティションキーでしかないプライマリキーがあるため、項目の取 得だけが可能で、テーブルのクエリを行うことはできません。この例では、項目 Id を使用して特定 の製品項目を取り出しています。 using using using using using using using System; System.Collections.Generic; System.Linq; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DocumentModel; Amazon.Runtime; Amazon.SecurityToken; namespace com.amazonaws.codesamples { class MidLevelQueryAndScan { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) API Version 2012-08-10 132 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル { try { // Query examples. Table replyTable = Table.LoadTable(client, "Reply"); string forumName = "Amazon DynamoDB"; string threadSubject = "DynamoDB Thread 2"; FindRepliesInLast15Days(replyTable, forumName, threadSubject); FindRepliesInLast15DaysWithConfig(replyTable, forumName, threadSubject); FindRepliesPostedWithinTimePeriod(replyTable, forumName, threadSubject); // Get Example. Table productCatalogTable = Table.LoadTable(client, "ProductCatalog"); int productId = 101; GetProduct(productCatalogTable, productId); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } private static void GetProduct(Table tableName, int productId) { Console.WriteLine("*** Executing GetProduct() ***"); Document productDocument = tableName.GetItem(productId); if (productDocument != null) { PrintDocument(productDocument); } else { Console.WriteLine("Error: product " + productId + " does not exist"); } } private static void FindRepliesInLast15Days(Table table, string forumName, string threadSubject) { string Attribute = forumName + "#" + threadSubject; DateTime twoWeeksAgoDate = DateTime.UtcNow TimeSpan.FromDays(15); QueryFilter filter = new QueryFilter("Id", QueryOperator.Equal, partitionKey); filter.AddCondition("ReplyDateTime", QueryOperator.GreaterThan, twoWeeksAgoDate); // Use Query overloads that takes the minimum required query parameters. Search search = table.Query(filter); List<Document> documentSet = new List<Document>(); API Version 2012-08-10 133 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル do { documentSet = search.GetNextSet(); Console.WriteLine("\nFindRepliesInLast15Days: printing ............"); foreach (var document in documentSet) PrintDocument(document); } while (!search.IsDone); } private static void FindRepliesPostedWithinTimePeriod(Table table, string forumName, string threadSubject) { DateTime startDate = DateTime.UtcNow.Subtract(new TimeSpan(21, 0, 0, 0)); DateTime endDate = DateTime.UtcNow.Subtract(new TimeSpan(1, 0, 0, 0)); QueryFilter filter = new QueryFilter("Id", QueryOperator.Equal, forumName + "#" + threadSubject); filter.AddCondition("ReplyDateTime", QueryOperator.Between, startDate, endDate); QueryOperationConfig config = new QueryOperationConfig() { Limit = 2, // 2 items/page. Select = SelectValues.SpecificAttributes, AttributesToGet = new List<string> { "Message", "ReplyDateTime", "PostedBy" }, ConsistentRead = true, Filter = filter }; Search search = table.Query(config); List<Document> documentList = new List<Document>(); do { documentList = search.GetNextSet(); Console.WriteLine("\nFindRepliesPostedWithinTimePeriod: printing replies posted within dates: {0} and {1} ............", startDate, endDate); foreach (var document in documentList) { PrintDocument(document); } } while (!search.IsDone); } private static void FindRepliesInLast15DaysWithConfig(Table table, string forumName, string threadName) { DateTime twoWeeksAgoDate = DateTime.UtcNow TimeSpan.FromDays(15); QueryFilter filter = new QueryFilter("Id", QueryOperator.Equal, forumName + "#" + threadName); API Version 2012-08-10 134 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル filter.AddCondition("ReplyDateTime", QueryOperator.GreaterThan, twoWeeksAgoDate); // You are specifying optional parameters so use QueryOperationConfig. QueryOperationConfig config = new QueryOperationConfig() { Filter = filter, // Optional parameters. Select = SelectValues.SpecificAttributes, AttributesToGet = new List<string> { "Message", "ReplyDateTime", "PostedBy" }, ConsistentRead = true }; Search search = table.Query(config); List<Document> documentSet = new List<Document>(); do { documentSet = search.GetNextSet(); Console.WriteLine("\nFindRepliesInLast15DaysWithConfig: printing ............"); foreach (var document in documentSet) PrintDocument(document); } while (!search.IsDone); } private static void PrintDocument(Document document) { // count++; Console.WriteLine(); foreach (var attribute in document.GetAttributeNames()) { string stringValue = null; var value = document[attribute]; if (value is Primitive) stringValue = value.AsPrimitive().Value.ToString(); else if (value is PrimitiveList) stringValue = string.Join(",", (from primitive in value.AsPrimitiveList().Entries select primitive.Value).ToArray()); Console.WriteLine("{0} - {1}", attribute, stringValue); } } } } AWS SDK for .NET の Table.Scan メソッド Scan メソッドではテーブル全体のスキャンが実行されます。ここでは 2 つのオーバーロードを使用 できます。Scan メソッドで必要とされるパラメータは、次のオーバーロードを使用して指定できる、 スキャンフィルタだけです。 Scan(ScanFilter filter); API Version 2012-08-10 135 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル たとえば、フォーラムスレッドのテーブルを維持していて、そこではスレッドの件名 (プライマリ)、 関連メッセージ、スレッドが属するフォーラムの Id、タグなどの情報を追跡しているとします。ス レッドの件名がプライマリキーであるとします。 Thread(Subject, Message, ForumId, Tags, LastPostedDateTime, .... ) これは、AWS フォーラムで見られるフォーラムやスレッドを簡略化したものです(「Discussion Forums」を参照)。次の C# コードスニペットでは、特定のフォーラム (ForumId = 101) 内で、 「sortkey」というタグが付加されたすべてのスレッドをクエリしています。ForumId はプライマリ キーではないため、この例ではテーブルをスキャンしています。ScanFilter には 2 つの条件が含ま れています。クエリによって、両方の条件を満たすすべてのスレッドが返されます。 string tableName = "Thread"; Table ThreadTable = Table.LoadTable(client, tableName); ScanFilter scanFilter = new ScanFilter(); scanFilter.AddCondition("ForumId", ScanOperator.Equal, 101); scanFilter.AddCondition("Tags", ScanOperator.Contains, "sortkey"); Search search = ThreadTable.Scan(scanFilter); オプションパラメータの指定 Scan には、取り出す属性のリストや、強力な整合性のある読み込みを実行するかどうかなど、オプ ションのパラメータを指定することもできます。オプションパラメータを指定するには、必須および オプションのパラメータを含む ScanOperationConfig オブジェクトを作成し、次のオーバーロー ドを使用する必要があります。 Scan(ScanOperationConfig config); 次の C# コードスニペットでは、前述のものと同じクエリ (ForumId が 101 で Tag 属性に「sortkey」 キーワードが含まれているフォーラムスレッドを検索する) を実行しています。ただしここで は、オプションのパラメータを追加して、特定の属性リストだけを取り出すものとします。その 場合は、次のコード例に示すように、必須およびオプションのすべてのパラメータを指定して ScanOperationConfig オブジェクトを作成する必要があります。 string tableName = "Thread"; Table ThreadTable = Table.LoadTable(client, tableName); ScanFilter scanFilter = new ScanFilter(); scanFilter.AddCondition("ForumId", ScanOperator.Equal, forumId); scanFilter.AddCondition("Tags", ScanOperator.Contains, "sortkey"); ScanOperationConfig config = new ScanOperationConfig() { AttributesToGet = new List<string> { "Subject", "Message" } , Filter = scanFilter }; Search search = ThreadTable.Scan(config); API Version 2012-08-10 136 Amazon DynamoDB 開発者ガイド .NET ドキュメントモデル 例: Table.Scan メソッドを使用したスキャン Scan オペレーションでは完全なテーブルスキャンが実行されるため、非効率的なオペレーションに なる可能性があります。代わりにクエリを使用してください。ただし場合によっては、テーブルに 対してスキャンを実行しなければならないことがあります。たとえば、次の C# コード例に示すよう に、製品価格にデータ入力エラーがあるためテーブルのスキャンを行う場合があります。この例では ProductCatalog テーブルをスキャンして、価格の値が 0 未満である製品を検索しています。この例 は、2 つの Table.Scan オーバーロードの使い方を示しています。 • ScanFilter オブジェクトをパラメータとする Table.Scan。 必須パラメータだけを渡す場合は、ScanFilter パラメータを渡すことができます。 • ScanOperationConfig オブジェクトをパラメータとする Table.Scan。 Scan メソッドにオプションパラメータを渡す場合には、ScanOperationConfig パラメータを使 用する必要があります。 using using using using using System; System.Collections.Generic; System.Linq; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DocumentModel; namespace com.amazonaws.codesamples { class MidLevelScanOnly { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { Table productCatalogTable = Table.LoadTable(client, "ProductCatalog"); // Scan example. FindProductsWithNegativePrice(productCatalogTable); FindProductsWithNegativePriceWithConfig(productCatalogTable); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void FindProductsWithNegativePrice(Table productCatalogTable) { // Assume there is a price error. So we scan to find items priced < 0. ScanFilter scanFilter = new ScanFilter(); scanFilter.AddCondition("Price", ScanOperator.LessThan, 0); Search search = productCatalogTable.Scan(scanFilter); List<Document> documentList = new List<Document>(); do { documentList = search.GetNextSet(); Console.WriteLine("\nFindProductsWithNegativePrice: printing ............"); foreach (var document in documentList) API Version 2012-08-10 137 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル PrintDocument(document); } while (!search.IsDone); } private static void FindProductsWithNegativePriceWithConfig(Table productCatalogTable) { // Assume there is a price error. So we scan to find items priced < 0. ScanFilter scanFilter = new ScanFilter(); scanFilter.AddCondition("Price", ScanOperator.LessThan, 0); ScanOperationConfig config = new ScanOperationConfig() { Filter = scanFilter, Select = SelectValues.SpecificAttributes, AttributesToGet = new List<string> { "Title", "Id" } }; Search search = productCatalogTable.Scan(config); List<Document> documentList = new List<Document>(); do { documentList = search.GetNextSet(); Console.WriteLine("\nFindProductsWithNegativePriceWithConfig: printing ............"); foreach (var document in documentList) PrintDocument(document); } while (!search.IsDone); } private static void PrintDocument(Document document) { // count++; Console.WriteLine(); foreach (var attribute in document.GetAttributeNames()) { string stringValue = null; var value = document[attribute]; if (value is Primitive) stringValue = value.AsPrimitive().Value.ToString(); else if (value is PrimitiveList) stringValue = string.Join(",", (from primitive in value.AsPrimitiveList().Entries select primitive.Value).ToArray()); Console.WriteLine("{0} - {1}", attribute, stringValue); } } } } .NET: オブジェクト永続性モデル トピック API Version 2012-08-10 138 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル • DynamoDB の属性 (p. 140) • DynamoDBContext クラス (p. 142) • サポートされているデータの種類 (p. 147) • DynamoDB で AWS SDK for .NET オブジェクト永続性モデルを使用した、バージョン番号による オプティミスティックロック (p. 148) • AWS SDK for .NET オブジェクト永続性モデルを使用した、DynamoDB での任意データのマッピ ング (p. 150) • AWS SDK for .NET オブジェクト永続性モデルを使用したバッチオペレーション (p. 153) • 例: AWS SDK for .NET オブジェクト永続性モデルを使用した CRUD オペレーション (p. 156) • 例: AWS SDK for .NET オブジェクト永続性モデルを使用したバッチ書き込みオペレーショ ン (p. 158) • 例: AWS SDK for .NET オブジェクト永続性モデルを使用した、DynamoDB でのクエリおよびス キャン (p. 161) AWS SDK for .NET には、クライアント側クラスを DynamoDB テーブルにマッピングできるオブジェ クト永続性モデルが用意されています。各オブジェクトインスタンスが、対応するテーブルの項目に マッピングされます。クライアント側オブジェクトをテーブルに保存するために、オブジェクト永続 性モデルでは、DynamoDB のエントリポイントとなる DynamoDBContext クラスを使用できます。 このクラスでは、DynamoDB に接続してテーブルにアクセスし、各種の CRUD オペレーションやク エリを実行することができます。 オブジェクト永続性モデルには、クライアント側クラスをテーブルにマッピングし、プロパティ/ フィールドを属性にマッピングする、属性のセットが用意されています。 Note オブジェクト永続性モデルには、テーブルを作成、更新、または削除するための API はあ りません。データオペレーションだけが可能になっています。テーブルを作成、更新、削除 するには、AWS SDK for .NET 低レベル API を使用する必要があります。詳細については、 「テーブルの操作 : .NET (p. 191)」を参照してください。 オブジェクト永続性モデルの機能を示すために、例を見てみましょう。まず ProductCatalog テーブル から示します。ここでは Id がプライマリキーになっています。 ProductCatalog(Id, ...) Title、ISBN、および Authors プロパティを持つ Book クラスがあるとします。次の C# コードスニ ペットに示すように、オブジェクト永続性モデルで定義された属性を追加することで、Book クラスを ProductCatalog テーブルにマッピングできます。 [DynamoDBTable("ProductCatalog")] public class Book { [DynamoDBHashKey] public int Id { get; set; } public string Title { get; set; } public int ISBN { get; set; } [DynamoDBProperty("Authors")] public List<string> BookAuthors { get; set; } [DynamoDBIgnore] public string CoverPage { get; set; } API Version 2012-08-10 139 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル } 前述の例では、DynamoDBTable 属性によって、Book クラスが ProductCatalog テーブルにマッピン グされています。 オブジェクト永続性モデルでは、クラスプロパティとテーブル属性との間で、明示的なマッピングと デフォルトのマッピングの両方がサポートされています。 • 明示的なマッピング – プライマリキーにプロパティをマッピングするには、オブジェクト永続性モ デル属性の DynamoDBHashKey および DynamoDBRangeKey を使用する必要があります。さらに、 非プライマリキー属性については、クラス内のプロパティ名と、マッピング先の対応するテーブル 属性が同じでない場合は、DynamoDBProperty 属性を明示的に追加してマッピングを定義する必 要があります。 前述の例では、Id プロパティが同じ名前のプライマリキーにマッピングされ、BookAuthors プロ パティが ProductCatalog テーブル内の Authors 属性にマッピングされています。 • デフォルトのマッピング – デフォルトでは、オブジェクト永続性モデルによって、クラスプロパ ティがテーブル内の同じ名前の属性にマッピングされます。 前述の例では、Title および ISBN プロパティが、ProductCatalog テーブル内の同じ名前の属性に マッピングされています。 すべてのクラスプロパティをマッピングする必要はありません。これらのプロパティを特定す るには、DynamoDBIgnore 属性を追加します。Book インスタンスをテーブルに保存する場 合、DynamoDBContext には CoverPage プロパティは含まれません。このプロパティは、書籍イン スタンスを取り出す場合にも返されません。 int や string など、.NET プリミティブ型のプロパティをマッピングできます。また、任意データをい ずれかの DynamoDB 型にマッピングする適切なコンバーターがある限り、任意のデータ型をマッピ ングすることもできます。任意の型のマッピングについては、「AWS SDK for .NET オブジェクト永 続性モデルを使用した、DynamoDB での任意データのマッピング (p. 150)」を参照してください。 オブジェクト永続性モデルでは、オプティミスティックロックがサポートされています。それによっ て、更新オペレーションで、更新する項目の最新のコピーを確実に使用することができます。詳細に ついては、「DynamoDB で AWS SDK for .NET オブジェクト永続性モデルを使用した、バージョン番 号によるオプティミスティックロック (p. 148)」を参照してください。 DynamoDB の属性 このセクションでは、クラスとプロパティを DynamoDB のテーブルや属性にマッピングできるよう に、オブジェクト永続性モデルで使用できる属性を示します。 Note 次の属性では、DynamoDBTable と DynamoDBHashKey だけが必須です。 DynamoDBGlobalSecondaryIndexHashKey グローバルセカンダリインデックスのパーティションキーにクラスプロパティをマッピングします。 この属性は、グローバルセカンダリインデックス の Query を実行する必要がある場合に使用しま す。 DynamoDBGlobalSecondaryIndexRangeKey グローバルセカンダリインデックスのソートキーにクラスプロパティをマッピングします。この属性 は、グローバルセカンダリインデックスの Query を実行し、インデックスソートキーを使用して結果 を絞り込む必要がある場合に使用します。 API Version 2012-08-10 140 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル DynamoDBHashKey テーブルのプライマリキーのパーティションキーにクラスプロパティをマッピングします。プライマ リキーの属性をコレクション型にすることはできません。 次の C# コード例では、Book クラスを ProductCatalog テーブルに、Id プロパティをテーブルのプラ イマリキーのパーティションキーにマッピングしています。 [DynamoDBTable("ProductCatalog")] public class Book { [DynamoDBHashKey] public int Id { get; set; } // Additional properties go here. } DynamoDBIgnore 関連するプロパティを無視するように指示します。クラスプロパティを保存しない場合は、この属 性を追加することで、テーブルにオブジェクトを保存するときにこのプロパティを含めないように DynamoDBContext に指示できます。 DynamoDBLocalSecondaryIndexRangeKey local secondary indexのソートキーにクラスプロパティをマッピングします。この属性は、local secondary indexの Query を実行し、インデックスソートキーを使用して結果を絞り込む必要がある 場合に使用します。 DynamoDBProperty テーブルの属性にクラスプロパティをマッピングします。クラスプロパティを同じ名前のテーブル属 性にマッピングする場合は、この属性を指定する必要はありません。ただし名前が異なる場合は、こ のタグを使用してマッピングを指定できます。次の C# ステートメントでは、DynamoDBProperty に よって、BookAuthors プロパティがテーブル内の Authors 属性にマッピングされています。 [DynamoDBProperty("Authors")] public List<string> BookAuthors { get; set; } DynamoDBContext はこのマッピング情報を使用して、対応するテーブルにオブジェクトデータを保 存するときに Authors 属性を作成します。 DynamoDBRenamable クラスプロパティの代替名を指定します。これは、クラスプロパティの名前がテーブル属性と異なる DynamoDB テーブルに任意のデータをマッピングするためのカスタムコンバーターを記述する場合に 役立ちます。 DynamoDBRangeKey テーブルのプライマリキーのソートキーにクラスプロパティをマッピングします。テーブルに 複合プライマリキー (パーティションキーおよびソートキー) がある場合は、クラスマッピング で、DynamoDBHashKey と DynamoDBRangeKey の両方の属性を指定する必要があります。 たとえば、サンプルテーブルの Reply には、Id パーティションキーと Replenishment ソートキーで構 成されたプライマリキーがあります。次の C# コード例では、Reply クラスを Reply テーブルにマッ ピングしています。クラス定義では、プロパティのうち 2 つがプライマリキーにマッピングされるこ とも示しています。 API Version 2012-08-10 141 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル サンプルテーブルの詳細については、「テーブルの作成とサンプルデータのロード (p. 166)」を参照 してください。 [DynamoDBTable("Reply")] public class Reply { [DynamoDBHashKey] public int ThreadId { get; set; } [DynamoDBRangeKey] public string Replenishment { get; set; } // Additional properties go here. } DynamoDBTable DynamoDB でクラスがマッピングされるターゲットテーブルを識別します。たとえば次の C# コード 例では、Developer クラスを DynamoDB の People テーブルにマッピングしています。 [DynamoDBTable("People")] public class Developer { ...} この属性は、継承またはオーバーライドすることができます。 • DynamoDBTable 属性は継承できます。前述の例では、Developer クラスから継承された新し いクラス Lead を追加すると、People テーブルにもマッピングされます。People テーブルに Developer と Lead の両方のオブジェクトが格納されます。 • DynamoDBTable 属性もオーバーライドできます。次の C# コード例では、Manager クラスは Developer クラスから継承していますが、DynamoDBTable 属性が明示的に追加されているため、 クラスが別のテーブル(Managers)にマッピングされています。 [DynamoDBTable("Managers")] public class Manager extends Developer { ...} オプションのパラメータ LowerCamelCaseProperties を追加すると、次の C# コードスニペッ トに示すように、オブジェクトを格納する場合にプロパティ名の先頭文字を小文字にするよう に、DynamoDB にリクエストできます。 [DynamoDBTable("People", LowerCamelCaseProperties=true)] public class Developer { string DeveloperName; ...} Developer クラスのインスタンスを保存する場合、DynamoDBContext では DeveloperName プロ パティが developerName として保存されます。 DynamoDBVersion 項目のバージョン番号を格納するクラスプロパティを識別します。バージョニングの詳細について は、「DynamoDB で AWS SDK for .NET オブジェクト永続性モデルを使用した、バージョン番号によ るオプティミスティックロック (p. 148)」を参照してください。 DynamoDBContext クラス DynamoDBContext クラスは、DynamoDB データベースのエントリポイントです。このクラスから DynamoDB に接続して、各種のテーブル内のデータにアクセスし、さまざまな CRUD オペレーショ API Version 2012-08-10 142 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル ンとクエリを実行することができます。DynamoDBContext クラスでは次のメソッドを使用できま す。 CreateMultiTableBatchGet 複数の個々の BatchGet オブジェクトで構成される MultiTableBatchGet オブジェクトを作成しま す。各 BatchGet オブジェクトは、1 つの DynamoDB テーブルから項目を取り出すときに使用でき ます。 1 つ以上のテーブルから項目を取り出すには、ExecuteBatchGet メソッドを使用 し、MultiTableBatchGet オブジェクトをパラメータとして渡します。 CreateMultiTableBatchWrite 複数の個々の BatchWrite オブジェクトで構成される MultiTableBatchWrite オブジェクトを作 成します。これらの BatchWrite オブジェクトはそれぞれ、1 つの DynamoDB テーブルの項目を書 き込んだり削除したりするために使用できます。 1 つ以上のテーブルに書き込むには、ExecuteBatchWrite メソッドを使用 し、MultiTableBatchWrite オブジェクトをパラメータとして渡します。 CreateBatchGet テーブルから複数の項目を取り出すために使用できる BatchGet オブジェクトを作成します。詳細に ついては、「バッチ取得: 複数の項目の取得 (p. 155)」を参照してください。 CreateBatchWrite テーブルに複数の項目を入力する、またはテーブルから複数の項目を削除するために使用できる BatchWrite オブジェクトを作成します。詳細については、「バッチ書き込み: 複数の項目の書き込 みおよび削除 (p. 153)」を参照してください。 Delete テーブルから項目を削除します。このメソッドでは、削除する項目のプライマリキーが必要になりま す。プライマリキーの値、またはこのメソッドのパラメータとしてプライマリキーの値を使用するク ライアント側オブジェクトを入力できます。 • クライアント側オブジェクトをパラメータとして指定し、オプティミスティックロックを有効にす ると、クライアント側とサーバー側のオブジェクトのバージョンが一致する場合のみ、削除が成功 します。 • プライマリキーの値だけをパラメータとして指定すると、オプティミスティックロックを有効にし ているかどうかにかかわらず、削除が成功します。 Note このオペレーションをバックグラウンドで実行するには、DeleteAsync メソッドを使用しま す。 Dispose すべてのマネージドリソースとアンマネージドリソースの Dispose を実行します。 ExecuteBatchGet 1 つ以上のテーブルからデータを読み込みます。MultiTableBatchGet 内のすべての BatchGet オ ブジェクトを処理します。 API Version 2012-08-10 143 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル Note このオペレーションをバックグラウンドで実行するには、ExecuteBatchGetAsync メソッ ドを使用します。 ExecuteBatchWrite 1 つ以上のテーブルにデータを書き込むまたは削除します。MultiTableBatchWrite 内のすべての BatchWrite オブジェクトを処理します。 Note このオペレーションをバックグラウンドで実行するには、ExecuteBatchWriteAsync メ ソッドを使用します。 FromDocument Document のインスタンスと仮定すると、FromDocument メソッドは、クライアント側のクラスのイ ンスタンスを返します。 これは、オブジェクト永続性モデルと合わせてドキュメントモデルクラスを使用してデータオペレー ションを行う場合に役立ちます。AWS SDK for .NET で使用されるドキュメントモデルクラスの詳細 については、「.NET ドキュメントモデル (p. 116)」を参照してください。 doc という名前の Document オブジェクトがあり、Forum 項目の表現を含んでいるとします。(この オブジェクトの構成方法については、下の ToDocument メソッドの説明を参照してください)。次の C# コードスニペットに示すように、FromDocument を使用して Document から Forum 項目を取り出 すことができます。 forum101 = context.FromDocument<Forum>(101); Note Document オブジェクトで IEnumerable インターフェイスを実装している場 合、FromDocuments メソッドを使用できます。これにより、Document のすべてのクラスイ ンスタンスを反復的に処理できます。 FromQuery QueryOperationConfig オブジェクトに定義されたクエリパラメータを使用して、Query オペレー ションを実行します。 Note このオペレーションをバックグラウンドで実行するには、FromQueryAsync メソッドを使用 します。 FromScan ScanOperationConfig オブジェクトに定義されたスキャンパラメータを使用して、Scan オペレー ションを実行します。 Note このオペレーションをバックグラウンドで実行するには、FromScanAsync メソッドを使用し ます。 API Version 2012-08-10 144 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル GetTargetTable 指定した型のターゲットテーブルを取り出します。これは、任意のデータを DynamoDB テーブルに マッピングするためのカスタムコンバーターを記述していて、カスタムデータ型に関連付けられてい るテーブルを特定する必要がある場合に役立ちます。 Load テーブルから項目を取り出します。このメソッドでは、取り出す項目のプライマリキーだけが必要に なります。 デフォルトでは、DynamoDB では結果整合性のある値を持つ項目が返されます。結果整合性モデルの 詳細については、「読み込み整合性 (p. 16)」を参照してください。 Note このオペレーションをバックグラウンドで実行するには、LoadAsync メソッドを使用しま す。 Query 指定したクエリパラメータに基づいてテーブルのクエリが実行されます。 複合プライマリキー (パーティションキーおよびソートキー) が存在する場合にのみ、テーブルにクエ リを実行できます。クエリを実行する場合は、パーティションキーと、ソートキーに適用される条件 を指定する必要があります。 クライアント側の Reply クラスが DynamoDB の Reply テーブルにマッピングされているとしま す。次の C# コードスニペットでは、Reply テーブルのクエリを実行し、過去 15 日間に投稿され たフォーラムスレッドの返信を検索しています。Reply テーブルには、Id パーティションキーと ReplyDateTime ソートキーを持つプライマリキーがあります。Reply テーブルの詳細については、 「テーブルの作成とサンプルデータのロード (p. 166)」を参照してください。 DynamoDBContext context = new DynamoDBContext(client); string replyId = "DynamoDB#DynamoDB Thread 1"; //Partition key DateTime twoWeeksAgoDate = DateTime.UtcNow.Subtract(new TimeSpan(14, 0, 0, 0)); // Date to compare. IEnumerable<Reply> latestReplies = context.Query<Reply>(replyId, QueryOperator.GreaterThan, twoWeeksAgoDate); これにより、Reply オブジェクトのコレクションが返されます。 Query メソッドでは、「遅延ロード」された IEnumerable コレクションが返されます。最初に結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われます。一 致するすべての項目は、IEnumerable を反復的に処理するだけで取得できます。 テーブルにシンプルなプライマリキー (パーティションキー) がある場合は、Query メソッドを使用す ることはできません。代わりに Load メソッドを使用して、パーティションキーを入力して項目を取 り出すことができます。 Note このオペレーションをバックグラウンドで実行するには、QueryAsync メソッドを使用しま す。 API Version 2012-08-10 145 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル Save 指定したオブジェクトがテーブルに保存されます。入力オブジェクトで指定されたプライマリキーが テーブル内に存在しない場合は、このメソッドによって新しい項目がテーブルに追加されます。プラ イマリキーが存在する場合は、このメソッドによって既存の項目が更新されます。 オプティミスティックロックを設定している場合には、クライアント側とサーバー側で項目のバー ジョンが一致する場合のみ、更新が正常に実行されます。詳細については、「DynamoDB で AWS SDK for .NET オブジェクト永続性モデルを使用した、バージョン番号によるオプティミスティック ロック (p. 148)」を参照してください。 Note このオペレーションをバックグラウンドで実行するには、SaveAsync メソッドを使用しま す。 Scan テーブル全体のスキャンを実行します。 スキャン条件を指定することで、スキャン結果にフィルタを適用することができます。この条件は、 テーブル内の任意の属性に適用することができます。クライアント側のクラス Book が、DynamoDB の ProductCatalog テーブルにマッピングされているとします。次の C# コードスニペットでは、テー ブルがスキャンされ、価格が 0 未満の書籍項目だけが返されています。 IEnumerable<Book> itemsWithWrongPrice = context.Scan<Book>( new ScanCondition("Price", ScanOperator.LessThan, price), new ScanCondition("ProductCategory", ScanOperator.Equal, "Book") ); Scan メソッドでは、「遅延ロード」された IEnumerable コレクションが返されます。最初に結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われます。一 致するすべての項目は、IEnumerable を反復的に処理するだけで取得できます。 パフォーマンス上の理由から、テーブルについてはスキャンを避け、クエリを行うようにしてくださ い。 Note このオペレーションをバックグラウンドで実行するには、ScanAsync メソッドを使用しま す。 ToDocument クラスインスタンスから、Document ドキュメントモデルクラスのインスタンスが返されます。 これは、オブジェクト永続性モデルと合わせてドキュメントモデルクラスを使用してデータオペレー ションを行う場合に役立ちます。AWS SDK for .NET で使用されるドキュメントモデルクラスの詳細 については、「.NET ドキュメントモデル (p. 116)」を参照してください。 クライアント側のクラスが Forum サンプルテーブルにマッピングされているとします。その場合は次 の C# コードスニペットに示すように、DynamoDBContext を使用して、Forum テーブルから項目を Document オブジェクトとして取得することができます。 DynamoDBContext context = new DynamoDBContext(client); API Version 2012-08-10 146 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル Forum forum101 = context.Load<Forum>(101); // Retrieve a forum by primary key. Document doc = context.ToDocument<Forum>(forum101); DynamoDBContext でのオプションパラメータの指定 オブジェクト永続性モデルを使用する場合は、DynamoDBContext に次のオプションパラメータを指 定できます。 • ConsistentRead – Load、Query、または Scan オペレーションを使用してデータを取り出す場合 は、このパラメータをオプションで追加して、データの最新の値をリクエストすることができま す。 • IgnoreNullValues – このパラメータにより、Save オペレーション時に属性の null 値を無視するよう に DynamoDBContext に指示できます。このパラメータが false の場合(または設定されていない 場合)、null 値は、特定の属性を削除するディレクティブと見なされます。 • SkipVersionCheck – このパラメータにより、項目を保存または削除する場合にバージョンの比 較を行わないように DynamoDBContext に指示できます。バージョニングの詳細については、 「DynamoDB で AWS SDK for .NET オブジェクト永続性モデルを使用した、バージョン番号による オプティミスティックロック (p. 148)」を参照してください。 • TableNamePrefix – すべてのテーブル名に特定の文字列をプレフィックスとして付けます。このパ ラメータが null の場合(または設定されていない場合)、プレフィックスは使用されません。 次の C# コードスニペットでは、前述のオプションパラメータのうち、2 つを指定して、新しい DynamoDBContext を作成しています。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); ... DynamoDBContext context = new DynamoDBContext(client, new DynamoDBContextConfig { ConsistentRead = true, SkipVersionCheck = true}); DynamoDBContext では、このコンテキストを使用して送信した各リクエストに、これらのオプショ ンパラメータが含められます。 これらのパラメータを DynamoDBContext レベルで設定する代わりに、次の C# コードスニペットに 示すように、DynamoDBContext を使用して実行する個々のオペレーションに対して指定することも できます。この例では特定の書籍項目がロードされています。DynamoDBContext の Load メソッド では、前述のオプションパラメータを指定します。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); ... DynamoDBContext context = new DynamoDBContext(client); Book bookItem = context.Load<Book>(productId,new DynamoDBContextConfig{ ConsistentRead = true, SkipVersionCheck = true }); この場合 DynamoDBContext には、Get リクエストを送信する場合のみ、これらのパラメータが含ま れます。 サポートされているデータの種類 オブジェクト永続性モデルでは、プリミティブな .NET データ型、コレクション、および任意のデー タ型のセットがサポートされています。このモデルでは、次のプリミティブデータ型がサポートされ ています。 • bool API Version 2012-08-10 147 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル • byte • char • DateTime • decimal • double • float • Int16 • Int32 • Int64 • SByte • string • UInt16 • UInt32 • UInt64 オブジェクト永続性モデルでは、次の制限の下で .NET コレクション型もサポートされています。 • コレクション型は ICollection インターフェイスを実装する必要があります。 • コレクション型は、サポートされているプリミティブ型で構成されている必要があります。たとえ ば、ICollection<string> や ICollection<bool> などです。 • コレクション型では、パラメータがないコンストラクタを使用できなければなりません。 次の表に、前述の .NET 型が DynamoDB の型にどのようにマッピングされるかを示します。 .NET プリミティブ型 DynamoDB の型 すべての数値型 N(数値型) すべての文字列型 S (文字列型) MemoryStream、byte[] B(バイナリ型) ブール N(数値型)、0 は偽を表し 1 は真を表す。 コレクション型 BS(バイナリセット)型、SS(文字列セット) 型、NS(数値セット)型 DateTime S(文字列型)。DateTime の値は、ISO-8601 形 式の文字列として格納されます。 オブジェクト永続性モデルでは、任意のデータ型もサポートされています。ただし、複合型を DynamoDB 型にマッピングするためのコンバーターコードを入力する必要があります。 DynamoDB で AWS SDK for .NET オブジェクト永続性モデル を使用した、バージョン番号によるオプティミスティックロッ ク オブジェクト永続性モデルではオプティミスティックロックがサポートされており、項目を更新また は削除する前に、アプリケーションの項目バージョンとサーバー側の項目バージョンが同じになりま す。更新する項目を取り出すとします。しかし、更新を返送する前に、他のアプリケーションが同じ 項目を更新しました。この場合、アプリケーションに項目の古いコピーが残ることになります。オプ API Version 2012-08-10 148 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル ティミスティックロックがない場合に更新を行うと、他のアプリケーションで行われた更新が上書き されます。 オブジェクト永続性モデルのオプティミスティックロック機能では、オプティミスティックロックを 有効にするために DynamoDBVersion タグを使用できます。この機能を使用するには、バージョン番 号を格納するためのプロパティをクラスに追加します。DynamoDBVersion 属性をプロパティに追加 します。最初にオブジェクトを保存すると、DynamoDBContext によってバージョン番号が割り当て られ、項目を更新するたびにその値が増えていきます。 更新または削除リクエストは、クライアント側のオブジェクトのバージョンが、サーバー側の対応す る項目のバージョン番号に一致する場合のみ成功します。アプリケーションに古いコピーがある場 合に項目を更新または削除するには、その前にサーバーから最新バージョンを取得する必要がありま す。 次の C# コードスニペットでは、オブジェクト永続性属性と合わせて Book クラスを定義 し、ProductCatalog テーブルにマッピングしています。DynamoDBVersion 属性が指定されたクラス の VersionNumber プロパティには、バージョン番号が格納されます。 [DynamoDBTable("ProductCatalog")] public class Book { [DynamoDBHashKey] //Partition key public int Id { get; set; } [DynamoDBProperty] public string Title { get; set; } [DynamoDBProperty] public string ISBN { get; set; } [DynamoDBProperty("Authors")] public List<string> BookAuthors { get; set; } [DynamoDBVersion] public int? VersionNumber { get; set; } } Note DynamoDBVersion 属性は、null が許容された数値プリミティブ型(int? など)に対しての み適用できます。 オプティミスティックロックは、DynamoDBContext オペレーションに対して次のような影響があり ます。 • 保存—DynamoDBContext は、新しい項目に対して初期バージョン番号 0 を割り当てます。 既存の項目を取り出し、その項目の 1 つ以上のプロパティを更新して変更を保存する場合 には、クライアント側とサーバー側のバージョン番号が一致する場合のみ、保存が成功しま す。DynamoDBContext によってバージョン番号が増加します。バージョン番号を設定する必要は ありません。 • 削除—次の C# コードスニペットに示すように、Delete メソッドでは、プライマリキーの値または オブジェクトのいずれかをパラメータとして指定できるオーバーロードを使用できます。 DynamoDBContext context = new DynamoDBContext(client); ... // Load a book. Book book = context.Load<ProductCatalog>(111); // Do other operations. // Delete 1 - Pass in the book object. context.Delete<ProductCatalog>(book); API Version 2012-08-10 149 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル // Delete 2 - pass in the Id (primary key) context.Delete<ProductCatalog>(222); パラメータとしてオブジェクトを指定した場合には、オブジェクトのバージョンがサーバー側の対 応する項目のバージョンと一致する場合のみ、削除が可能になります。ただしパラメータとしてプ ライマリキーの値を入力した場合には、DynamoDBContext はバージョン番号を認識せず、バー ジョンチェックを行わずに項目を削除します。 オブジェクト永続性モデルのコードでは、オプティミスティックロックの内部実装で、DynamoDB の条件付き更新と条件付き削除 API アクションが使用されます。 オプティミスティックロックの無効化 オプティミスティックロックを無効にするには、SkipVersionCheck 設定プロパティを使用しま す。このプロパティは、DynamoDBContext の作成時に設定できます。この場合、このコンテキスト を使用して作成したすべてのリクエストについて、オプティミスティックロックが無効になります。 詳細については、「DynamoDBContext でのオプションパラメータの指定 (p. 147)」を参照してく ださい。 コンテキストレベルでプロパティを設定する代わりに、次の C# コードスニペットに示すように、 特定のオペレーションに対するオプティミスティックロックを無効にすることができます。コード 例では、このコンテキストを使用して書籍項目を削除しています。Delete メソッドはオプションの SkipVersionCheck プロパティを true に設定し、バージョンチェックを無効にします。 DynamoDBContext context = new DynamoDBContext(client); // Load a book. Book book = context.Load<ProductCatalog>(111); ... // Delete the book. context.Delete<Book>(book, new DynamoDBContextConfig { SkipVersionCheck = true }); AWS SDK for .NET オブジェクト永続性モデルを使用し た、DynamoDB での任意データのマッピング サポートされている .NET 型(「サポートされているデータの種類 (p. 147)」を参照)に加え て、DynamoDB 型に直接マッピングされない型を、アプリケーションで使用できます。オブジェクト 永続性モデルでは、任意の型から DynamoDB 型に、またはその反対にデータを変換できるコンバー ターがある限り、任意の型のデータを格納できます。コンバーターコードによって、オブジェクトの 保存およびロード中にデータが変換されます。 クライアント側ではどのような型でも作成できますが、テーブルに格納されているデータは DynamoDB 型の一種であり、クエリおよびスキャンでは、データの比較は DynamoDB に格納されて いるデータに対して行われます。 次の C# コード例では、Id、Title、ISBN、および Dimension プロパティを使用して Book クラス を定義しています。Dimension プロパティは、Height、Width、および Thickness プロパティを 記述する DimensionType に含まれています。このコード例では、コンバーターメソッド ToEntry および FromEntry によって、DimensionType と DynamoDB 文字列型との間でデータが変換されて います。たとえば Book インスタンスを保存する場合には、コンバーターによって "8.5x11x.05" など の書籍の寸法文字列が作成され、書籍を取り出す場合には、文字列が DimensionType インスタンス に変換されます。 この例では、Book 型を ProductCatalog テーブルにマッピングしています。説明のために、サンプ ルの Book インスタンスを保存し、取り出し、寸法を更新し、更新された Book を再度保存していま す。 API Version 2012-08-10 150 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル 次のサンプルをテストするための詳しい手順については、『.NET コードサンプル (p. 173)』を参照 してください。 using using using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DataModel; Amazon.DynamoDBv2.DocumentModel; Amazon.Runtime; Amazon.SecurityToken; namespace com.amazonaws.codesamples { class HighLevelMappingArbitraryData { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { DynamoDBContext context = new DynamoDBContext(client); // 1. Create a book. DimensionType myBookDimensions = new DimensionType() { Length = 8M, Height = 11M, Thickness = 0.5M }; Book myBook = new Book { Id = 501, Title = "AWS SDK for .NET Object Persistence Model Handling Arbitrary Data", ISBN = "999-9999999999", BookAuthors = new List<string> { "Author 1", "Author 2" }, Dimensions = myBookDimensions }; context.Save(myBook); // 2. Retrieve the book. Book bookRetrieved = context.Load<Book>(501); // 3. Update property (book dimensions). bookRetrieved.Dimensions.Height += 1; bookRetrieved.Dimensions.Length += 1; bookRetrieved.Dimensions.Thickness += 0.2M; // Update the book. context.Save(bookRetrieved); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } API Version 2012-08-10 151 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } } [DynamoDBTable("ProductCatalog")] public class Book { [DynamoDBHashKey] //Partition key public int Id { get; set; } [DynamoDBProperty] public string Title { get; set; } [DynamoDBProperty] public string ISBN { get; set; } // Multi-valued (set type) attribute. [DynamoDBProperty("Authors")] public List<string> BookAuthors { get; set; } // Arbitrary type, with a converter to map it to DynamoDB type. [DynamoDBProperty(typeof(DimensionTypeConverter))] public DimensionType Dimensions { get; set; } } public class DimensionType { public decimal Length { get; set; } public decimal Height { get; set; } public decimal Thickness { get; set; } } // Converts the complex type DimensionType to string and vice-versa. public class DimensionTypeConverter : IPropertyConverter { public DynamoDBEntry ToEntry(object value) { DimensionType bookDimensions = value as DimensionType; if (bookDimensions == null) throw new ArgumentOutOfRangeException(); string data = string.Format("{1}{0}{2}{0}{3}", " x ", bookDimensions.Length, bookDimensions.Height, bookDimensions.Thickness); DynamoDBEntry entry = new Primitive { Value = data }; return entry; } public object FromEntry(DynamoDBEntry entry) { Primitive primitive = entry as Primitive; if (primitive == null || !(primitive.Value is String) || string.IsNullOrEmpty((string)primitive.Value)) throw new ArgumentOutOfRangeException(); string[] data = ((string)(primitive.Value)).Split(new string[] { " x " }, StringSplitOptions.None); if (data.Length != 3) throw new ArgumentOutOfRangeException(); API Version 2012-08-10 152 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル DimensionType complexData = new DimensionType { Length = Convert.ToDecimal(data[0]), Height = Convert.ToDecimal(data[1]), Thickness = Convert.ToDecimal(data[2]) }; return complexData; } } } AWS SDK for .NET オブジェクト永続性モデルを使用したバッ チオペレーション バッチ書き込み: 複数の項目の書き込みおよび削除 単一のリクエストでテーブルに対して複数のオブジェクトを入力または削除するには、次の手順を実 行します。 • DynamoDBContext の CreateBatchWrite メソッドを実行して、BatchWrite クラスのインスタ ンスを作成します。 • 入力または削除する項目を指定します。 • 1 つ以上の項目を入力するには、AddPutItem または AddPutItems メソッドを使用します。 • 1 つ以上の項目を削除するには、項目のプライマリキーを指定するか、削除する項目にマッ ピングするクライアント側オブジェクトを指定します。削除する項目のリストを指定するに は、AddDeleteItem、AddDeleteItems、および AddDeleteKey メソッドを使用します。 • 指定したすべての項目をテーブルに入力またはテーブルから削除するには、BatchWrite.Execute メソッドを呼び出します。 Note オブジェクト永続性モデルを使用する場合には、バッチ内で任意の数のオペレーションを指 定できます。ただし DynamoDB では、1 つのバッチ内のオペレーションの数と、1 つのバッ チオペレーションでのバッチの合計サイズが制限されています。制限の具体的な詳細につい ては、BatchWriteItem を参照してください。許容されている書き込みリクエスト数、または 許容されている HTTP ペイロードの最大サイズをバッチ書き込みリクエストが超えたことを API が検出すると、バッチが複数の小さなバッチに分割されます。さらに、バッチ書き込みに 対する応答で、未処理の項目が返された場合には、API がそれら未処理の項目を使用して、別 のバッチリクエストを自動的に送信します。 DynamoDB の ProductCatalog テーブルにマッピングされる、C# クラスの Book クラスを定 義しているとします。次の C# コードスニペットでは、BatchWrite オブジェクトを使用し て、ProductCatalog テーブルに 2 つの項目をアップロードし、1 つの項目を削除しています。 DynamoDBContext context = new DynamoDBContext(client); var bookBatch = context.CreateBatchWrite<Book>(); // 1. Specify two books to add. Book book1 = new Book { Id = 902, ISBN = "902-11-11-1111", ProductCategory = "Book", Title = "My book3 in batch write" }; API Version 2012-08-10 153 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル Book book2 = new Book { Id = 903, ISBN = "903-11-11-1111", ProductCategory = "Book", Title = "My book4 in batch write" }; bookBatch.AddPutItems(new List<Book> { book1, book2 }); // 2. Specify one book to delete. bookBatch.AddDeleteKey(111); bookBatch.Execute(); 複数のテーブルを対象にオブジェクトを入力または削除するには、次の手順を実行します。 • それぞれの型について BatchWrite クラスの 1 つのインスタンスを作成し、前述のセクションで説 明したように、入力または削除する項目を指定します。 • 次のいずれかの方法を使用して、MultiTableBatchWrite のインスタンスを作成します。 • 前述のステップで作成したいずれかの BatchWrite オブジェクトで、Combine メソッドを実行 します。 • BatchWrite オブジェクトのリストを入力して、MultiTableBatchWrite 型のインスタンスを 作成します。 • DynamoDBContext の CreateMultiTableBatchWrite メソッドを実行して、BatchWrite オ ブジェクトのリストを渡します。 • 指定された入力および削除オペレーションを各種のテーブルで実行す る、MultiTableBatchWrite の Execute メソッドを呼び出します。 DynamoDB で Forum および Thread テーブルにマッピングされる、Forum および Thread C# クラス を定義しているとします。さらに、Thread クラスでバージョニングが有効になっているとします。 バッチオペレーションではバージョニングがサポートされていないため、次の C# コードスニペッ トに示すように、バージョニングを明示的に無効にする必要があります。このコードスニペットで は、MultiTableBatchWrite オブジェクトを使用して複数のテーブルを更新しています。 DynamoDBContext context = new DynamoDBContext(client); // Create BatchWrite objects for each of the Forum and Thread classes. var forumBatch = context.CreateBatchWrite<Forum>(); DynamoDBOperationConfig config = new DynamoDBOperationConfig(); config.SkipVersionCheck = true; var threadBatch = context.CreateBatchWrite<Thread>(config); // 1. New Forum item. Forum newForum = new Forum { Name = "Test BatchWrite Forum", Threads = 0 }; forumBatch.AddPutItem(newForum); // 2. Specify a forum to delete by specifying its primary key. forumBatch.AddDeleteKey("Some forum"); // 3. New Thread item. API Version 2012-08-10 154 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル Thread newThread = new Thread { ForumName = "Amazon S3 forum", Subject = "My sample question", KeywordTags = new List<string> { "Amazon S3", "Bucket" }, Message = "Message text" }; threadBatch.AddPutItem(newThread); // Now execute multi-table batch write. var superBatch = new MultiTableBatchWrite(forumBatch, threadBatch); superBatch.Execute(); 実例については、「例: AWS SDK for .NET オブジェクト永続性モデルを使用したバッチ書き込みオペ レーション (p. 158)」を参照してください。 Note DynamoDB バッチ API では、バッチ内の書き込み数と、バッチのサイズが制限されていま す。詳細については、BatchWriteItem を参照してください。.NET オブジェクト永続性モデル API を使用する場合は、任意の数のオペレーションを指定できます。ただし、バッチ内のオ ペレーションの数またはサイズが制限を超えた場合には、.NET API がバッチ書き込みリクエ ストを小さいバッチに分割して、複数のバッチ書き込みリクエストを DynamoDB に送信しま す。 バッチ取得: 複数の項目の取得 単一のリクエストでテーブルから複数の項目を取り出すには、次の手順を実行します。 • CreateBatchGet クラスのインスタンスを作成します。 • 取り出すプライマリキーのリストを指定します。 • Execute メソッドを呼び出します。応答では、項目が Results プロパティによって返されます。 次の C# コードのサンプルでは、ProductCatalog テーブルから 3 つの項目を取り出しています。結果 内の項目の順序は、必ずしもプライマリキーを指定した順序と同じではありません。 DynamoDBContext context = new DynamoDBContext(client); var bookBatch = context.CreateBatchGet<ProductCatalog>(); bookBatch.AddKey(101); bookBatch.AddKey(102); bookBatch.AddKey(103); bookBatch.Execute(); // Process result. Console.WriteLine(devBatch.Results.Count); Book book1 = bookBatch.Results[0]; Book book2 = bookBatch.Results[1]; Book book3 = bookBatch.Results[2]; 複数のテーブルからオブジェクトを取り出すには、次の手順を実行します。 • それぞれの型について CreateBatchGet 型のインスタンスを作成し、各テーブルから取り出すプ ライマリキーの値を指定します。 • 次のいずれかの方法を使用して、MultiTableBatchGet クラスのインスタンスを作成します。 • 前述のステップで作成したいずれかの BatchGet オブジェクトで、Combine メソッドを実行しま す。 API Version 2012-08-10 155 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル • BatchGet オブジェクトのリストを入力して、MultiBatchGet 型のインスタンスを作成しま す。 • DynamoDBContext の CreateMultiTableBatchGet メソッドを実行して、BatchGet オブ ジェクトのリストを渡します。 • MultiTableBatchGet の Execute メソッドを呼び出すと、個々の BatchGet オブジェクトに結 果が返されます。 次の C# コードスニペットでは、CreateBatchGet メソッドを使用して、Order および OrderDetail テーブルから複数の項目を取り出しています。 var orderBatch = context.CreateBatchGet<Order>(); orderBatch.AddKey(101); orderBatch.AddKey(102); var orderDetailBatch = context.CreateBatchGet<OrderDetail>(); orderDetailBatch.AddKey(101, "P1"); orderDetailBatch.AddKey(101, "P2"); orderDetailBatch.AddKey(102, "P3"); orderDetailBatch.AddKey(102, "P1"); var orderAndDetailSuperBatch = orderBatch.Combine(orderDetailBatch); orderAndDetailSuperBatch.Execute(); Console.WriteLine(orderBatch.Results.Count); Console.WriteLine(orderDetailBatch.Results.Count); Order order1 = orderBatch.Results[0]; Order order2 = orderDetailBatch.Results[1]; OrderDetail orderDetail1 = orderDetailBatch.Results[0]; 例: AWS SDK for .NET オブジェクト永続性モデルを使用した CRUD オペレーション 次の C# コード例では、Id、title、ISBN、および Authors プロパティを指定して、Book クラスを 宣言しています。これらのプロパティは、オブジェクト永続性属性を使用して、DynamoDB の ProductCatalog テーブルにマッピングされています。さらにこのコード例では、DynamoDBContext を使用して一般的な CRUD オペレーションを実行しています。この例では、サンプルの Book インス タンスを作成して ProductCatalog テーブルに保存しています。さらに書籍項目を取り出し、ISBN お よび Authors プロパティを更新しています。更新によって、既存の作成者リストが置き換えられてい ることに注意してください。この例では最終的に書籍項目が削除されています。 この例で使用されている ProductCatalog テーブルの詳細については、「テーブルの作成とサンプル データのロード (p. 166)」を参照してください。次のサンプルをテストするための詳しい手順につい ては、「.NET コードサンプル (p. 173)」を参照してください。 Note 以下の例は、同期メソッドをサポートしていないため、.NET Core コアには適用されませ ん。詳細については、「AWS の .NET 用非同期 API」を参照してください。 using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DataModel; Amazon.Runtime; API Version 2012-08-10 156 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル namespace com.amazonaws.codesamples { class HighLevelItemCRUD { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { DynamoDBContext context = new DynamoDBContext(client); TestCRUDOperations(context); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } private static void TestCRUDOperations(DynamoDBContext context) { int bookID = 1001; // Some unique value. Book myBook = new Book { Id = bookID, Title = "object persistence-AWS SDK for.NET SDK-Book 1001", ISBN = "111-1111111001", BookAuthors = new List<string> { "Author 1", "Author 2" }, }; // Save the book. context.Save(myBook); // Retrieve the book. Book bookRetrieved = context.Load<Book>(bookID); // Update few properties. bookRetrieved.ISBN = "222-2222221001"; bookRetrieved.BookAuthors = new List<string> { " Author 1", "Author x" }; // Replace existing authors list with this. context.Save(bookRetrieved); // Retrieve the updated book. This time add the optional ConsistentRead parameter using DynamoDBContextConfig object. Book updatedBook = context.Load<Book>(bookID, new DynamoDBContextConfig { ConsistentRead = true }); // Delete the book. context.Delete<Book>(bookID); // Try to retrieve deleted book. It should return null. Book deletedBook = context.Load<Book>(bookID, new DynamoDBContextConfig { ConsistentRead = true }); if (deletedBook == null) Console.WriteLine("Book is deleted"); API Version 2012-08-10 157 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル } } [DynamoDBTable("ProductCatalog")] public class Book { [DynamoDBHashKey] //Partition key public int Id { get; set; } [DynamoDBProperty] public string Title { get; set; } [DynamoDBProperty] public string ISBN { get; set; } [DynamoDBProperty("Authors")] //String Set datatype public List<string> BookAuthors { get; set; } } } 例: AWS SDK for .NET オブジェクト永続性モデルを使用した バッチ書き込みオペレーション 次の C# コード例では、Book、Forum、Thread、および Reply クラスが宣言され、オブジェクト永続 性モデル属性を使用して、DynamoDB テーブルにマッピングされています。 このコード例ではさらに DynamoDBContext を使用して、次のバッチ書き込みオペレーションを示し ています。 • ProductCatalog テーブルに対して書籍項目を入力または削除する BatchWrite オブジェクト。 • Forum および Thread テーブルに対して項目を入力または削除する MultiTableBatchWrite オブ ジェクト。 この例で使用されているテーブルの詳細については、「テーブルの作成とサンプルデータのロー ド (p. 166)」を参照してください。次のサンプルをテストするための詳しい手順については、 「.NET コードサンプル (p. 173)」を参照してください。 using using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DataModel; Amazon.Runtime; Amazon.SecurityToken; namespace com.amazonaws.codesamples { class HighLevelBatchWriteItem { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { DynamoDBContext context = new DynamoDBContext(client); SingleTableBatchWrite(context); MultiTableBatchWrite(context); } API Version 2012-08-10 158 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void SingleTableBatchWrite(DynamoDBContext context) { Book book1 = new Book { Id = 902, InPublication = true, ISBN = "902-11-11-1111", PageCount = "100", Price = 10, ProductCategory = "Book", Title = "My book3 in batch write" }; Book book2 = new Book { Id = 903, InPublication = true, ISBN = "903-11-11-1111", PageCount = "200", Price = 10, ProductCategory = "Book", Title = "My book4 in batch write" }; var bookBatch = context.CreateBatchWrite<Book>(); bookBatch.AddPutItems(new List<Book> { book1, book2 }); Console.WriteLine("Performing batch write in SingleTableBatchWrite()."); bookBatch.Execute(); } private static void MultiTableBatchWrite(DynamoDBContext context) { // 1. New Forum item. Forum newForum = new Forum { Name = "Test BatchWrite Forum", Threads = 0 }; var forumBatch = context.CreateBatchWrite<Forum>(); forumBatch.AddPutItem(newForum); // 2. New Thread item. Thread newThread = new Thread { ForumName = "S3 forum", Subject = "My sample question", KeywordTags = new List<string> { "S3", "Bucket" }, Message = "Message text" }; API Version 2012-08-10 159 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル DynamoDBOperationConfig config = new DynamoDBOperationConfig(); config.SkipVersionCheck = true; var threadBatch = context.CreateBatchWrite<Thread>(config); threadBatch.AddPutItem(newThread); threadBatch.AddDeleteKey("some partition key value", "some sort key value"); var superBatch = new MultiTableBatchWrite(forumBatch, threadBatch); Console.WriteLine("Performing batch write in MultiTableBatchWrite()."); superBatch.Execute(); } } [DynamoDBTable("Reply")] public class Reply { [DynamoDBHashKey] //Partition key public string Id { get; set; } [DynamoDBRangeKey] //Sort key public DateTime ReplyDateTime { get; set; } // Properties included implicitly. public string Message { get; set; } // Explicit property mapping with object persistence model attributes. [DynamoDBProperty("LastPostedBy")] public string PostedBy { get; set; } // Property to store version number for optimistic locking. [DynamoDBVersion] public int? Version { get; set; } } [DynamoDBTable("Thread")] public class Thread { // PK mapping. [DynamoDBHashKey] //Partition key public string ForumName { get; set; } [DynamoDBRangeKey] //Sort key public String Subject { get; set; } // Implicit mapping. public string Message { get; set; } public string LastPostedBy { get; set; } public int Views { get; set; } public int Replies { get; set; } public bool Answered { get; set; } public DateTime LastPostedDateTime { get; set; } // Explicit mapping (property and table attribute names are different. [DynamoDBProperty("Tags")] public List<string> KeywordTags { get; set; } // Property to store version number for optimistic locking. [DynamoDBVersion] public int? Version { get; set; } } API Version 2012-08-10 160 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル [DynamoDBTable("Forum")] public class Forum { [DynamoDBHashKey] //Partition key public string Name { get; set; } // All the following properties are explicitly mapped, // only to show how to provide mapping. [DynamoDBProperty] public int Threads { get; set; } [DynamoDBProperty] public int Views { get; set; } [DynamoDBProperty] public string LastPostBy { get; set; } [DynamoDBProperty] public DateTime LastPostDateTime { get; set; } [DynamoDBProperty] public int Messages { get; set; } } [DynamoDBTable("ProductCatalog")] public class Book { [DynamoDBHashKey] //Partition key public int Id { get; set; } public string Title { get; set; } public string ISBN { get; set; } public int Price { get; set; } public string PageCount { get; set; } public string ProductCategory { get; set; } public bool InPublication { get; set; } } } 例: AWS SDK for .NET オブジェクト永続性モデルを使用し た、DynamoDB でのクエリおよびスキャン このセクションの C# コード例では、次のクラスを定義して、DynamoDB 内のテーブルにマッピング しています。この例で使用されているテーブルの作成については、「テーブルの作成とサンプルデー タのロード (p. 166)」を参照してください。 • Book クラスは ProductCatalog テーブルにマッピングされます。 • Forum、Thread、および Reply クラスは、同じ名前テーブルにマッピングされます。 この例では DynamoDBContext を使用して、さらに次のクエリとスキャンオペレーションを実行して います。 • Id によって書籍を取得します。 ProductCatalog テーブルでは Id がプライマリキーになっています。プライマリキーの一部にソート キーは含まれていません。したがって、テーブルのクエリを行うことはできません。項目は Id 値を 使用して取得できます。 • Reply テーブルに対して次のクエリを実行します(Reply テーブルのプライマリキーは Id および ReplyDateTime 属性で構成されています。ReplyDateTime はソートキーです。したがってこのテー ブルではクエリを実行できます)。 • 過去 15 日間に投稿されたフォーラムスレッドに対する返信を検索します。 API Version 2012-08-10 161 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル • 特定の日付範囲の間に投稿されたフォーラムスレッドに対する返信を検索します。 • ProductCatalog テーブルをスキャンし、価格が 0 未満である書籍を検索します。 パフォーマンス上の理由から、スキャンオペレーションではなくクエリを使用するようにしてくだ さい。ただし、場合によってはテーブルをスキャンする必要があります。データ入力エラーがあ り、書籍の価格の 1 つが 0 未満に設定されたとします。この例では、ProductCategory テーブルを スキャンして、価格が 0 未満である書籍項目(ProductCategory は書籍)を検索しています。 実例を作成する手順については、「.NET コードサンプル (p. 173)」を参照してください。 using using using using using using using System; System.Collections.Generic; System.Configuration; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DataModel; Amazon.DynamoDBv2.DocumentModel; Amazon.Runtime; namespace com.amazonaws.codesamples { class HighLevelQueryAndScan { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { DynamoDBContext context = new DynamoDBContext(client); // Get item. GetBook(context, 101); // Sample forum and thread to test queries. string forumName = "Amazon DynamoDB"; string threadSubject = "DynamoDB Thread 1"; // Sample queries. FindRepliesInLast15Days(context, forumName, threadSubject); FindRepliesPostedWithinTimePeriod(context, forumName, threadSubject); // Scan table. FindProductsPricedLessThanZero(context); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } private static void GetBook(DynamoDBContext context, int productId) { Book bookItem = context.Load<Book>(productId); API Version 2012-08-10 162 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル Console.WriteLine("\nGetBook: Printing result....."); Console.WriteLine("Title: {0} \n No.Of threads:{1} \n No. of messages: {2}", bookItem.Title, bookItem.ISBN, bookItem.PageCount); } private static void FindRepliesInLast15Days(DynamoDBContext context, string forumName, string threadSubject) { string replyId = forumName + "#" + threadSubject; DateTime twoWeeksAgoDate = DateTime.UtcNow TimeSpan.FromDays(15); IEnumerable<Reply> latestReplies = context.Query<Reply>(replyId, QueryOperator.GreaterThan, twoWeeksAgoDate); Console.WriteLine("\nFindRepliesInLast15Days: Printing result....."); foreach (Reply r in latestReplies) Console.WriteLine("{0}\t{1}\t{2}\t{3}", r.Id, r.PostedBy, r.Message, r.ReplyDateTime); } private static void FindRepliesPostedWithinTimePeriod(DynamoDBContext context, string forumName, string threadSubject) { string forumId = forumName + "#" + threadSubject; Console.WriteLine("\nFindRepliesPostedWithinTimePeriod: Printing result....."); DateTime startDate = DateTime.UtcNow - TimeSpan.FromDays(30); DateTime endDate = DateTime.UtcNow - TimeSpan.FromDays(1); IEnumerable<Reply> repliesInAPeriod = context.Query<Reply>(forumId, QueryOperator.Between, startDate, endDate); foreach (Reply r in repliesInAPeriod) Console.WriteLine("{0}\t{1}\t{2}\t{3}", r.Id, r.PostedBy, r.Message, r.ReplyDateTime); } private static void FindProductsPricedLessThanZero(DynamoDBContext context) { int price = 0; IEnumerable<Book> itemsWithWrongPrice = context.Scan<Book>( new ScanCondition("Price", ScanOperator.LessThan, price), new ScanCondition("ProductCategory", ScanOperator.Equal, "Book") ); Console.WriteLine("\nFindProductsPricedLessThanZero: Printing result....."); foreach (Book r in itemsWithWrongPrice) API Version 2012-08-10 163 Amazon DynamoDB 開発者ガイド .NET: オブジェクト永続性モデル Console.WriteLine("{0}\t{1}\t{2}\t{3}", r.Id, r.Title, r.Price, r.ISBN); } } [DynamoDBTable("Reply")] public class Reply { [DynamoDBHashKey] //Partition key public string Id { get; set; } [DynamoDBRangeKey] //Sort key public DateTime ReplyDateTime { get; set; } // Properties included implicitly. public string Message { get; set; } // Explicit property mapping with object persistence model attributes. [DynamoDBProperty("LastPostedBy")] public string PostedBy { get; set; } // Property to store version number for optimistic locking. [DynamoDBVersion] public int? Version { get; set; } } [DynamoDBTable("Thread")] public class Thread { // PK mapping. [DynamoDBHashKey] //Partition key public string ForumName { get; set; } [DynamoDBRangeKey] //Sort key public DateTime Subject { get; set; } // Implicit mapping. public string Message { get; set; } public string LastPostedBy { get; set; } public int Views { get; set; } public int Replies { get; set; } public bool Answered { get; set; } public DateTime LastPostedDateTime { get; set; } // Explicit mapping (property and table attribute names are different. [DynamoDBProperty("Tags")] public List<string> KeywordTags { get; set; } // Property to store version number for optimistic locking. [DynamoDBVersion] public int? Version { get; set; } } [DynamoDBTable("Forum")] public class Forum { [DynamoDBHashKey] public string Name { get; set; } // All the following properties are explicitly mapped, // only to show how to provide mapping. [DynamoDBProperty] public int Threads { get; set; } [DynamoDBProperty] API Version 2012-08-10 164 Amazon DynamoDB 開発者ガイド コードサンプルの実行 public int Views { get; set; } [DynamoDBProperty] public string LastPostBy { get; set; } [DynamoDBProperty] public DateTime LastPostDateTime { get; set; } [DynamoDBProperty] public int Messages { get; set; } } [DynamoDBTable("ProductCatalog")] public class Book { [DynamoDBHashKey] //Partition key public int Id { get; set; } public string Title { get; set; } public string ISBN { get; set; } public int Price { get; set; } public string PageCount { get; set; } public string ProductCategory { get; set; } public bool InPublication { get; set; } } } この開発者ガイドのコードサンプルの実行 AWS SDK は、Java、JavaScript in the browser、.NET、Node.js、PHP、Python、Rubyで、DynamoDB を広範にサポートしています。これ らの言語をすぐに開始するには、Amazon DynamoDB 入門ガイド を参照してください。 AWS SDK は、さまざまな言語で利用できます。詳細なリストについては、「Tools for Amazon Web Services」を参照してください。 この開発者ガイドのコードサンプルは、次のプログラミング言語を使用して DynamoDB オペレー ションについて詳細に説明しています。 • Java (p. 171) • .NET (p. 173) • PHP (p. 175) この演習を開始する前に、AWS にサインアップし、アクセスキーとシークレットキーを取得して、 コンピュータで AWS コマンドラインインターフェイスをセットアップする必要があります。この作 業を行っていない場合は、「DynamoDB (ウェブサービス) のセットアップ (p. 48)」を参照してくださ い。 Note DynamoDB のダウンロード可能バージョンを使用する場合は、AWS CLI を使用してテーブル とサンプルデータを作成する必要があります。また、各 AWS CLI コマンドで --endpointurl パラメーターも指定する必要があります。詳細については、「ローカルエンドポイント の設定 (p. 46)」を参照してください。 API Version 2012-08-10 165 Amazon DynamoDB 開発者ガイド サンプルデータのロード テーブルの作成とサンプルデータのロード このセクションでは、AWS マネジメントコンソール を使用して DynamoDB にテーブルを作成しま す。次に、AWS Command Line Interface (AWS CLI) を使用してこれらのテーブルにデータをロード します。 これらのテーブルとそのデータは、この開発者ガイド全体で例として使用されます。 Note アプリケーション開発者の方は、「Amazon DynamoDB 入門ガイド」も参照することをお勧 めします。 「Amazon DynamoDB 入門ガイド」では、ダウンロード可能なバージョンの DynamoDB を 使用します。これにより、スループット、ストレージ、またはデータ転送に料金を支払うこ となく、無料で DynamoDB 低レベル API について学習できます。 トピック • ステップ 1: サンプルテーブルの作成 (p. 166) • ステップ 2: データをテーブルにロードする (p. 168) • ステップ 3: データにクエリを実行する (p. 169) • ステップ 4: (オプション) クリーンアップする (p. 170) • 概要 (p. 171) ステップ 1: サンプルテーブルの作成 このセクションでは、AWS マネジメントコンソール を使用して、DynamoDB で 2 つのシンプルな ユースケース用のテーブルを作成します。 ユースケース 1: 製品カタログ DynamoDB に製品情報を格納するとします。各製品には固有の属性があるため、これらの各製品につ いて異なる情報を保存する必要があります。 ProductCatalog テーブルを作成できます。このテーブルでは、各項目が 1 つの数値属性 Id によって 一意に特定されます。 テーブル名 プライマリキー ProductCatalog パーティションキー: Id (数値) ユースケース 2: フォーラムアプリケーション 掲示板やフォーラム用のアプリケーションを構築するとします。Amazon Web Services フォーラ ムは、このようなアプリケーションの 1 つの例です。お客様は開発者コミュニティとやり取りし、質 問をしたり、他のお客様の投稿に返信したりできます。各 AWS サービスには専用フォーラムがあり ます。だれでも、フォーラムでメッセージを投稿して新しいディスカッションスレッドを開始できま す。各スレッドは、任意の数の返信を受け取ることができます。 3 つのテーブル (Forum、Thread、Reply) を作成して、このアプリケーションをモデル化できます。 テーブル名 プライマリキー フォーラム パーティションキー: Name (文字列) スレッド パーティションキー: ForumName (文字列) API Version 2012-08-10 166 Amazon DynamoDB 開発者ガイド サンプルデータのロード テーブル名 プライマリキー ソートキー: Subject (文字列) Reply パーティションキー: Id (文字列) ソートキー: ReplyDateTime (文字列) [Reply] テーブルには、PostedBy-Message-Index という名前のグローバルセカンダリインデックスが あります。このインデックスでは、Reply テーブルの 2 つの非キー属性でのクエリを容易にします。 インデックス名 プライマリキー PostedBy-Message-Index パーティションキー: PostedBy (文字列) ソートキー: Message (文字列) ProductCatalog テーブルを作成する 1. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 2. [Create Table] を選択します。 3. [Create DynamoDB table] 画面で、次の操作を行います。 4. a. [Table name] フィールドに「ProductCatalog」と入力します。 b. [Primary key] の [Partition key] フィールドに「Id」と入力します。データ型を [Number] に設 定します。 すべての設定が正しいことを確認したら、[Create] を選択します。 Forum テーブルを作成する 1. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 2. [Create Table] を選択します。 3. [Create DynamoDB table] 画面で、次の操作を行います。 4. a. [Table name] フィールドに「Forum」と入力します。 b. [Primary key] の [Partition key] フィールドに「Name」と入力します。データ型を [String] に 設定します。 すべての設定が正しいことを確認したら、[Create] を選択します。 Thread テーブルを作成する 1. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 2. [Create Table] を選択します。 3. [Create DynamoDB table] 画面で、次の操作を行います。 a. [Table name] フィールドに「Thread」と入力します b. [Primary key] ページで、以下の操作を行います。 • [Partition key] フィールドに「ForumName」と入力します。データ型を [String] に設定しま す。 • [Add sort key] を選択します。 • [Sort key] フィールドに「Subject」と入力します。データ型を [String] に設定します。 API Version 2012-08-10 167 Amazon DynamoDB 開発者ガイド サンプルデータのロード 4. すべての設定が正しいことを確認したら、[Create] を選択します。 Reply テーブルを作成する 1. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 2. 3. [Create Table] を選択します。 [Create DynamoDB table] 画面で、次の操作を行います。 a. b. [Table name] フィールドに「Reply」と入力します [Primary key] ページで、以下の操作を行います。 • [Partition key] フィールドに「Id」と入力します。データ型を [String] に設定します。 • [Add sort key] を選択します。 • [Sort key] フィールドに「ReplyDateTime」と入力します。データ型を [String] に設定し ます。 c. [Table settings] セクションで、[Use default settings] を選択解除します。 d. [Secondary indexes] セクションで、[Add index] を選択します。 e. [Add index] ウィンドウで、以下の操作を行います。 • [Primary key] ページで、以下の操作を行います。 • [Partition key] フィールドに「PostedBy」と入力します。データ型を [String] に設定し ます。 • [Add sort key] を選択します。 • [Sort key] フィールドに「Message」と入力します。データ型を [String] に設定します。 • [Index name] フィールドに「PostedBy-Message-Index」と入力します • [Projected attributes] を [All] に設定します。 • [Add index] を選択します。 4. すべての設定が正しいことを確認したら、[Create] を選択します。 ステップ 2: データをテーブルにロードする このステップでは、作成したテーブルにサンプルデータをロードします。DynamoDB コンソール にデータを手動で入力できます。ただし、時間を節約するため、代わりに AWS Command Line Interface を使用します。 Note まだ AWS CLI をセットアップしていない場合は、手順について「」を参照してください。 各テーブル用のサンプルデータと JSON ファイルが含まれる .zip アーカイブをダウンロードしま す。ファイルごとに、AWS CLI を使用してデータを DynamoDB にロードします。データのロードが 成功するたびに、以下の出力が作成されます。 { "UnprocessedItems": {} } サンプルデータファイルアーカイブのダウンロード 1. 次のリンクを使用してサンプルデータアーカイブ (sampledata.zip) をダウンロードします。 • sampledata.zip API Version 2012-08-10 168 Amazon DynamoDB 開発者ガイド サンプルデータのロード 2. アーカイブから .json データファイルを抽出します。 3. 現在のディレクトリに .json データファイルをコピーします。 サンプルデータを DynamoDB テーブルにロードする 1. データとともに ProductCatalog テーブルをロードするには、次のコマンドを入力します。 aws dynamodb batch-write-item --request-items file://ProductCatalog.json 2. データとともに Forum テーブルをロードするには、次のコマンドを入力します。 aws dynamodb batch-write-item --request-items file://Forum.json 3. データとともに Thread テーブルをロードするには、次のコマンドを入力します。 aws dynamodb batch-write-item --request-items file://Thread.json 4. データとともに Reply テーブルをロードするには、次のコマンドを入力します。 aws dynamodb batch-write-item --request-items file://Reply.json データロードの確認 AWS マネジメントコンソール を使用して、テーブルにロードしたデータを確認できます。 AWS マネジメントコンソールを使用してデータを確認するには 1. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 2. ナビゲーションペインで、[ Tables] を選択します。 3. テーブルのリストで、[ProductCatalog] を選択します。 4. [Items] タブを選択して、テーブルにロードしたデータを表示できます。 5. テーブルの項目を表示するには、その Id を選択します (必要に応じて、編集することもできま す)。 6. テーブルの一覧に返すには、[Cancel] を選択します。 作成した他のテーブルごとに、この手順を繰り返します。 • フォーラム • スレッド • Reply ステップ 3: データにクエリを実行する このステップでは、DynamoDB コンソールで作成したテーブルに対して、いくつかの単純なクエリを 試行します。 1. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 2. ナビゲーションペインで、[ Tables] を選択します。 3. テーブルのリストで、[Reply] を選択します。 4. [Items] タブを選択して、テーブルにロードしたデータを表示できます。 5. [Create item] ボタンのすぐ下にある、データフィルタリンクを選択します。 API Version 2012-08-10 169 Amazon DynamoDB 開発者ガイド サンプルデータのロード これを行うと、コンソールにデータフィルタリングペインが表示されます。 6. 7. データフィルタリングペインで以下の作業を行います。 a. オペレーションを [Scan] から [Query] に変更します。 b. [Partition key] に値を入力します。Amazon DynamoDB#DynamoDB Thread 1 c. [Start] を選択します。クエリ条件に一致する項目のみが Reply テーブルから返されます。 Reply テーブルには、PostedBy および Message 属性にグローバルセカンダリインデックスがあ ります。データフィルタリングペインを使用してインデックスにクエリを実行できます。次の作 業を行います。 a. 次からクエリソースを変更します。 [Table] Reply: Id, ReplyDateTime 次のように変更する必要があります。 [Index] PostedBy-Message-Index: PostedBy, Message b. [Partition key] に値を入力します。User A c. [Start] を選択します。クエリ条件に一致する項目のみが、PostedBy-Message-Index から返 されます。 DynamoDB コンソールを使用して、他のテーブルを確認します。 • ProductCatalog • フォーラム • スレッド ステップ 4: (オプション) クリーンアップする この『Amazon DynamoDB 開発者ガイド』では、DynamoDB 低レベル API および各種 AWS SDK を 使用してテーブルと項目のオペレーションを示すため、これらのサンプルテーブルを繰り返し参照し ます。この開発者ガイドの残りの部分を読む予定の場合、これらのテーブルが役に立ちます。 API Version 2012-08-10 170 Amazon DynamoDB 開発者ガイド Java コードサンプル ただし、これらのテーブルを維持する予定がない場合は、必要ないリソースに対する課金を防ぐため に、テーブルを削除してください。 サンプルテーブルを削除するには 1. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 2. ナビゲーションペインで、[ Tables] を選択します。 3. テーブルのリストで、[ProductCatalog] を選択します。 4. [Delete Table] を選択します。選択を確認する画面が表示されます。 作成した他のテーブルごとに、この手順を繰り返します。 • フォーラム • スレッド • Reply 概要 この演習では、DynamoDB コンソールを使用して DynamoDB で複数のテーブルを作成しました。次 に、AWS CLI を使用してテーブルにデータをロードし、DynamoDB コンソールを使用してデータで いくつかの基本的なオペレーションを実行しました。 DynamoDB コンソールおよび AWS CLI は、すぐに使用を開始するのに便利です。ただ し、DynamoDB の動作の詳細と、DynamoDB を使用したアプリケーションプログラムの記述の詳細 を参照することをお勧めします。この開発者ガイドの残りの部分では、これらのトピックに対応しま す。 Java コードサンプル トピック • Java: AWS 認証情報の設定 (p. 172) • Java: AWS リージョンとエンドポイントの設定 (p. 172) この開発者ガイドには、Java コードスニペットとすぐに使用できるプログラムが含まれています。こ れらのコードサンプルは、次のセクションで確認することができます。 • DynamoDB での項目の操作 (p. 204) • DynamoDB でのテーブルの操作 (p. 178) • クエリおよびスキャンの使用 (p. 287) • セカンダリインデックスを使用したデータアクセス性の向上 (p. 333) • Java: DynamoDBMapper (p. 78) • DynamoDB ストリーム を使用したテーブルアクティビティのキャプチャ (p. 426) Note Amazon DynamoDB 入門ガイド には、追加の Java サンプルプログラムが含まれます。 Eclipse と AWS Toolkit for Eclipse を使用して、すぐに開始できます。フル機能の IDE に加えて、自 動更新で AWS SDK for Java および AWS アプリケーションの構築用に事前設定されたテンプレート も取得できます。 API Version 2012-08-10 171 Amazon DynamoDB 開発者ガイド Java コードサンプル Java コードサンプルを実行するには (Eclipse を使用) 1. Eclipse IDE をダウンロードし、インストールします。 2. AWS Toolkit for Eclipse をダウンロードし、インストールします。 3. Eclipse を開始し、[Eclipse] メニューから、[File]、[New]、[Other] の順に選択します。 4. [Select a wizard] で、[AWS]、[AWS Java Project]、[Next] の順に選択します。 5. [Create an AWS Java] で、以下の操作を行います。 a. [Project name] で、プロジェクトの名前を入力します。 b. [Select Account] で、リストから認証情報プロファイルを選択します。 AWS Toolkit for Eclipse を初めて使用する場合、[Configure AWS Accounts] を選択し て、AWS 認証情報を設定します。 6. [Finish] を選択してプロジェクトを作成します。 7. [Eclipse] メニューから [File]、[New]、[Class] の順に選択します。 8. [Java Class] で、[Name] にクラスの名前を入力し (実行するコードサンプルと同じ名前を使用)、 [Finish] を選択してクラスを作成します。 9. お読みになっているドキュメントページから Eclipse エディターにコードサンプルをコピーしま す。 10. コードを実行するには、Eclipse メニューの [Run] を選択します。 SDK for Java には、DynamoDB を操作するためにスレッドセーフなクライアントが用意されていま す。最善の方法としては、ご利用のアプリケーションでクライアントを 1 つ作成し、そのクライアン トをスレッド間で再利用することです。 詳細については、AWS SDK for Java を参照してください。 Note この開発者ガイドのコードサンプルは、最新バージョンの AWS SDK for Java で使用するた めのものです。 AWS Toolkit for Eclipse を使用している場合、SDK for Java の自動更新を設定することができ ます。Eclipse でこれを行なうには、[Preferences] に移動し、[AWS Toolkit] --> [AWS SDK for Java] --> [新しい SDK を自動的にダウンロード] の順に選択します。 Java: AWS 認証情報の設定 SDK for Java では、実行時にアプリケーションに AWS 認証情報を指定する必要があります。この開 発者ガイドのコードサンプルでは、『AWS SDK for Java Developer Guide』の「Set Up Your AWS Credentials」で説明されているように、AWS 認証情報ファイルを使用することを前提としています。 ~/.aws/credentials という名前の AWS 認証情報ファイルの例を次に示します。ここで、チルダ 文字 (~) はホームディレクトリを表します。 [default] aws_access_key_id = AWS access key ID goes here aws_secret_access_key = Secret key goes here Java: AWS リージョンとエンドポイントの設定 デフォルトでは、米国西部 (オレゴン) リージョンで、DynamoDB にアクセスします。リージョンを変 更するには、AmazonDynamoDBClient プロパティを変更します。 API Version 2012-08-10 172 Amazon DynamoDB 開発者ガイド .NET コードサンプル 次のコードスニペットは、新しい AmazonDynamoDBClient をインスタンス化します。その後、クラ イアントは、別のリージョンでコードが DynamoDB に対して実行するように変更されます。 import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import com.amazonaws.regions.Regions; ... // This client will default to US West (Oregon) AmazonDynamoDBClient client = new AmazonDynamoDBClient(); // Modify the client so that it accesses a different region. client.withRegion(Regions.US_EAST_1); withRegion メソッドを使用して、利用可能な任意のリージョンで、Amazon DynamoDB を対象とし てコードを実行します。詳細なリストについては、『アマゾン ウェブ サービス全般のリファレンス』 の「AWS Regions and Endpoints」を参照してください。 ローカルコンピュータで DynamoDB を使用しコードサンプルを実行する場合、次に示すようにエン ドポイントを設定する必要があります。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); // Set the endpoint URL client.withEndpoint("http://localhost:8000"); .NET コードサンプル トピック • .NET: AWS 認証情報の設定 (p. 174) • .NET: AWS リージョンとエンドポイントの設定 (p. 175) この開発者ガイドには、.NET コードスニペットとすぐに使用できるプログラムが含まれています。こ れらのコードサンプルは、次のセクションで確認することができます。 • DynamoDB での項目の操作 (p. 204) • DynamoDB でのテーブルの操作 (p. 178) • クエリおよびスキャンの使用 (p. 287) • セカンダリインデックスを使用したデータアクセス性の向上 (p. 333) • .NET ドキュメントモデル (p. 116) • .NET: オブジェクト永続性モデル (p. 138) • DynamoDB ストリーム を使用したテーブルアクティビティのキャプチャ (p. 426) Note Amazon DynamoDB 入門ガイド には、追加の .NET サンプルプログラムが含まれます。 AWS SDK for .NET と Toolkit for Visual Studio を使用して、すぐに開始できます。 .NET コードサンプルを実行するには (Visual Studio を使用) 1. Microsoft Visual Studio をダウンロードし、インストールします。 2. Toolkit for Visual Studio をダウンロードし、インストールします。 API Version 2012-08-10 173 Amazon DynamoDB 開発者ガイド .NET コードサンプル 3. Visual Studio を起動し、[File]、[New]、[Project] の順に選択します。 4. [New Project] で、[AWS Empty Project]、[OK] の順に選択します。 5. [AWS アクセス認証情報] で、[既存のプロファイルを使用] を選択し、リストからご自分の認証情 報の内容を選択して、[OK] を選択します。 初めて Toolkit for Visual Studio を使用する場合は、[新しいプロファイルを使用] を選択し、AWS の認証情報を設定します。 6. Visual Studio プロジェクトで、プログラムソースコード (Program.cs) のタブを選択します。エ ディターにある他のコードを置き換えて、お読みになっているドキュメントページから、Visual Studio にコードサンプルをコピーします。 7. The type or namespace name...could not be found 形式のエラーメッセージが表示 された場合、次のように DynamoDB の AWS SDK アセンブリをインストールする必要がありま す。 8. a. ソリューションエクスプローラーで、プロジェクトのコンテキスト (右クリック) メニューを 開いて、[Manage NuGet Packages] を選択します。 b. NuGet パッケージマネージャーで、[Browse] を選択します。 c. 検索ボックスに、「AWSSDK.DynamoDBv2」と入力し、完了するまでお待ちください。 d. [AWSSDK.DynamoDBv2]、[Install] の順に選択します。 e. インストールが完了したら、[Program.cs] タブを選択し、プログラムに戻ります。 コードを実行するには、Visual Studio ツールバーの [Start] ボタンを選択します。 AWS SDK for .NET には、DynamoDB を操作するためにスレッドセーフなクライアントが用意されて います。最善の方法としては、ご利用のアプリケーションでクライアントを 1 つ作成し、そのクライ アントをスレッド間で再利用することです。 詳細については、「AWS SDK for .NET」を参照してください。 Note この開発者ガイドのコードサンプルは、最新バージョンの AWS SDK for .NET で使用するた めのものです。 .NET: AWS 認証情報の設定 AWS SDK for .NET では、アプリケーションの実行時に AWS 認証情報を指定する必要があります。 この開発者ガイドのコードサンプルは、『AWS SDK for .NET 開発者ガイド』の「SDK ストアの使 用」の説明に従って、AWS の認証情報ファイルを管理している SDK ストアを使用することを前提と しています。 Toolkit for Visual Studio では、任意数のアカウントの複数セットの認証情報がサポートされていま す。各セットはプロファイルと呼ばれています。Visual Studio では、プロジェクトの App.config ファイルにエントリを追加するため、アプリケーションは実行時に AWS 認証情報を見つけることが できます。 次の例は、Toolkit for Visual Studio を使用した新しいプロジェクトの作成時に生成されたデフォルト の App.config ファイルを示しています。 <?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="AWSProfileName" value="default"/> <add key="AWSRegion" value="us-west-2" /> </appSettings> API Version 2012-08-10 174 Amazon DynamoDB 開発者ガイド PHP コードサンプル </configuration> 実行時に、このプログラムは AWSProfileName エントリで指定されているように、AWS 認証情報 の default セットを使用します。AWS 認証情報それ自体は、暗号化されたフォームで SDK ストア に保持されます。Toolkit for Visual Studio は、すべて Visual Studio 内からの認証情報を管理するため のグラフィカルユーザーインターフェイスを使用します。詳細については、『AWS Toolkit for Visual Studio ユーザーガイド』の「認証情報の指定」を参照してください。 Note デフォルトでは、米国西部 (オレゴン) リージョンで、DynamoDB にアクセスしま す。App.config ファイルで AWSRegion エントリを変更して、リージョンを変更できま す。Amazon DynamoDB が利用可能なすべての AWS リージョンで、AWSRegion を設定でき ます。詳細なリストについては、『アマゾン ウェブ サービス全般のリファレンス』の「AWS Regions and Endpoints」を参照してください。 .NET: AWS リージョンとエンドポイントの設定 デフォルトでは、米国西部 (オレゴン) リージョンで、DynamoDB にアクセスしま す。App.config ファイルで AWSRegion エントリを変更して、リージョンを変更できます。また は、AmazonDynamoDBClient プロパティを変更することによってもリージョンを変更できます。 次のコードスニペットは、新しい AmazonDynamoDBClient をインスタンス化します。クライアント は、別のリージョンでコードが DynamoDB に対して実行するように変更されます。 AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig(); // This client will access the US East 1 region. clientConfig.RegionEndpoint = RegionEndpoint.USEast1; AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig); リージョンの詳細なリストについては、アマゾン ウェブ サービス全般のリファレンスのAWS のリー ジョンとエンドポイントを参照してください。 ローカルコンピューターで DynamoDB を使用しコードサンプルを実行する場合、エンドポイントを 設定する必要があります。 AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig(); // Set the endpoint URL clientConfig.ServiceURL = "http://localhost:8000"; AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig); PHP コードサンプル トピック • PHP: AWS 認証情報の設定 (p. 176) • PHP: AWS リージョンとエンドポイントを設定 (p. 176) この開発者ガイドには、PHP コードスニペットとすぐに使用できるプログラムが含まれています。こ れらのコードサンプルは、次のセクションで確認することができます。 • DynamoDB での項目の操作 (p. 204) • DynamoDB でのテーブルの操作 (p. 178) • クエリおよびスキャンの使用 (p. 287) API Version 2012-08-10 175 Amazon DynamoDB 開発者ガイド PHP コードサンプル • セカンダリインデックスを使用したデータアクセス性の向上 (p. 333) • DynamoDB ストリーム を使用したテーブルアクティビティのキャプチャ (p. 426) Note Amazon DynamoDB 入門ガイド には、追加の PHP サンプルプログラムが含まれます。 PHP の SDK を使用する方法は、環境によって、また、どのようにアプリケーションを実行するかに よって異なります。このドキュメント内のコードサンプルは、コマンドラインから実行できますが、 異なる環境 (ウェブサーバーなど) で実行する場合は変更できます。 PHP コードサンプルを実行 (コマンドラインから) 1. 「最小要件」に説明されているように、環境が PHP の SDK の最小要件を満たしていることを確 認します。 2. AWS SDK for PHP をダウンロードし、インストールします。 使用するインストール方法によっては、PHP 拡張モジュール間の依存性を解決するために、コー ドを変更しなければならない場合があります。詳細については、AWS SDK for PHP のドキュメ ントの「使用開始」の「使用開始」セクションを参照してください。 3. (お読みになっているドキュメントページから) コードサンプルをコンピュータのファイルにコ ピーします。 4. コマンドラインからコードを実行します。以下に例を示します。php myProgram.php Note この開発者ガイドのコードサンプルは、最新バージョンの AWS SDK for PHP で使用するため のものです。 PHP: AWS 認証情報の設定 PHP の SDK では、アプリケーションの実行時に AWS 認証情報を指定する必要があります。この開 発者ガイドのコードサンプルは、AWS SDK for PHP ドキュメントの「Credentials」で説明されてい るように、AWS 認証情報ファイルを使用することを前提としています。 ~/.aws/credentials という名前の AWS 認証情報ファイルの例を次に示します。ここで、チルダ 文字 (~) はホームディレクトリを表します。 [default] aws_access_key_id = AWS access key ID goes here aws_secret_access_key = Secret key goes here PHP: AWS リージョンとエンドポイントを設定 DynamoDB クライアントを作成するときに、AWS のリージョンを指定する必要があります。これを 行うには、使用するリージョンとAws\Sdk オブジェクトを指定します。 次のコードスニペットは 米国西部 (オレゴン) リージョンを使用して、新しい Aws\Sdk オブジェク トをインスタンス化します。次に、このリージョンを使用する DynamoDB クライアントを作成しま す。 $sdk = new Aws\Sdk([ 'region' => 'us-west-2', // US West (Oregon) Region API Version 2012-08-10 176 Amazon DynamoDB 開発者ガイド PHP コードサンプル 'version' => 'latest' // Use the latest version of the AWS SDK for PHP ]); // Create a new DynamoDB client $dynamodb = $sdk->createDynamoDb(); ローカルコンピュータで DynamoDB を使用しコードサンプルを実行する場合、次に示すようにエン ドポイントを設定する必要があります。 $sdk = new Aws\Sdk([ 'endpoint' => 'http://localhost:8000', // Use DynamoDB running locally 'region' => 'us-west-2', // US West (Oregon) Region 'version' => 'latest' // Use the latest version of the AWS SDK for PHP ]); // Create a new DynamoDB client $dynamodb = $sdk->createDynamoDb(); API Version 2012-08-10 177 Amazon DynamoDB 開発者ガイド テーブルの操作 DynamoDB の操作 ここでは、次のトピックについて詳しく説明します。 トピック • DynamoDB でのテーブルの操作 (p. 178) • DynamoDB での項目の操作 (p. 204) • クエリおよびスキャンの使用 (p. 287) • セカンダリインデックスを使用したデータアクセス性の向上 (p. 333) • DynamoDB ストリーム を使用したテーブルアクティビティのキャプチャ (p. 426) DynamoDB でのテーブルの操作 トピック • プライマリキーの指定 (p. 179) • テーブルの読み書き要件の指定 (p. 179) • キャパシティーユニットの計算 (p. 181) • テーブルのリストと情報を取得する (p. 183) • DynamoDB のタグ付け (p. 184) • テーブルの操作 : Java (p. 186) • テーブルの操作 : .NET (p. 191) • テーブルの操作 : PHP (p. 198) Amazon DynamoDB でテーブルを作成するときには、テーブル名、プライマリキー、および必須 の読み書きスループット値を指定する必要があります。テーブル名に指定できる文字は、a-z、AZ、0-9、'_' (アンダースコア)、'-' (ハイフン)、'.' (ドット)です。名前は 3~255 文字で指定しま す。リレーショナルデータベースでは、テーブルは事前定義されたスキーマを保持しています。こ のスキーマには、テーブル名、プライマリキー、列名、データ型などのプロパティが記述されてい ます。テーブルに保存されているすべてのレコードは、同じ一連の列で構成されている必要がありま す。DynamoDB は NoSQL データベースです。必要なプライマリキーを除き、DynamoDB テーブルに はスキーマがありません。DynamoDB テーブル内の個々の項目には多数の属性があります。ただし、 項目サイズに対する 400 KB の制限があります。 ベストプラクティスについては、テーブルの操作のガイドライン (p. 566) を参照してください。 オプションでタグを使用して、既存の DynamoDB リソースにラベルを付けることができます。詳細 については、「DynamoDB のタグ付け (p. 184)」を参照してください。 API Version 2012-08-10 178 Amazon DynamoDB 開発者ガイド プライマリキーの指定 プライマリキーの指定 テーブルを作成する場合には、テーブル名に加えて、テーブルのプライマリキーを指定する必要があ ります。プライマリキーは各項目を一意に識別するため、テーブル内の 2 つの項目が同じプライマリ キーを持つことはありません。 DynamoDB は 2 種類の異なるプライマリキーをサポートします。 • パーティションキー — パーティションキーという 1 つの属性で構成されたシンプルなプライマリ キー。DynamoDB は内部ハッシュ関数への入力として、パーティションキーの値を使用します。 ハッシュ関数からの出力により、項目が保存されるパーティションが決まります。テーブルの 2 つ の項目が、同じパーティションキー値を持つことはできません。 • パーティションキーとソートキー — 2 つの属性で構成された複合プライマリキー。最初の属性 はパーティションキーであり、2 番目の属性はソートキーです。DynamoDB は内部ハッシュ関数 への入力として、パーティションキーの値を使用します。ハッシュ関数からの出力により、項目が 保存されるパーティションが決まります。同じパーティションキーを持つすべての項目は、ソート キー値でソートされてまとめて保存されます。2 つの項目でパーティションキー値を同じにするこ とは可能ですが、これらの 2 つの項目のソートキー値は異なっている必要があります。 テーブルの読み書き要件の指定 DynamoDB は、予測可能で低レイテンシーの応答時間を実現するあらゆる規模のワークロードをサ ポートするように構築されています。 高可用性と低レイテンシーの応答を実現するために、DynamoDB では、テーブル作成時に必須の読み 書きスループット値を指定する必要があります。DynamoDB はこの情報を使用して十分なハードウェ アリソースを予約し、また、複数のサーバーにまたがるデータを適切に分割してスループット要件を 満たしています。アプリケーションデータとアクセスの要件が変化した場合は、DynamoDB コンソー ルまたは API を使用して、プロビジョニングされたスループットを簡単に増減できます。 DynamoDB はリソースの割り当てと予約を行い、持続性のある低レイテンシーを実現することで、ス ループット要件に対応します。お客様は、これらのリソースの時間単位の予約に対して代金を支払い ます。支払いは貴社の成長に応じて行うことができ、スループット要件の引き上げや引き下げも簡単 です。たとえば、既存のデータストアからの大量のデータを新しいテーブルに入力しなければならな い場合があります。この場合、大容量の書き込みスループットを設定したテーブルを作成できます。 また、初回のデータアップロード後には、その書き込みスループットを下げ、アプリケーションの要 件に合うように読み込みスループットを高めます。 テーブル作成時には、以下のキャパシティーユニットによってスループット要件を指定しま す。UpdateTable リクエスト内でこれらのユニットを指定して、既存テーブルのプロビジョニング されたスループットを増減することもできます。 • 読み込みキャパシティーユニット – 最大 4 KB のサイズの項目に対する、強い整合性のある読み込 みの 1 秒あたりの数です。たとえば、読み込みキャパシティーユニット 10 をリクエストすると、 該当するテーブルに対して 4 KB の強い整合性のある読み込みのスループットを、1 秒あたり 10 回リクエストします。結果整合性のある読み込みの場合、1 つの読み込みキャパシティーユニット は、最大 4 KB の項目を 1 秒あたり 2 回読み込むことになります。読み込み整合性の詳細について は、「読み込み整合性 (p. 16)」を参照してください。 • 書き込みキャパシティーユニット – 1 秒あたりの 1 KB の書き込み数たとえば、書き込みキャパシ ティーユニット 10 をリクエストすると、該当するテーブルに対して 1 KB のサイズを 1 秒あたり 10 回書き込むスループットをリクエストします。 DynamoDB はこれらのキャパシティーユニットを使用して、リクエストされたスループットを提供す るための十分なリソースをプロビジョニングします。 テーブルのキャパシティーユニットを決定するときは、以下の点を考慮する必要があります。 API Version 2012-08-10 179 Amazon DynamoDB 開発者ガイド テーブルの読み書き要件 • 項目サイズ – DynamoDB は、指定するキャパシティーユニットの読み書き数に従って、テーブル にリソースを割り当てます。これらのキャパシティーユニットは、データ項目のサイズ(1 回の読 み込みで 4 KB または 1 回の書き込みで 1 KB)に基づいています。たとえば、テーブル内の項目 が 4 KB 以下の場合、各項目の読み込みオペレーションでは、読み込みキャパシティーユニット 1 が消費されます。項目が 4 KB を超える場合は、各読み込みオペレーションでは、追加のキャパシ ティーユニットが消費されます。この場合、1 秒あたりに実行できるデータベース読み込みオペ レーションの数は、プロビジョニング済みの読み込みキャパシティーユニットの数よりも少なくな ります。たとえば、テーブルに対して読み込みキャパシティーユニット 10 のスループットをリク エストする場合に項目のサイズが 8 KB であれば、そのテーブルに対して強い整合性のある読み込 みが 1 秒あたり最大 5 回確保されます。 • 読み書きリクエストの期待値 – アプリケーションからテーブルに対して 1 秒あたりに実行される読 み書きオペレーションの期待数も決定する必要があります。この期待値は、推定の項目サイズとと もに、読み書きキャパシティーユニットの値を決定する際に役立ちます。 • 整合性 – 読み込みキャパシティーユニットは、強い整合性のある読み込みオペレーションに基づい ています。ただし、このオペレーションには、より多くの手間がかかり、データベースリソースの 消費量は結果整合性のある読み込みの 2 倍になります。たとえば、プロビジョニングされたスルー プットの 10 の読み込みキャパシティーユニットを持つテーブルは、4 KB の項目に対する 1 秒あた り 10 の強い整合性のある読み込み、または、同じ項目に対する 1 秒あたり 20 の結果整合性のある 読み込みのいずれかを提供します。アプリケーションでどちらの整合性読み込みが必要かは、テー ブルにプロビジョニングする必要のある読み込みキャパシティーユニットの数の決定要因となりま す。DynamoDB では、読み込みオペレーションのデフォルトは、結果整合性のある読み込みとな ります。これらのオペレーションの中には、強い整合性のある読み込みを指定できるものもありま す。 • Secondary indexes – インデックスに対するクエリは、プロビジョニングされた読み込みスループッ トを消費します。DynamoDB は 2 種類の セカンダリインデックスes (グローバルセカンダリイン デックスes と local secondary indexes) をサポートします。インデックスおよびプロビジョニング されたスループットに関する詳細については、「セカンダリインデックスを使用したデータアクセ ス性の向上 (p. 333)」を参照してください。 これらの要因は、テーブル作成時に指定する、アプリケーションのスループット要件を決定する際 に役立ちます。CloudWatch のメトリクスを使用して、パフォーマンスをモニタリングできます。ま た、アラームを設定し、消費されたキャパシティーユニットの特定のしきい値に到達した場合に通 知することもできます。DynamoDB コンソールでは、デフォルトのメトリクスをいくつか利用でき ます。このメトリクスを確認して、テーブルパフォーマンスをモニタリングし、必要に応じてスルー プット要件を調整できます。詳細については、DynamoDB コンソールにアクセスしてください。 DynamoDB では、自動的にテーブルパーティション全体にデータが分散され、複数のサーバーに格 納されます。最適なスループットを実現するために、これらのパーティション全体にできるだけ均一 に読み込みリクエストを分散する必要があります。たとえば、1 秒あたり 100 万の読み込みキャパシ ティーユニットでテーブルをプロビジョニングする必要があるとします。テーブル内の単一の項目に 100 万のリクエストを発行すると、すべての読み込みアクティビティが単一のパーティションに集中 します。しかし、テーブル内の全項目にリクエストを分散すると、DynamoDB はテーブルパーティ ションに並列でアクセスできます。これにより、テーブルのプロビジョニングされたスループットの 目標を実現できます。 読み込みの場合、異なる平均項目サイズ、リクエスト率、および整合性の組み合わせに対応する、プ ロビジョニングされたスループットの値が、以下のテーブルで比較されます。 期待される項目サイズ 整合性 1 秒あたりの期待され る読み込み数 必須のプロビジョニン グされたスループット 4 KB 強い整合性 50 50 8 KB 強い整合性 50 100 4 KB 結果整合性 50 25 API Version 2012-08-10 180 Amazon DynamoDB 開発者ガイド キャパシティーユニットの計算 期待される項目サイズ 整合性 1 秒あたりの期待され る読み込み数 必須のプロビジョニン グされたスループット 8 KB 結果整合性 50 50 読み込みの項目サイズは、次の 4 KB の倍数に切り上げられます。たとえば、3,500 バイトの項目 は、4 KB の項目と同じスループットを消費します。 書き込みの場合、異なる平均項目サイズおよび書き込みリクエスト率に対応する、プロビジョニング されたスループットの値が、以下のテーブルで比較されます。 期待される項目サイズ 1 秒あたりの期待される書き込 み数 必須のプロビジョニングされた スループット 1 KB 50 50 2 KB 50 100 書き込みの項目サイズは、次の 1 KB の倍数に切り上げられます。たとえば、500 バイトの項目は、1 KB の項目と同じスループットを消費します。 DynamoDB は、リクエストされた読み込みと書き込みのキャパシティーユニットにリソースをコミッ トします。その結果として、リクエストされた率内にとどまることが予想されます。プロビジョニン グされたスループットは、リクエストされるデータのサイズにも依存します。読み込みまたは書き込 みのリクエスト率が、リクエストされるデータの累積的なサイズに組み合わされ、現在確保されてい る容量を超える場合、DynamoDB は、プロビジョニングされたスループットレベルが超過したことを 示すエラーを返します。 ProvisionedThroughput パラメータを使用して、プロビジョニングされたスループットを設定し ます。ProvisionedThroughput パラメータの設定については、Amazon DynamoDB API Reference の CreateTable を参照してください。 プロビジョニングされたスループットの使用に関する詳細については、「テーブルの操作のガイドラ イン (p. 566)」を参照してください。 Note ワークロードの急上昇(新製品の発売など)により、スループットがテーブルの現在のプロ ビジョニングされたスループットを超過する可能性が予想される場合は、UpdateTable オペ レーションを使用して、ProvisionedThroughput 値を大きくすることをお勧めします。 テーブル単位またはアカウント単位の、現在の最大のプロビジョニングされたスループット 値については、「DynamoDB での制限 (p. 558)」を参照してください。 UpdateTable リクエストを発行すると、テーブルのステータスが AVAILABLE から UPDATING に変わります。テーブルは UPDATING 中も全面的に利用できます。この期間 中、DynamoDB は必要なリソースを割り当てて、新しいプロビジョニングされたスループッ トレベルをサポートします。この処理が完了すると、テーブルのステータスが UPDATING か ら AVAILABLE に変わります。 キャパシティーユニットの計算 DynamoDB では、キャパシティーユニットは、以下のように定義されます。 • 最大サイズ 4 KB の項目について、1 つの読み込みキャパシティーユニット = 1 秒あたり 1 回の強力 な整合性のある読み込み、あるいは 1 秒あたり 2 回の結果整合性のある読み込み。 API Version 2012-08-10 181 Amazon DynamoDB 開発者ガイド キャパシティーユニットの計算 • 最大サイズ 1 KB の項目について、1 つの書き込みキャパシティーユニット = 1 秒あたり 1 回の書き 込み 項目サイズは、属性名と属性値の長さの合計です。(キャパシティーユニットの消費を最適化するに は、属性名の長さをできるだけ短くすることをお勧めします。) Null またはブール属性値のサイズは、属性名の長さ + 1 バイトです。 リスト型またはマップ型の属性は、その内容にかかわらず、余分な 3 バイトが必要です。空のリスト またはマップのサイズは、属性名の長さ + 3 バイトです。属性が空でない場合、サイズは、属性名の 長さ + 属性値の長さの合計 + 3 バイトです。 読み取り操作 DynamoDB 読み込みオペレーションが読み込みキャパシティーユニットを消費する仕組みについて次 に説明します。 • GetItem – テーブルから単一の項目を読み取ります。キャパシティーユニットの計算では、項目サ イズは、次の 4 KB 境界に切り上げられます。たとえば、3.5 KB の項目を読み取ると、DynamoDB は項目サイズを 4 KB まで切り上げます。10 KB の項目を読み取ると、DynamoDB は項目サイズを 12 KB まで切り上げます。 • BatchGetItem – 1 つ以上のテーブルから 100 個の項目を読み取ります。DynamoDB はバッチ内の 各項目を個別の GetItem リクエストとして処理するため、DynamoDB は、まず各項目のサイズを 次の &read_size; 境界に切り上げ、次に合計サイズを算出します。この結果は、すべての項目の合 計サイズと必ずしも同じではありません。たとえば、BatchGetItem が 1.5 KB の項目と 6.5 KB の 項目を読み込むと、DynamoDB は、サイズを 8 KB(1.5 KB + 6.5 KB)ではなく、12 KB(4 KB + 8 KB)と算出します。 • Query - 同じパーティションキー値を持つ複数の項目を読み取ります。返されるすべての項目は単 一の読み取りオペレーションとして扱われ、DynamoDB はすべての項目の合計サイズを計算し、次 の 4 KB 境界に切り上げます。たとえば、クエリの結果、合計サイズが 40.8 KB になる 10 項目が返 されるとします。DynamoDB はオペレーションの項目サイズを 44 KB まで切り上げます。クエリ の結果、64 バイトの項目が 1,500 項目返されると、累積サイズは 96 KB になります。 • Scan - テーブルのすべての項目を読み取ります。DynamoDB は、スキャンにより返される項目のサ イズではなく、評価される項目のサイズを考慮します。 存在しない項目に対して読み込みオペレーションを実行しても、DynamoDB ではやはりプロビジョ ンド読み込みスループットが消費されます。強力な整合性のある読み込みオペレーションでは、1 つ の読み込みキャパシティーユニットが消費されますが、結果整合性のある読み込みオペレーションで は、半分の読み込みキャパシティーユニットが消費されます。 項目を返すオペレーションの場合、取り出す属性の一部をリクエストできます。ただし、項目サイズ の計算には影響を及ぼしません。また、Query と Scan は、属性値の代わりに項目数を返します。項 目数の取得には、同じ量の読み込みキャパシティーユニットが使用され、その結果は同じ項目サイズ の計算の影響を受けます。これは、DynamoDB では、項目数を増加させるために各項目を読み込む必 要があるからです。 読み取りオペレーションと読み取り整合性 前出の計算によって、強い整合性のある読み込みリクエストが仮定されます。結果整合性のある読み 込みリクエストでは、このオペレーションによってキャパシティーユニットの半分のみが消費されま す。結果整合性のある読み込みでは、合計項目サイズが 80 KB の場合、オペレーションによって 10 キャパシティーユニットのみが消費されます。 書き込み操作 DynamoDB 書き込みオペレーションが書き込みキャパシティーユニットを消費する仕組みについて次 に説明します。 API Version 2012-08-10 182 Amazon DynamoDB 開発者ガイド テーブルのリストと情報を取得する • PutItem – テーブルに単一の項目を書き込みます。同じプライマリキーを持つ項目がテーブル内に 存在する場合、このオペレーションによって項目が置き換えられます。プロビジョニングされたス ループットの消費量を算出する場合、重要な項目サイズは 2 つのうち大きい方となります。 • UpdateItem - テーブル内の単一の項目を変更します。DynamoDB は更新前後に表示される項目の サイズを考慮します。プロビジョニングされたスループットの消費は、これらの項目サイズの大き い方を反映しています。項目の属性の一部だけを更新した場合でも、UpdateItem は、プロビジョ ニングされたスループットの総量 ("前" の項目サイズと "後" の項目サイズで、より大きい方) を消費 します。 • DeleteItem – テーブルから単一の項目を削除します。プロビジョニングされたスループットの消 費量は、削除された項目のサイズに基づいています。 • BatchWriteItem – 1 つ以上のテーブルに最大 25 個の項目を書き込みます。DynamoDB はバッ チの各項目を個別の PutItem または DeleteItem リクエスト (更新はサポートされない) とし て処理するため、DynamoDB は各項目のサイズを 1 KB 境界にまず切り上げてから、合計サイズ を計算します。この結果は、すべての項目の合計サイズと必ずしも同じではありません。たとえ ば、BatchWriteItem が 500 バイトと 3.5 KB の項目を書き込んだ場合、DynamoDB はサイズ を、4 KB (500 bytes + 3.5 KB) ではなく、5 KB (1 KB + 4 KB) と計算します。 PutItem、UpdateItem、および DeleteItem オペレーションでは、DynamoDB は項目のサイズを 次の 1 KB に切り上げます。たとえば、1.6 KB の項目を入力または削除すると、DynamoDB は項目サ イズを 2 KB まで切り上げます。 PutItem、UpdateItem、DeleteItem では、条件付き書き込みが可能です。これは指定した条件が true と評価された場合のみ書き込みオペレーションが行われるというものです。式が false と評価さ れた場合でも、DynamoDB はテーブルの書き込みキャパシティーユニットを消費します。 • 項目が存在する場合、消費される書き込みキャパシティーユニットの数は、項目のサイズによっ て異なります (たとえば、1 KB の項目の条件付き書き込みが失敗すると、1 つの書き込みキャパシ ティーユニットが消費されます。項目のサイズがその倍である場合、条件付き書き込みが失敗する と、2 つの書き込みキャパシティーユニットが消費されます)。 • 項目が存在しない場合、DynamoDB は 1 つの書き込みキャパシティーユニットを消費します。 テーブルのリストと情報を取得する すべてのテーブルのリストを取得するには、ListTables オペレーションを使用しま す。ListTables の 1 回の 呼び出しで、最大 100 個のテーブル名を取得できます。テーブルの数が 100 個を超える場合は、ListTables によってページ分割された結果が返されるようにリクエストす ることで、すべてのテーブル名を取得できます。 任意のテーブルの構造を調べるには、DescribeTable オペレーションを使用しま す。DescribeTable によって返されるメタデータには、テーブル作成時のタイムスタンプ、キース キーマ、プロビジョンドスループット設定、推定サイズ、既存のすべての セカンダリインデックス が 含まれています。 Note CreateTable のリクエスト直後に DescribeTable リクエストを発行した場 合、DynamoDB によって ResourceNotFoundException が返されることがありま す。DescribeTable で結果整合性のあるクエリが使用されており、テーブルのメタデータが その時点で使用できない可能性があるためです。数秒間待ってから、再び DescribeTable リクエストを試してみてください。 テーブルで使用されるストレージの計算時に、DynamoDB は、100 bytes のオーバーヘッド をインデックス化の目的で各項目に追加します。DescribeTable オペレーションは、この オーバーヘッドを含むテーブルサイズを返します。また、このオーバーヘッドは、ストレー ジ費用に算入されます。ただし、この余分な 100 bytes は、キャパシティーユニットの計算に は使用されません。価格の詳細については、「DynamoDB Pricing」を参照してください。 API Version 2012-08-10 183 Amazon DynamoDB 開発者ガイド DynamoDB のタグ付け DynamoDB のタグ付け DynamoDB リソースにタグでラベルを付けることができます。タグを使用すると、リソースを目的、 所有者、環境、その他の条件などさまざまな方法で分類することができます。タグは次のことに役立 ちます。 • リソースに割り当てたタグに基づいてリソースをすばやく特定する。 • タグ別に分類された AWS 請求を表示する。 Note タグが付けられたテーブルに関連するローカルセカンダリインデックス (LSI) およびグロー バルセカンダリインデックス (GSI) は、自動的に同じタグでラベルが付けられます。現在の ところ、DynamoDB Streams の使用にタグを付けることはできません。 タグ付けは、Amazon EC2、Amazon S3、DynamoDB などの AWS のサービスでサポートされていま す。効率的なタグ付けを行うと、特定のタグを持つサービス間でレポートを作成でき、コストインサ イトを得ることができます。 タグ付けを開始するには、次の操作を実行します。 1. タグ付けの制限 (p. 184) について理解します。 2. タグ付けオペレーション (p. 184) を使用してタグを作成します。 3. コスト配分レポート (p. 185) を使用して、アクティブなタグごとに AWS のコストを追跡しま す。 最後に、最適のタグ付け手法に従うことをお勧めします。詳細については、「AWS Tagging Strategies」を参照してください。 タグ付けの制限 タグはそれぞれ、1 つのキーと 1 つの値で構成されており、どちらもお客様側が定義します。以下の 制限が適用されます。 • 各 DynamoDB テーブルは同じキーを含む 1 つのタグのみを持つことができます。既存のタグ (同じ キー) を追加しようとすると、既存のタグの値は新しい値に更新されます。 • タグのキーと値は大文字と小文字が区別されます。 • キーの最大長: 128 文字(Unicode) • 値の最大長: 256 文字(Unicode) • 使用できる文字は、文字、ホワイトスペース、数字、および特殊文字 +、-、= です。_ : / • リソースあたりのタグの最大数: 50 • AWS 側で割り当てたタグ名と値には自動的に aws: というプレフィックスが付けられますが、これ を割り当てることはできません。AWS 側で割り当てたタグ名は、50 個というタグ数の制限には含 まれません。ユーザー側で割り当てたタグ名は、user: というプレフィックスを付けてコスト配分 レポートに表示されます。 • リソースの作成と同時にタグを付けることはできません。タグ付けは、リソースが作成された後で のみ実行できる別のアクションです。 • 過去にさかのぼってタグを適用することはできません。 タグ付けオペレーション このセクションでは、DynamoDB コンソールまたは CLI を使用してタグを追加、リスト、編集、また は削除する方法について説明します。次に、これらのユーザー定義タグをアクティブ化し、コスト配 API Version 2012-08-10 184 Amazon DynamoDB 開発者ガイド DynamoDB のタグ付け 分の追跡のため、Billing and Cost Management コンソールに表示できます。詳細については、「コス ト配分レポート (p. 185)」を参照してください。 一括編集の場合は、AWS マネジメントコンソールのタグエディターを使用することもできます。詳細 については、「Tag Editor の使用」を参照してください。 代わりに API を使用する場合は、「Amazon DynamoDB API Reference」を参照してください。 トピック • タグ付け (コンソール) (p. 185) • タグ付け (CLI) (p. 185) タグ付け (コンソール) コンソールを使用してタグを追加、リスト、編集、または削除するには: 1. https://console.aws.amazon.com/dynamodb/home にある DynamoDB コンソールを開きます。 2. テーブルを選択し、[Settings] タブを選択します。 ここでタグを追加、リスト、編集、または削除できます。この例で、Movies タグは、映画テーブ ル用に値 moviesProd で作成されました。 タグ付け (CLI) 映画テーブル用に値 blueTeam で Owner タグを追加するには: aws dynamodb tag-resource \ --resource-arn arn:aws:dynamodb:us-east-1:123456789012:table/Movies \ --tags Key=Owner,Value=blueTeam 映画テーブルに関連付けられているすべてのタグをリストするには: aws dynamodb list-tags-of-resource \ --resource-arn arn:aws:dynamodb:us-east-1:123456789012:table/Movies コスト配分レポート AWS ではタグを使用して、コスト配分レポートでリソースのコストが整理されます。AWS は 2 種類 のコスト配分タグを提供しています。 • AWS が生成したタグ。AWS は、お客様に代わってこのタグを定義、作成、適用します。 • ユーザー定義タグ。これらのタグは、お客様が定義、作成、適用します。 コストエクスプローラーまたはコスト配分レポートで使用するには、事前に両方のタイプのタグを 別々にアクティブ化しておく必要があります。 AWS が生成したタグをアクティブ化するには: 1. https://console.aws.amazon.com/billing/home#/ で AWS マネジメントコンソールにサインインし、 [Billing and Cost Management] コンソールを開きます。 2. ナビゲーションペインで、[Cost Allocation Tags] を選択します。 3. [AWS-Generated Cost Allocation Tags] で、[Activate] を選択します。 API Version 2012-08-10 185 Amazon DynamoDB 開発者ガイド テーブルの操作 : Java ユーザー定義タグをアクティブ化するには: 1. https://console.aws.amazon.com/billing/home#/ で AWS マネジメントコンソールにサインインし、 [Billing and Cost Management] コンソールを開きます。 2. ナビゲーションペインで、[Cost Allocation Tags] を選択します。 3. [User-Defined Cost Allocation Tags] で、[Activate] を選択します。 タグを作成し、アクティブ化すると、アクティブなタグによってグループ化された使用量とコストを 含むコスト配分レポートが AWS によって生成されます。コスト配分レポートには、ご利用の AWS サービスのコストすべてが請求期間別に出力されます。タグ付きとタグなしのどちらのリソースもこ のレポートに出力されるので、リソース別の請求額を明確に分類できます。 Note 現在のところ、DynamoDB から転送されるすべてのデータが、コスト配分レポートでタグ別 に分類されるわけではありません。 詳細については、「コスト配分タグの使用」を参照してください。 テーブルの操作 : Java トピック • テーブルの作成 (p. 186) • テーブルの更新 (p. 187) • テーブルの削除 (p. 188) • テーブルの一覧表示 (p. 188) • 例: AWS SDK for Java ドキュメント API を使用したテーブルの作成、更新、削除、一覧表 示 (p. 189) AWS SDK for Java を使用して、テーブルの作成、更新、削除、アカウント内の全テーブルの一覧表 示、特定のテーブルに関する情報収集を実行できます。 次に、AWS SDK for Java ドキュメント API を使用したテーブルオペレーションの一般的なステップ を示します。 テーブルの作成 テーブルを作成するには、テーブル名、プライマリキー、およびプロビジョニングされたスループッ ト値を指定する必要があります。以下の コードスニペットでは、数値型の属性 Id をプライマリキー として使用するサンプルテーブルを作成します。 AWS SDK for Java API を使用してテーブルを作成するには: 1. DynamoDB クラスのインスタンスを作成します。 2. CreateTableRequest をインスタンス化して、リクエスト情報を指定します。 テーブル名、属性定義、キースキーマ、プロビジョニングされたスループット値を指定する必要が あります。 3. リクエストオブジェクトをパラメータとして指定して、createTable メソッドを実行します。 以下の コードスニペットは、前述のステップの例です。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( API Version 2012-08-10 186 Amazon DynamoDB 開発者ガイド テーブルの操作 : Java new ProfileCredentialsProvider())); ArrayList<AttributeDefinition> attributeDefinitions= new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition().withAttributeName("Id").withAttributeType("N")); ArrayList<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>(); keySchema.add(new KeySchemaElement().withAttributeName("Id").withKeyType(KeyType.HASH)); CreateTableRequest request = new CreateTableRequest() .withTableName(tableName) .withKeySchema(keySchema) .withAttributeDefinitions(attributeDefinitions) .withProvisionedThroughput(new ProvisionedThroughput() .withReadCapacityUnits(5L) .withWriteCapacityUnits(6L)); Table table = dynamoDB.createTable(request); table.waitForActive(); DynamoDB によりテーブルが作成され、そのステータスが ACTIVE に設定されるまでは、テーブルを 使用する準備ができません。 createTable リクエストは、テーブルについての詳細情報を取得する ために使用できる Table オブジェクトを返します。 TableDescription tableDescription = dynamoDB.getTable(tableName).describe(); System.out.printf("%s: %s \t ReadCapacityUnits: %d \t WriteCapacityUnits: %d", tableDescription.getTableStatus(), tableDescription.getTableName(), tableDescription.getProvisionedThroughput().getReadCapacityUnits(), tableDescription.getProvisionedThroughput().getWriteCapacityUnits()); クライアントの describe メソッドを呼び出せば、いつでもテーブル情報を収集できます。 TableDescription tableDescription = dynamoDB.getTable(tableName).describe(); テーブルの更新 既存のテーブルのプロビジョニングされたスループット値のみを更新できます。ご利用のアプリケー ションの要件によっては、これらの値を更新する必要があります。 Note 読み込みキャパシティーユニットと書き込みキャパシティーユニットは、いつでも増やせま す。ただし、これらの値を減らすことができるのは、24 時間で 4 回 だけです。詳細なガイド ラインおよび制限については、「テーブルの読み書き要件の指定 (p. 179)」を参照してくだ さい。 AWS SDK for Java API を使用してテーブルを更新するには: 1. Table クラスのインスタンスを作成します。 API Version 2012-08-10 187 Amazon DynamoDB 開発者ガイド テーブルの操作 : Java 2. ProvisionedThroughput クラスのインスタンスを作成して、新しいスループット値を指定しま す。 3. ProvisionedThroughput インスタンスをパラメータとして指定して、updateTable メソッドを 実行します。 以下の コードスニペットは、前述のステップの例です。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); Table table = dynamoDB.getTable("ProductCatalog"); ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput() .withReadCapacityUnits(15L) .withWriteCapacityUnits(12L); table.updateTable(provisionedThroughput); table.waitForActive(); テーブルの削除 テーブルを削除するには: 1. Table クラスのインスタンスを作成します。 2. DeleteTableRequest クラスのインスタンスを作成し、削除するテーブル名を指定します。 3. Table インスタンスをパラメータとして指定して、deleteTable メソッドを実行します。 以下の コードスニペットは、前述のステップの例です。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); Table table = dynamoDB.getTable("ProductCatalog"); table.delete(); table.waitForDelete(); テーブルの一覧表示 アカウントのテーブルを一覧表示するには、DynamoDB のインスタンスを作成し、listTables メ ソッドを実行します。ListTables オペレーションはパラメータを必要としません。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); TableCollection<ListTablesResult> tables = dynamoDB.listTables(); Iterator<Table> iterator = tables.iterator(); while (iterator.hasNext()) { Table table = iterator.next(); System.out.println(table.getTableName()); API Version 2012-08-10 188 Amazon DynamoDB 開発者ガイド テーブルの操作 : Java } 例: AWS SDK for Java ドキュメント API を使用したテーブル の作成、更新、削除、一覧表示 次のコード例では、AWS SDK for Java ドキュメント API を使用して、テーブル(ExampleTable) を作成、更新、削除します。 このテーブル更新の一環として、プロビジョニングされたスループッ ト値が増加します。この例では、アカウント内にすべてのテーブルが一覧表示され、固有のテーブ ルの説明が取得されます。以下の例を実行するための詳しい手順については、「Java コードサンプ ル (p. 171)」を参照してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import java.util.ArrayList; import java.util.Iterator; import import import import import import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Table; com.amazonaws.services.dynamodbv2.document.TableCollection; com.amazonaws.services.dynamodbv2.model.AttributeDefinition; com.amazonaws.services.dynamodbv2.model.CreateTableRequest; com.amazonaws.services.dynamodbv2.model.KeySchemaElement; com.amazonaws.services.dynamodbv2.model.KeyType; com.amazonaws.services.dynamodbv2.model.ListTablesResult; com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; com.amazonaws.services.dynamodbv2.model.TableDescription; public class DocumentAPITableExample { static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); static String tableName = "ExampleTable"; public static void main(String[] args) throws Exception { createExampleTable(); listMyTables(); getTableInformation(); updateExampleTable(); deleteExampleTable(); } static void createExampleTable() { try { ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("Id") API Version 2012-08-10 189 Amazon DynamoDB 開発者ガイド テーブルの操作 : Java .withAttributeType("N")); ArrayList<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>(); keySchema.add(new KeySchemaElement() .withAttributeName("Id") .withKeyType(KeyType.HASH)); //Partition key CreateTableRequest request = new CreateTableRequest() .withTableName(tableName) .withKeySchema(keySchema) .withAttributeDefinitions(attributeDefinitions) .withProvisionedThroughput(new ProvisionedThroughput() .withReadCapacityUnits(5L) .withWriteCapacityUnits(6L)); System.out.println("Issuing CreateTable request for " + tableName); Table table = dynamoDB.createTable(request); System.out.println("Waiting for " + tableName + " to be created...this may take a while..."); table.waitForActive(); getTableInformation(); } catch (Exception e) { System.err.println("CreateTable request failed for " + tableName); System.err.println(e.getMessage()); } } static void listMyTables() { TableCollection<ListTablesResult> tables = dynamoDB.listTables(); Iterator<Table> iterator = tables.iterator(); System.out.println("Listing table names"); while (iterator.hasNext()) { Table table = iterator.next(); System.out.println(table.getTableName()); } } static void getTableInformation() { System.out.println("Describing " + tableName); TableDescription tableDescription = dynamoDB.getTable(tableName).describe(); System.out.format("Name: %s:\n" + "Status: %s \n" + "Provisioned Throughput (read capacity units/sec): %d \n" + "Provisioned Throughput (write capacity units/sec): %d \n", tableDescription.getTableName(), tableDescription.getTableStatus(), tableDescription.getProvisionedThroughput().getReadCapacityUnits(), API Version 2012-08-10 190 Amazon DynamoDB 開発者ガイド テーブルの操作 : .NET tableDescription.getProvisionedThroughput().getWriteCapacityUnits()); } static void updateExampleTable() { Table table = dynamoDB.getTable(tableName); System.out.println("Modifying provisioned throughput for " + tableName); try { table.updateTable(new ProvisionedThroughput() .withReadCapacityUnits(6L).withWriteCapacityUnits(7L)); table.waitForActive(); } catch (Exception e) { System.err.println("UpdateTable request failed for " + tableName); System.err.println(e.getMessage()); } } static void deleteExampleTable() { Table table = dynamoDB.getTable(tableName); try { System.out.println("Issuing DeleteTable request for " + tableName); table.delete(); System.out.println("Waiting for " + tableName + " to be deleted...this may take a while..."); table.waitForDelete(); } catch (Exception e) { System.err.println("DeleteTable request failed for " + tableName); System.err.println(e.getMessage()); } } } テーブルの操作 : .NET トピック • テーブルの作成 (p. 192) • テーブルの更新 (p. 193) • テーブルの削除 (p. 194) • テーブルの一覧表示 (p. 194) • 例: AWS SDK for .NET の低レベル API を使用した、テーブルの作成、更新、削除、一覧表 示 (p. 195) AWS SDK for .NET を使用して、テーブルの作成、更新、削除、アカウント内の全テーブルの一覧表 示、特定のテーブルに関する情報収集を実行できます。 以下に、AWS SDK for .NET を使用したテーブルオペレーションの一般的な手順を示します。 API Version 2012-08-10 191 Amazon DynamoDB 開発者ガイド テーブルの操作 : .NET 1. AmazonDynamoDBClient クラスのインスタンス(クライアント)を作成します。 2. 対応するリクエストオブジェクトを作成して、オペレーションについて必要なパラメータとオプ ションパラメータを入力します。 たとえば、テーブルを作成するには CreateTableRequest オブジェクトを作成し、既存のテーブ ルを更新するには UpdateTableRequest オブジェクトを作成します。 3. 前述のステップで作成したクライアントから提供された適切なメソッドを実行します。 テーブルの作成 テーブルを作成するには、テーブル名、プライマリキー、およびプロビジョニングされたスループッ ト値を指定する必要があります。 以下に、.NET 低レベル API を使用してテーブルを作成する手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. リクエスト情報を指定する CreateTableRequest クラスのインスタンスを作成します。 テーブル名、プライマリキー、およびプロビジョニングされたスループット値を指定する必要があ ります。 3. リクエストオブジェクトをパラメータとして指定して、AmazonDynamoDBClient.CreateTable メソッドを実行します。 次の C# コードスニペットは、前述のステップを示しています。このサンプルでは、Id をプライマリ キーとして使用するテーブル(ProductCatalog)、およびプロビジョニングされたスループット値の セットを作成します。ご利用のアプリケーションの要件によっては、UpdateTable API を使用して、 プロビジョニングされたスループット値を更新できます。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ProductCatalog"; var request = new CreateTableRequest { TableName = tableName, AttributeDefinitions = new List<AttributeDefinition>() { new AttributeDefinition { AttributeName = "Id", AttributeType = "N" } }, KeySchema = new List<KeySchemaElement>() { new KeySchemaElement { AttributeName = "Id", KeyType = "HASH" //Partition key } }, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 10, WriteCapacityUnits = 5 } }; API Version 2012-08-10 192 Amazon DynamoDB 開発者ガイド テーブルの操作 : .NET var response = client.CreateTable(request); DynamoDB がテーブルを作成し、テーブルのステータスを ACTIVE に設定するまで待機する必要が あります。CreateTable 応答には、必要なテーブル情報が記載された TableDescription プロパ ティが含まれます。 var result = response.CreateTableResult; var tableDescription = result.TableDescription; Console.WriteLine("{1}: {0} \t ReadCapacityUnits: {2} \t WriteCapacityUnits: {3}", tableDescription.TableStatus, tableDescription.TableName, tableDescription.ProvisionedThroughput.ReadCapacityUnits, tableDescription.ProvisionedThroughput.WriteCapacityUnits); string status = tableDescription.TableStatus; Console.WriteLine(tableName + " - " + status); また、クライアントの DescribeTable メソッドを呼び出せば、いつでもテーブル情報を収集できま す。 var res = client.DescribeTable(new DescribeTableRequest{TableName = "ProductCatalog"}); テーブルの更新 既存のテーブルのプロビジョニングされたスループット値のみを更新できます。ご利用のアプリケー ションの要件によっては、これらの値を更新する必要があります。 Note 読み込みキャパシティーユニットと書き込みキャパシティーユニットは、いつでも増やせ ます。また、読み込みキャパシティーユニットは、いつでも減らせます。ただし、書き込み キャパシティーユニットを減らすことができるのは、24 時間で 4 回 だけです。変更する場合 は、必ず現在の値から 10% 以上は変更してください。詳細なガイドラインおよび制限につい ては、「テーブルの読み書き要件の指定 (p. 179)」を参照してください。 以下に、.NET 低レベル API を使用してテーブルを更新する手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. リクエスト情報を指定する UpdateTableRequest クラスのインスタンスを作成します。 テーブル名およびプロビジョニングされたスループット値を指定する必要があります。 3. リクエストオブジェクトをパラメータとして指定して、AmazonDynamoDBClient.UpdateTable メソッドを実行します。 次の C# コードスニペットは、前述のステップを示しています。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ExampleTable"; var request = new UpdateTableRequest() { TableName = tableName, API Version 2012-08-10 193 Amazon DynamoDB 開発者ガイド テーブルの操作 : .NET ProvisionedThroughput = new ProvisionedThroughput() { // Provide new values. ReadCapacityUnits = 20, WriteCapacityUnits = 10 } }; var response = client.UpdateTable(request); テーブルの削除 以下に、.NET 低レベル API を使用してテーブルを削除する手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. DeleteTableRequest クラスのインスタンスを作成し、削除するテーブル名を指定します。 3. リクエストオブジェクトをパラメータとして指定して、AmazonDynamoDBClient.DeleteTable メソッドを実行します。 次の C# コードスニペットは、前述のステップを示しています。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ExampleTable"; var request = new DeleteTableRequest{ TableName = tableName }; var response = client.DeleteTable(request); テーブルの一覧表示 アカウント内にテーブルを一覧表示するには、AWS SDK for .NET 低レベル API を使用し て、AmazonDynamoDBClient のインスタンスを作成し、ListTables メソッドを実行しま す。ListTables オペレーションはパラメータを必要としません。ただし、オプションパラメータ を指定できます。たとえば、ページングを使用して 1 ページあたりのテーブル名を制限する場 合には、Limit パラメータを設定できます。この場合は、以下の C# コードスニペットに示すよ うに、ListTablesRequest オブジェクトを作成し、オプションパラメータを指定する必要が あります。ページサイズに加え、このリクエストでは、ExclusiveStartTableName パラメー タを設定します。ただし、初めは、ExclusiveStartTableName は null です。最初のページ の結果を取り出した後に次ページの結果を取り出すには、このパラメータ値を、現在の結果の LastEvaluatedTableName プロパティに設定する必要があります。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); // Initial value for the first page of table names. string lastEvaluatedTableName = null; do { // Create a request object to specify optional parameters. var request = new ListTablesRequest { Limit = 10, // Page size. ExclusiveStartTableName = lastEvaluatedTableName }; var response = client.ListTables(request); ListTablesResult result = response.ListTablesResult; foreach (string name in result.TableNames) Console.WriteLine(name); API Version 2012-08-10 194 Amazon DynamoDB 開発者ガイド テーブルの操作 : .NET lastEvaluatedTableName = result.LastEvaluatedTableName; } while (lastEvaluatedTableName != null); 例: AWS SDK for .NET の低レベル API を使用した、テーブル の作成、更新、削除、一覧表示 次の C# の例では、テーブル (ExampleTable) を作成、更新、および削除します。 アカウント内にす べてのテーブルが一覧表示され、固有のテーブルの説明が取得されます。このテーブル更新によっ て、プロビジョニングされたスループット値が増加します。次のサンプルをテストするための詳しい 手順については、「.NET コードサンプル (p. 173)」を参照してください。 using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.Model; Amazon.Runtime; namespace com.amazonaws.codesamples { class LowLevelTableExample { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); private static string tableName = "ExampleTable"; static void Main(string[] args) { try { CreateExampleTable(); ListMyTables(); GetTableInformation(); UpdateExampleTable(); DeleteExampleTable(); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } private static void CreateExampleTable() { Console.WriteLine("\n*** Creating table ***"); var request = new CreateTableRequest { AttributeDefinitions = new List<AttributeDefinition>() { new AttributeDefinition API Version 2012-08-10 195 Amazon DynamoDB 開発者ガイド テーブルの操作 : .NET { AttributeName = "Id", AttributeType = "N" }, new AttributeDefinition { AttributeName = "ReplyDateTime", AttributeType = "N" } }, KeySchema = new List<KeySchemaElement> { new KeySchemaElement { AttributeName = "Id", KeyType = "HASH" //Partition key }, new KeySchemaElement { AttributeName = "ReplyDateTime", KeyType = "RANGE" //Sort key } }, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 5, WriteCapacityUnits = 6 }, TableName = tableName }; var response = client.CreateTable(request); var tableDescription = response.TableDescription; Console.WriteLine("{1}: {0} \t ReadsPerSec: {2} \t WritesPerSec: {3}", tableDescription.TableStatus, tableDescription.TableName, tableDescription.ProvisionedThroughput.ReadCapacityUnits, tableDescription.ProvisionedThroughput.WriteCapacityUnits); string status = tableDescription.TableStatus; Console.WriteLine(tableName + " - " + status); WaitUntilTableReady(tableName); } private static void ListMyTables() { Console.WriteLine("\n*** listing tables ***"); string lastTableNameEvaluated = null; do { var request = new ListTablesRequest { Limit = 2, API Version 2012-08-10 196 Amazon DynamoDB 開発者ガイド テーブルの操作 : .NET ExclusiveStartTableName = lastTableNameEvaluated }; var response = client.ListTables(request); foreach (string name in response.TableNames) Console.WriteLine(name); lastTableNameEvaluated = response.LastEvaluatedTableName; } while (lastTableNameEvaluated != null); } private static void GetTableInformation() { Console.WriteLine("\n*** Retrieving table information ***"); var request = new DescribeTableRequest { TableName = tableName }; var response = client.DescribeTable(request); TableDescription description = response.Table; Console.WriteLine("Name: {0}", description.TableName); Console.WriteLine("# of items: {0}", description.ItemCount); Console.WriteLine("Provision Throughput (reads/sec): {0}", description.ProvisionedThroughput.ReadCapacityUnits); Console.WriteLine("Provision Throughput (writes/sec): {0}", description.ProvisionedThroughput.WriteCapacityUnits); } private static void UpdateExampleTable() { Console.WriteLine("\n*** Updating table ***"); var request = new UpdateTableRequest() { TableName = tableName, ProvisionedThroughput = new ProvisionedThroughput() { ReadCapacityUnits = 6, WriteCapacityUnits = 7 } }; var response = client.UpdateTable(request); WaitUntilTableReady(tableName); } private static void DeleteExampleTable() { Console.WriteLine("\n*** Deleting table ***"); var request = new DeleteTableRequest { TableName = tableName }; API Version 2012-08-10 197 Amazon DynamoDB 開発者ガイド テーブルの操作 : PHP var response = client.DeleteTable(request); Console.WriteLine("Table is being deleted..."); } private static void WaitUntilTableReady(string tableName) { string status = null; // Let us wait until table is created. Call DescribeTable. do { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); status = res.Table.TableStatus; } catch (ResourceNotFoundException) { // DescribeTable is eventually consistent. So you might // get resource not found. So we handle the potential exception. } } while (status != "ACTIVE"); } } } テーブルの操作 : PHP トピック • テーブルの作成 (p. 199) • テーブルの更新 (p. 200) • テーブルの削除 (p. 200) • テーブルの一覧表示 (p. 201) • 例: AWS SDK for PHP の低レベル API を使用した、テーブルの作成、更新、削除、一覧表 示 (p. 202) AWS SDK for PHP を使用して、テーブルの作成、更新、削除、アカウント内の全テーブルの一覧表 示、特定のテーブルに関する情報収集を実行できます。 以下に、PHP の SDK を使用した DynamoDB オペレーションの一般的な手順を示します。 1. DynamoDB クライアントのインスタンスを作成します。 2. オプションのパラメーターを含む DynamoDB オペレーションのパラメーターを指定します。 3. DynamoDB からの応答をアプリケーションのローカル変数にロードします。 API Version 2012-08-10 198 Amazon DynamoDB 開発者ガイド テーブルの操作 : PHP テーブルの作成 テーブルを作成するには、テーブル名、プライマリキー、およびプロビジョニングされたスループッ ト値を指定する必要があります。以下の PHP コードサンプルでは、数値型の属性 Id をプライマリ キーとして使用する ExampleTable を作成します。 次の PHP コードスニペットでは、Id をプライマリキーとして使用するテーブル (ProductCatalog)、お よびプロビジョニングされたスループット値のセットを作成します。ご利用のアプリケーションの要 件によっては、updateTable メソッドを使用して、プロビジョニングされたスループット値を更新 できます。 require 'vendor/autoload.php'; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'ExampleTable'; echo "# Creating table $tableName...\n"; $result = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'Id', 'AttributeType' => 'N' ] ], 'KeySchema' => [ [ 'AttributeName' => 'Id', 'KeyType' => 'HASH' ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 5, 'WriteCapacityUnits' => 6 ] ]); print_r($result->getPath('TableDescription')); データをテーブル内に配置するには、DynamoDB がテーブルを作成し、テーブルのステータスを ACTIVE に設定するまで待機する必要があります。クライアントの waitUntil 関数を使用して、 テーブルのステータスが ACTIVE になるまで待機することができます。 次の コードスニペットはそれを行う方法を示しています。連想配列 @waiter はオプションであ り、waitUntil のポーリングオプションを指定することができます。 $dynamodb->waitUntil('TableExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] ]); API Version 2012-08-10 199 Amazon DynamoDB 開発者ガイド テーブルの操作 : PHP テーブルの更新 既存のテーブルを更新し、プロビジョニングされたスループット値またはセカンダリインデックスを 変更できます。 UpdateTable リクエストが成功するとすぐに、テーブルのステータスは UPDATING になります。オ ペレーションが完了すると、テーブルの状態は ACTIVE に戻ります。 以下の PHP コードスニペットは、テーブルのプロビジョニングされたスループット設定を変更しま す。次に、テーブルが再度 ACTIVE になるまで待機します。 $tableName = 'ExampleTable'; echo "Updating provisioned throughput settings on $tableName...\n"; $result = $dynamodb->updateTable([ 'TableName' => $tableName, 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 6, 'WriteCapacityUnits' => 7 ] ]); $dynamodb->waitUntil('TableExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] ]); echo "New provisioned throughput settings:\n"; echo "Read capacity units: " . $result['TableDescription']['ProvisionedThroughput'] ['ReadCapacityUnits'] . "\n"; echo "Write capacity units: " . $result['TableDescription']['ProvisionedThroughput'] ['WriteCapacityUnits'] . "\n"; テーブルの削除 不要になったテーブルは削除できます。 DeleteTable リクエストが成功するとすぐに、テーブルのステータスは DELETING になります。オ ペレーションが完了すると、テーブルは存在しなくなります。 以下の PHP コードスニペットはテーブルを削除し、オペレーションが完了するまで待機します。 $tableName = 'ExampleTable'; echo "Deleting the table...\n"; API Version 2012-08-10 200 Amazon DynamoDB 開発者ガイド テーブルの操作 : PHP $result = $dynamodb->deleteTable([ 'TableName' => $tableName ]); $dynamodb->waitUntil('TableNotExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] ]); echo "The table has been deleted.\n"; テーブルの一覧表示 ListTables オペレーションを使用して、現在の AWS リージョン内のすべてのテーブルの名前を返 します。 オプションのパラメーターを指定できます。たとえば、ページングを使用して 1 ページあたりの テーブル名を制限する場合には、Limit パラメータを設定できます。ExclusiveStartTableName パラメータも設定できます。最初のページの結果を取り出すと、DynamoDB は LastEvalutedTableName 値を返します。ExclusiveStartTableName パラメータに LastEvalutedTableName の値を使用すると、次のページの結果を取得できます。 次の PHP コードスニペットは、現在の AWS リージョンで所有しているすべてのテーブルをリスト表 示します。ページごとに、2 つのテーブル名の Limit 値を使用して、LastEvalutedTableName の 値を ExclusiveStartTableName パラメーターに使用します。 $tables = []; unset($response); do { if (isset($response)) { $params = [ 'Limit' => 2, 'ExclusiveStartTableName' => $response['LastEvaluatedTableName'] ]; }else { $params = ['Limit' => 2]; } $response = $dynamodb->listTables($params); foreach ($response['TableNames'] as $key => $value) { echo "$value\n"; } $tables = array_merge($tables, $response['TableNames']); } while ($response['LastEvaluatedTableName']); // Print total number of tables echo "Total number of tables: "; print_r(count($tables)); echo "\n"; API Version 2012-08-10 201 Amazon DynamoDB 開発者ガイド テーブルの操作 : PHP 例: AWS SDK for PHP の低レベル API を使用した、テーブル の作成、更新、削除、一覧表示 次の PHP コード例では、テーブル (ExampleTable) を作成、更新、および削除します。このテーブル 更新の一環として、プロビジョニングされたスループット値が増加します。この例では、現在のリー ジョンのすべてのテーブルが一覧表示され、固有のテーブルの説明が取得されます。終了時に、この 例ではテーブルが削除されます。 Note 次に示すコード例を実行するための詳しい手順については、「PHP コードサンプ ル (p. 175)」を参照してください。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'ExampleTable'; echo "# Creating table $tableName...\n"; try { $response = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'Id', 'AttributeType' => 'N' ] ], 'KeySchema' => [ [ 'AttributeName' => 'Id', 'KeyType' => 'HASH' //Partition key ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 5, 'WriteCapacityUnits' => 6 ] ]); $dynamodb->waitUntil('TableExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 API Version 2012-08-10 202 Amazon DynamoDB 開発者ガイド テーブルの操作 : PHP ] ]); print_r($response->getPath('TableDescription')); echo "table $tableName has been created.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to create table $tableName\n"); } #################################################################### # Updating the table echo "# Updating the provisioned throughput of table $tableName.\n"; try { $response = $dynamodb->updateTable([ 'TableName' => $tableName, 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 6, 'WriteCapacityUnits' => 7 ] ]); $dynamodb->waitUntil('TableExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] ]); echo "New provisioned throughput settings:\n"; $response = $dynamodb->describeTable(['TableName' => $tableName]); echo "Read capacity units: " . $response['Table']['ProvisionedThroughput']['ReadCapacityUnits']."\n"; echo "Write capacity units: " . $response['Table']['ProvisionedThroughput']['WriteCapacityUnits']."\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to update table $tableName\n"); } #################################################################### # Deleting the table try { echo "# Deleting table $tableName...\n"; $response = $dynamodb->deleteTable([ 'TableName' => $tableName]); $dynamodb->waitUntil('TableNotExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, API Version 2012-08-10 203 Amazon DynamoDB 開発者ガイド 項目の操作 'maxAttempts' => 20 ] ]); echo "The table has been deleted.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to delete table $tableName\n"); } #################################################################### # List all table names for this AWS account, in this region echo "# Listing all of your tables in the current region...\n"; $tables = []; // Walk through table names, two at a time unset($response); do { if (isset($response)) { $params = [ 'Limit' => 2, 'ExclusiveStartTableName' => $response['LastEvaluatedTableName'] ]; }else { $params = ['Limit' => 2]; } $response = $dynamodb->listTables($params); foreach ($response['TableNames'] as $key => $value) { echo "$value\n"; } $tables = array_merge($tables, $response['TableNames']); } while ($response['LastEvaluatedTableName']); // Print total number of tables echo "Total number of tables: "; print_r(count($tables)); echo "\n"; ?> DynamoDB での項目の操作 トピック • 概要 (p. 205) • 項目を読み込む (p. 206) • 項目を書き込む (p. 206) API Version 2012-08-10 204 Amazon DynamoDB 開発者ガイド 概要 • バッチオペレーション (p. 207) • アトミックカウンタ (p. 207) • 条件付きの書き込み (p. 208) • 式を使用した項目の読み取りと書き込み (p. 210) • 項目の操作 : Java (p. 228) • 項目の操作 : .NET (p. 250) • 項目の操作 : PHP (p. 274) DynamoDB では、項目は属性の集まりです。各属性には名前と値があります。属性値はスカラー型、 セット型、ドキュメント型のいずれかです。詳細については、「データ型 (p. 12)」を参照してくださ い。 DynamoDB では、項目の読み取りおよび書き込みをするオペレーションを実行できます。これらのオ ペレーションでは、操作する項目と属性を指定する必要があります。項目を記述するとき、true と評 価される必要のある条件を 1 つ以上指定できます。たとえば、同じキーを持つ既存の項目がない場合 にのみ、書き込みが成功するようにできます。 このセクションでは、Amazon DynamoDB の項目を操作する方法について説明します。項目の読 み込みと書き込み、条件付き更新、アトミックカウンターも取り上げています。このセクションに は、AWS SDK を使用するサンプルコードも含まれています。ベストプラクティスについては、項目 の操作のガイドライン (p. 577) を参照してください。 概要 1 つの項目は 1 つ以上の属性で構成されます。各属性は名前、データ型、値で構成されます。項目の 読み込みまたは書き込み時、必須の属性はプライマリキーを構成する属性のみです。 Important プライマリキーでは、その属性をすべて指定する必要があります。たとえば、シンプルなプ ライマリキーの場合は、パーティションキーを指定する必要があります。複合プライマリ キー (パーティションキーおよびソートキー) の場合、パーティションキーおよびソートキー の両方を指定する必要があります。詳細については、次を参照してください。 プライマリ キー (p. 5)。 プライマリキーの場合を除き、テーブル内の項目には事前定義されたスキーマはありません。たとえ ば、製品情報を格納するには、ProductCatalog テーブルを作成し、書籍や自転車など、さまざまな製 品項目をこのテーブルに格納できます。以下のテーブルに、書籍と自転車の 2 つの項目を示します。 これらは、ProductCatalog テーブルに格納できます。この例では JSON に似た構文を使用して、属性 値を表しています。 Id(プライマリキー) 101 その他の属性 { Title = "Book 101 Title" ISBN = "111-1111111111" Authors = "Author 1" Price = "-2" Dimensions = "8.5 x 11.0 x 0.5" PageCount = "500" InPublication = true ProductCategory = "Book" } API Version 2012-08-10 205 Amazon DynamoDB 開発者ガイド 項目を読み込む Id(プライマリキー) 201 その他の属性 { Title = "18-Bicycle 201" Description = "201 description" BicycleType = "Road" Brand = "Brand-Company A" Price = "100" Color = [ "Red", "Black" ] ProductCategory = "Bike" } 個々の項目には多数の属性がありますが、項目サイズに対する 400 KB の制限があります。項目のサ イズは、属性名と値の長さの合計です(バイナリおよび UTF-8 の長さ)です。したがって、属性名は 短く保つことをお勧めします。 項目を読み込む DynamoDB テーブルから項目を読み込むには、GetItem オペレーションを使用します。必要な項目 のプライマリキーと共にテーブルの名前を指定する必要があります。 プライマリキーでは、一部ではなくすべての属性を指定する必要があります。たとえば、テーブルに 複合プライマリキー (パーティションキーおよびソートキー) がある場合、パーティションキーおよび ソートキーの値を指定する必要があります。 次に示しているのは、GetItem のデフォルトの動作です。 • GetItem は、結果整合性のある読み込みを行います。 • GetItem は、項目のすべての属性を返します。 • GetItem は、消費されるプロビジョンドキャパシティーユニットについて情報を返しません。 GetItem にはオプションのパラメーターが用意されているため、必要に応じてこれらのデフォルトを 上書きすることができます。 読み込み整合性 DynamoDB では、堅牢性を確保するために各項目のコピーが複数保持されます。それぞれの書き込み リクエストを成功させるために、DynamoDB では複数台のサーバーでの書き込みの堅牢性を保証して います。ただし、書き込みがすべてのコピーに伝達されるには時間がかかります。DynamoDB では、 データに結果整合性があります。つまり、ある項目を書き込み、すぐに読み込もうとすると、その書 き込みの結果が表示されない可能性があります。 デフォルトでは、GetItem オペレーションは結果整合性のある読み込みを行います。必要に応じて、 強力な整合性のある読み込みを代わりにリクエストできます。これにより、追加の読み込みキャパシ ティーユニットが消費されますが、最新の項目が返されます。 結果整合性のある GetItem リクエストによって消費される読み込みキャパシティーユニットは、強 い整合性のあるリクエストの半分だけです。このため、可能な限り、結果整合性のある読み込みを使 用できるようにアプリケーションを設計することが賢明です。データのすべてのコピーにわたる整合 性は、普通、1 秒以内に確保されます。 項目を書き込む DynamoDB テーブルの項目を作成、更新、削除するには、次のオペレーションを使用します。 API Version 2012-08-10 206 Amazon DynamoDB 開発者ガイド バッチオペレーション • PutItem - 新しい項目を作成します。同じキーを持つ項目がテーブルにすでに存在する場合は、新 しい項目に置き換えられます。テーブル名と書き込む項目を指定する必要があります。 • UpdateItem - 項目が存在しない場合、このオペレーションは新しい項目を作成します。すでに存 在する場合は、既存の項目の属性を変更します。テーブル名と変更する項目のキーを指定する必要 があります。更新する属性ごとに、新しい値を指定する必要があります。 • DeleteItem - 項目を削除します。テーブル名と削除する項目のキーを指定する必要があります。 これらの各オペレーションで、プライマリキーの一部の属性ではなくすべての属性を指定する必要が あります。たとえば、テーブルに複合プライマリキー (パーティションキーおよびソートキー) がある 場合、パーティションキーおよびソートキーの値を指定する必要があります。 既存の項目が誤って上書きされたり削除されたりしないように、条件式をこれらのどのオペレーショ ンでも使用できます。条件式を使用すると、オペレーションを続行する前に条件が true かどうか(項 目がテーブルにすでに存在するかどうかなど)を確認できます。すでに存在しない場合にのみ項目を 書き込むには、attribute_not_exists 関数と、テーブルのパーティションキーの名前を使用する 条件式とともに PutItem を使用します。これは、存在する項目にはパーティションキーがあるため です。詳細については、「条件付き書き込みオペレーション (p. 227)」を参照してください。 場合によっては、ある属性値を変更する前後に、その属性値を DynamoDB で表示することをお勧め します。たとえば、UpdateItem オペレーションでは、更新前に既存の属性値が返されるようにリ クエストできます。PutItem、UpdateItem、および DeleteItem には、ReturnValues パラメー ターがあります。このパラメーターを使用することで、属性の変更前後に、その属性値を返すことが できます。 デフォルトでは、これらのオペレーションはどれも、消費されるプロビジョンドキャパシティーユ ニットについて情報を返しません。ReturnConsumedCapacity パラメーターを使用すると、この情 報を取得できます。 バッチオペレーション アプリケーションで複数の項目を読み込む必要がある場合は、BatchGetItem を使用できま す。BatchGetItem の 1 回のリクエストで、最大 16 MB のデータ(最大 100 の項目)を取得できま す。さらに、BatchGetItem の 1 回のリクエストで、複数のテーブルから項目を取得できます。 BatchWriteItem オペレーションでは、複数の項目を入力したり削除したりできま す。BatchWriteItem オペレーションでは、最大 25 の入力または削除リクエストにより、最 大 16 MB のデータを書き込むことができます。個々の項目の最大サイズは 400 KB です。さら に、BatchWriteItem の 1 回のリクエストで、複数のテーブルの項目を入力したり削除したり できます(ただし BatchWriteItem で項目を更新することはできません。項目を更新するに は、UpdateItem を代わりに使用してください) バッチは 1 つ以上のリクエストで構成されます。リクエストごとに、DynamoDB によってそのリク エストに適切なオペレーションが呼び出されます。たとえば、BatchGetItem リクエストに 5 つの項 目が含まれている場合、DynamoDB によって 5 回の GetItem オペレーションが暗黙的に実行されま す。同様に、BatchWriteItem リクエストに 2 つの入力リクエストと 4 つの削除リクエストが含ま れている場合、DynamoDB によって 2 つの PutItem リクエストと 4 つの DeleteItem リクエスト が暗黙的に実行されます。 バッチの個々のリクエストが失敗しても(テーブルのプロビジョンドスループット設定を超えている ためなどで)、バッチ全体が失敗することはありません。代わりに、バッチオペレーションでは、失 敗した個々のリクエストのキーとデータが返されるため、そのオペレーションを再試行できるように なります。一般的に、バッチのすべてのリクエストが失敗しない限り、バッチオペレーションは失敗 しません。 アトミックカウンタ DynamoDB では、アトミックカウンターがサポートされています。そのため、UpdateItem オペレー ションを使用して、他の書き込みリクエストを妨げることなく既存の属性値をインクリメントまたは API Version 2012-08-10 207 Amazon DynamoDB 開発者ガイド 条件付きの書き込み デクリメントできます。(すべての書き込みリクエストは、受信された順に適用されます)。たと えば、あるウェブアプリケーションでサイトの訪問者数を示すカウンタを保持するとします。この場 合、アプリケーションはこのカウンタを、現在値に関係なくインクリメントする必要があります。 アトミックカウンターの更新はべき等のオペレーションではありません。つまり、カウンターは UpdateItem の呼び出しごとにインクリメントされます。前のリクエストの失敗が疑われる場合、ア プリケーションは UpdateItem オペレーションを再試行しますが、カウンターが 2 回更新される恐れ があります。ウェブサイトのカウンタの場合には許容できる可能性があります。というのも、訪問者 のカウントがわずかに上下しても大きな問題にはならないからです。 銀行業務用のアプリケーション の場合は、アトミックカウンターよりも条件付き更新を使用したほうが安全です。 アトミックカウンターを更新するには、UpdateItem オペレーションの UpdateExpression パラ メータで数値型の属性を使用し、実行する更新アクションとして SET を使用します。カウンターは正 の数を使用してインクリメント、負の数を使用してデクリメントできます。詳細については、「数値 属性の増減 (p. 224)」を参照してください。. 条件付きの書き込み マルチユーザー環境では、複数のクライアントが同じ項目にアクセスし、その項目の属性値の変更を 同時に実行する可能性があります。しかし、各クライアントでは、他のクライアントが項目をすでに 変更していることに気が付かない可能性があります。この点について、次の図に示します。ここで、 クライアント 1 とクライアント 2 は項目(Id=1)のコピーを取得しています。クライアント 1 は、価 格を 10 USD から 8 USD に変更します。その後で、クライアント 2 が同じ項目の価格を 12 USD に 変更します。この結果、クライアント 1 による前の変更内容は失われます。 クライアントによるデータ項目への書き込みを調整できるように、DynamoDB では、条件付き書き込 みが PutItem、DeleteItem、UpdateItem のオペレーションでサポートされています。条件付き書 き込みを使用すると、オペレーションが成功するのは、項目の属性が 1 つ以上の想定条件を満たす場 合のみです。それ以外の場合は、エラーが返されます。次の例では、クライアント 1 とクライアント 2 が項目(Id=1)のコピーを取得しています。まず、クライアント 1 は、サーバー上の既存の項目の 価格が 10 USD であるという条件で、項目の価格を 8 USD に更新しようとします。その条件が満たさ れるため、このオペレーションは成功します。その後、クライアント 2 は、サーバー上の既存の項目 の価格が 10 USD であるという条件で、項目の価格を 12 USD に更新しようとします。現在の価格が 8 USD ドルになっているため、その条件が満たされず、したがってクライアント 2 のリクエストは失 敗します。 API Version 2012-08-10 208 Amazon DynamoDB 開発者ガイド 条件付きの書き込み 条件付き書き込みがべき等のオペレーションであることに注意してください。つまり、同じ条件付き 書き込みリクエストを何度も送信できますが、指定した更新が最初に DynamoDB によって実行され た後は、更新のリクエストがあってもそれ以上項目への影響はありません。たとえば、現在の価格が 20 USD であるという条件で、書籍項目の価格を 10% 更新するリクエストを発行するとします。しか し、応答を得る前にネットワークエラーが発生したため、リクエストが成功したかどうかがわからな くなってしまいました。条件付き更新は、べき等のオペレーションであるため、同じリクエストを再 度送信することができます。DynamoDB は、現在の価格がまだ 20 USD である場合にのみ価格を更新 します。 条件付きの PutItem、DeleteItem、または UpdateItem をリクエストするに は、ConditionExpression パラメーターで条件(複数可)を指定します。ConditionExpression は、属性名、条件付き演算子および組み込み関数を含む文字列です。式全体の評価結果が true になる 必要があります。そうでない場合、オペレーションは失敗します。 Tip 詳細については、「条件付き書き込みオペレーション (p. 227)」を参照してください。 ReturnConsumedCapacity パラメータを指定した場合、条件書き込み中に使用された書き込み容 量ユニットの数が DynamoDB により返されます。(書き込みオペレーションでは、書き込み容量ユ ニットだけが使用される点に注意してください。読み込み容量ユニットが使用されることはありませ ん)。ReturnConsumedCapacity を TOTAL に設定すると、テーブルに対して消費された書き込み キャパシティーとすべてのグローバルセカンダリインデックスが返されます。INDEXES はグローバ ルセカンダリインデックスによって消費された書き込みキャパシティーのみを返し、NONE は、消費 されたキャパシティーの統計情報を一切返さないことを意味します。 条件付き書き込み中に ConditionExpression が false と評価された場合でも、DynamoDB はテー ブルから書き込みキャパシティーユニットを引き続き消費します。 • 項目が存在する場合、消費される書き込みキャパシティーユニットの数は、項目のサイズによっ て異なります (たとえば、1 KB の項目の条件付き書き込みが失敗すると、1 つの書き込みキャパシ ティーユニットが消費されます。項目のサイズがその倍である場合、条件付き書き込みが失敗する と、2 つの書き込みキャパシティーユニットが消費されます)。 • 項目が存在しない場合、DynamoDB は 1 つの書き込みキャパシティーユニットを消費します。 失敗した条件付き書き込みでは、書き込みオペレーションから予期される応答ではなく ConditionalCheckFailedException が返されます。したがって、消費された書き込みキャパシ ティーユニットに関する情報は受け取りません。ただし、Amazon CloudWatch でテーブルの ConsumedWriteCapacityUnits メトリクスを表示して、テーブルから消費された、プロビジョ API Version 2012-08-10 209 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み ニングされた書き込みキャパシティーを判断することができます。詳細については、「Amazon DynamoDB のモニタリング (p. 495)」の「DynamoDB Metrics (p. 497)」を参照してください。 Note local secondary indexは、グローバルセカンダリインデックスとは異なり、プロビジョニング されたスループット容量をそのテーブルと共有します。local secondary indexでの読み取りと 書き込みのアクティビティは、テーブルからプロビジョニングされたスループット容量を消 費します。 式を使用した項目の読み取りと書き込み DynamoDB では、式を使用して、項目から読み取る属性を示します。また、項目を書き込むときも式 を使用して、満たす必要がある条件(条件付き更新とも呼ばれます)と、属性を更新する方法を示し ます。更新の例として、属性を新しい値で置き換えたり、新しいデータをリストやマップに追加した りします。このセクションでは、利用可能なさまざまな種類の式について説明します。 Note 下位互換性のために、DynamoDB は式を使用しない条件パラメータもサポートします。詳細 については、「レガシー条件パラメータ (p. 678)」を参照してください。 新しいアプリケーションでは、レガシーパラメータではなく式を使用する必要があります。 トピック • 導入事例: ProductCatalog 項目 (p. 210) • プロジェクト式を使用した項目属性へのアクセス (p. 211) • 属性の名前および値でのプレースホルダーの使用 (p. 213) • 条件式を使用した条件付きの書き込みの実行 (p. 215) • 更新式を使用した項目および属性の変更 (p. 222) 導入事例: ProductCatalog 項目 このセクションでは、ProductCatalog テーブルの項目について検討します(このテーブルについては、 「サンプルテーブルとデータ (p. 589)」でいくつかの項目とともに説明します)。項目の表現を次に 示します。 { Id: 206, Title: "20-Bicycle 206", Description: "206 description", BicycleType: "Hybrid", Brand: "Brand-Company C", Price: 500, Color: ["Red", "Black"], ProductCategory: "Bike", InStock: true, QuantityOnHand: null, RelatedItems: [ 341, 472, 649 ], Pictures: { API Version 2012-08-10 210 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み FrontView: "http://example.com/products/206_front.jpg", RearView: "http://example.com/products/206_rear.jpg", SideView: "http://example.com/products/206_left_side.jpg" }, ProductReviews: { FiveStar: [ "Excellent! Can't recommend it highly enough! "Do yourself a favor and buy this." ], OneStar: [ "Terrible product! Do not buy this." ] } Buy it!", } 次の点に注意してください。 • パーティションキー値 (Id) は 206 です。ソートキーはありません。 • ほとんどの属性に、文字列、数値、ブール値、NULL などのスカラーデータ型があります。 • 1 つの属性(Color)は文字列セットです。 • 次の属性はドキュメントデータ型です。 • RelatedItems のリスト。各要素は関連製品の Id です。 • Pictures のマップ。各要素は対応するイメージファイルの URL と、写真の短い説明です。 • ProductReviews のマップ。各要素は、レーティングと、そのレーティングに対応する評価のリ ストを表します。最初に、このマップには 5 つ星と 1 つ星の評価が入力されます。 プロジェクト式を使用した項目属性へのアクセス テーブルからデータを読み取るには、GetItem、Query、Scan などの オペレーションを使用しま す。DynamoDB はデフォルトですべての項目属性を返します。すべての属性ではなく、一部の属性だ けを取得するには、プロジェクション式を使用します。 Note 以下のセクションの例は、「導入事例: ProductCatalog 項目 (p. 210)」の ProductCatalog 項 目に基づいています。 トピック • プロジェクション式 (p. 211) • ドキュメントパス (p. 212) プロジェクション式 プロジェクション式は、任意の属性を識別する文字列です。1 つの属性を取得するには、名前を指定 します。複数の属性の場合、名前をカンマで区切る必要があります。 プロジェクション式のいくつかの例を次に示します。 • 1 つの最上位属性。 Title • 3 つの最上位属性。DynamoDB は Color セット全体を取得します。 Title, Price, Color API Version 2012-08-10 211 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み • 4 つの最上位属性。DynamoDB は RelatedItems および ProductReviews のコンテンツ全体を返 します。 Title, Description, RelatedItems, ProductReviews 最初の文字が a-z または A-Z であり、2 番目の文字(ある場合)が a-z、A-Z、または 0-9 である場 合は、投影式で任意の属性値を使用できます。属性名がこの要件を満たさない場合は、式の属性名を プレースホルダーとして定義する必要があります。詳細については、「式の属性名 (p. 213)」を参照 してください。 Note プロジェクション式を指定する方法は、使用するプログラミング言語によって異なります。 サンプルコードについては、該当言語の Amazon DynamoDB 入門ガイド のセクションを参照 してください。 ドキュメントパス 式は、最上位属性に加えて、任意のドキュメントタイプ属性の個別の要素にアクセスできます。これ を行うには、項目内で要素の場所またはドキュメントパスを指定する必要があります。ドキュメント パスにより、DynamoDB は、複数のリストやマップ内で深くネストされている場合でも、属性の場所 を見つけることができます。 最上位属性の場合、ドキュメントパスは単純に属性名になります。 ネストされた属性の場合は、間接参照演算子を使用してドキュメントパスを構築します。 リスト要素へのアクセス リスト要素の間接参照演算子は [n] で、n は要素数です。リストの要素はゼロベースであるため、[0] はリスト内の最初の要素、[1] は 2 番目の要素、という順番で表されます。 • MyList[0] • AnotherList[12] • ThisList[5][11] 要素 ThisList[5] は、それ自体がネストされたリストです。したがって、ThisList[5][11] は、 そのリストの 12 番目の要素を参照します。 リストの間接参照のインデックスは、ゼロ以外の整数である必要があります。そのため、次の式は無 効です。 • MyList[-1] • MyList[0.4] マップ要素へのアクセス マップ要素の間接参照演算子は .(ドット)です。マップの要素間の区切り文字として、ドットを使用 します。 • MyMap.nestedField • MyMap.nestedField.deeplyNestedField ドキュメントパスの例 ドキュメントパスを使用したプロジェクション式のいくつかの例を次に示します。 API Version 2012-08-10 212 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み • RelatedItems リストの 3 番目の要素(このリスト要素はゼロベースであることに注意してくださ い)。 RelatedItems[2] • 項目の価格、色、製品の正面の写真。 Price, Color, Pictures.FrontView • すべての 5 つ星の評価。 ProductReviews.FiveStar • 最初の 5 つ星の評価。 ProductReviews.FiveStar[0] Note ドキュメントパスの最大深度は 32 です。したがって、任意のパスの間接参照の数はこの制限 を超えることはできません。 最初の文字が a-z または A-Z であり、2 番目の文字(ある場合)が a-z、A-Z、または 0-9 であ る場合は、ドキュメントパスで任意の属性値を使用できます。属性名がこの要件を満たさない場合 は、式の属性名をプレースホルダーとして定義する必要があります。詳細については、「式の属性 名 (p. 213)」を参照してください。 属性の名前および値でのプレースホルダーの使用 このセクションでは、DynamoDB 式で使用できるプレースホルダー(置換変数)について説明しま す。 トピック • 式の属性名 (p. 213) • 式の属性値 (p. 215) 式の属性名 場合によっては、DynamoDB 予約語と競合する属性名を含む式を書く必要が生じることがあります。 予約語の一覧については、「DynamoDB の予約語 (p. 668)」を参照してください。 たとえば、SESSION は予約語であるため、次のプロジェクション式は無効です。 • Classroom, Session, StartTime この問題に対処するには、式の属性名を定義できます。式の属性名は、実際の属性名の代わりとして 式で使用するプレースホルダーです。式の属性名は # で始まり、1 つ以上の英数字が続きます。 上記の式では、Session を、#s などの式の属性名と置き換えることができます。#(シャープ記号) は必須であり、これが属性名のプレースホルダーであることを示します。変更された式は次のように なります。 • Classroom, #s, StartTime Tip 属性名が数値で始まるか、スペース、特殊文字、または予約語を含む場合、式の属性名を使 用して式のその属性名を置き換えなければなりません。 API Version 2012-08-10 213 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み 式では、ドット(".")はドキュメントパスの区切り文字として解釈されます。ただし、DynamoDB で は属性名の一部としてドット文字を使用することもできます。これは、あいまいな意味を持つことが あります。例として、DynamoDB テーブル内の次の項目について考えます。 { Id: 1234, My.Scalar.Message: "Hello", MyMap: { MyKey: "My key value", MyOtherKey: 10 } } 次のプロジェクション式を使用して、My.Scalar.Message にアクセスするとします。 My.Scalar.Message DynamoDB は、予想される Hello 文字列ではなく空の結果を返します。これは、DynamoDB が式の ドットをドキュメントパスの区切り文字として解釈するためです。この場合、My.Scalar.Message の置換として式の属性名(#msm など)を定義する必要があります。その後、次のプロジェクション式 を使用します。 #msm 次に、DynamoDB が目的の結果を返します。Hello Tip 式のドットは、ドキュメントパスの区切り文字を表します。 属性名にドット文字が含まれる場合、その式属性名を定義します。その場合、式でその名前 を使用できます。 ここでは、次のプロジェクション式を使用して、埋め込み属性 MyMap.MyKey にアクセスするとしま す。 MyMap.MyKey 結果は、予想される My key value になります。 ただし、代わりに式属性名を使用することにした場合はどうなるでしょうか。たとえ ば、MyMap.MyKey の置換として #mmmk を定義した場合はどうなるでしょうか。DynamoDB は、予 想される文字列ではなく空の結果を返します。これは、DynamoDB が式属性値のドットを属性名内の 文字として解釈するためです。DynamoDB は、式属性名 #mmmk を評価すると、MyMap.MyKey がスカ ラー属性(これは意図されたものではありません)を参照していると判断します。 2 つの式属性名(ドキュメントパス内の要素ごとに 1 つずつ)を定義するのが正しい方法です。 • #mm — MyMap • #mk — MyKey その後、次のプロジェクション式を使用します。 #mm.#mk 次に、DynamoDB が目的の結果を返します。My key value API Version 2012-08-10 214 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み Note 式属性名のドットは、属性名内の有効な文字を表します。 入れ子になった属性にアクセスするには、ドキュメントパス内の各要素の式属性名を定義し ます。その後、これらの名前を式で使用できます。各名前はドットで区切ります。 式の属性名は、同じ属性名を繰り返し参照する必要がある場合にも役立ちます。たとえ ば、ProductCatalog 項目からいくつかの評価を取得する次の式を考えてみます。 • ProductReviews.FiveStar, ProductReviews.ThreeStar, ProductReviews.OneStar これをより簡潔にするために、ProductReviews を、#pr などの式の属性名で置き換えることができ ます。変更された式は次のようになります。 • #pr.FiveStar, #pr.ThreeStar, #pr.OneStar 式属性名を定義した場合、式全体で一貫して使用する必要があります。さらに、# 記号を省略するこ とはできません。 Note 式の属性名を指定する方法は、使用するプログラミング言語によって異なります。 サンプル コードについては、該当言語の Amazon DynamoDB 入門ガイド のセクションを参照してくだ さい。 式の属性値 属性を値と比較する必要がある場合は、式の属性値をプレースホルダーとして定義します。式の属性 値は、比較する実際の値(実行時までわからないことがある値)の置換です。式の属性値は : で始ま り、1 つ以上の英数字が続きます。 たとえば、価格が特定の値より低い製品を示し、実際の値はユーザーが入力するアプリケーションが あるとします。:p などの式の属性値を、プレースホルダーとして定義できます。: が必須であり、こ れは属性値のプレースホルダーであることを示します。このような式は次のようになります。 • Price < :p アプリケーションは、実行時に希望の価格を入力するようにユーザーに求めることができます。この 価格は式で使用され、DynamoDB は必要な結果を取得します。 式属性値を定義した場合、式全体で一貫して使用する必要があります。さらに、: 記号を省略するこ とはできません。 Note 式の属性値を指定する方法は、使用するプログラミング言語によって異なります。 サンプル コードについては、該当言語の Amazon DynamoDB 入門ガイド のセクションを参照してくだ さい。 条件式を使用した条件付きの書き込みの実行 テーブルの項目を確認するには、Query や Scan などの オペレーションを使用します。これらの オペレーションにより、選択条件およびフィルタリングの独自の条件を指定することができます。 DynamoDB は、条件に一致する項目のみを評価して返します。 API Version 2012-08-10 215 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み 項目を書き込むには、PutItem、UpdateItem、DeleteItem などの オペレーションを使用します。 これらのオペレーションとともに条件式を使用すると、項目を変更できる方法と条件を管理できま す。 項目が事前に一部の条件を満たさない場合、更新が発生しないようにすることができます。たと えば、PutItem が既存の項目を上書きしないようにできます。 Note このセクションの例は、「導入事例: ProductCatalog 項目 (p. 210)」の ProductCatalog 項目 に基づいています。 トピック • 条件式 (p. 216) • 条件式リファレンス (p. 217) 条件式 条件式は、テーブルの項目を読み書きするときに適用する制限を表します。条件式は、属性名、ド キュメントパス、論理演算子、および関数を含むフリーフォームの文字列です。条件式で使用できる 要素の一覧については、「条件式リファレンス (p. 217)」を参照してください。 条件式のいくつかの例を次に示します。 これらの式の一部では、属性の名前と値にプレースホルダー が使用されている点に注意してください。詳細については、「属性の名前および値でのプレースホル ダーの使用 (p. 213)」を参照してください。 • PutItem が既存の項目を上書きしないようにするには、項目のパーティションキーが存在しないこ とを指定する条件式を使用します。テーブルのすべての項目にはパーティションキーが必要である ため、これにより、既存の項目が上書きされるのを回避できます。たとえば、パーティションキー の名前が「town」の場合は、次のコードを使用できます。 attribute_not_exists(town) この条件式は PutItem で使用されます。DynamoDB は、書き込む項目のプライマリキーとプライ マリキーが一致する項目を最初に探します。結果にパーティションキーが含まれないのは、検索で 何も返されない場合のみです。それ以外の場合、上記の attribute_not_exists 関数は失敗し、 書き込みは禁止されます。 • RearView の写真があるすべての項目。 attribute_exists(Pictures.RearView) • 1 つ星の評価がない項目のみ。式の属性名 #pr, は、ProductReviews の置換です。 attribute_not_exists (#pr.OneStar) # 文字の詳細については、「式の属性名 (p. 213)」を参照してください。 • 単純なスカラー比較である :p は数値を表し、:bt は文字列を表します。 Price <= :p BicycleType = :bt • 2 つの条件はどちらも true でなければなりません。#P と #PC は、Price および ProductCategory 属性名のプレースホルダーです。:lo と :hi は、数値型の値を表してお り、:cat1 と :cat2 は文字列型の値を表しています。 (#P between :lo and :hi) and (#PC in (:cat1, :cat2)) 最初の文字が a-z または A-Z であり、残りの文字 (ある場合) が a-z、A-Z、または 0-9 である場合 は、条件式で任意の属性名を使用できます。属性名がこの要件を満たさない場合は、式の属性名をプ API Version 2012-08-10 216 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み レースホルダーとして定義する必要があります。詳細については、「式の属性名 (p. 213)」を参照し てください。 条件式リファレンス このセクションでは、DynamoDB の条件式の基本的な構成要素について説明します。 Note ConditionExpression の構文は FilterExpression パラメータと同じで す。FilterExpression はデータのクエリ時とスキャン時に使用されます。詳細について は、「クエリまたはスキャンからの結果のフィルタリング (p. 289)」を参照してください。 トピック • 条件式の構文 (p. 217) • 比較の実行 (p. 218) • 関数 (p. 218) • 論理評価 (p. 221) • 括弧 (p. 222) • 条件の優先順位 (p. 222) 条件式の構文 以下の構文の概要で、operand は次のいずれかです。 • 最上位の属性名(Id、Title、Description、ProductCategory など) • 入れ子の属性を参照するドキュメントパス condition-expression ::= operand comparator operand | operand BETWEEN operand AND operand | operand IN ( operand (',' operand (, ...) )) | function | condition AND condition | condition OR condition | NOT condition | ( condition ) comparator ::= = | <> | < | <= | > | >= function ::= attribute_exists (path) | attribute_not_exists (path) | attribute_type (path, type) | begins_with (path, substr) | contains (path, operand) | size (path) API Version 2012-08-10 217 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み 比較の実行 これらのコンパレータを使用して、値の範囲または値の列挙リストに対してオペランドを比較しま す。 • a = b - a が b と等しい場合、true • a <> b - a が b と等しくない場合、true • a < b - a が b より小さい場合、true • a <= b - a が b 以下である場合、true • a > b - a が b より大きい場合、true • a >= b - a が b 以上である場合、true 値の範囲または値の列挙リストに対してオペランドを比較するには、BETWEEN および IN キーワード を使用します。 • a BETWEEN b AND c - a が b 以上で、c 以下である場合、true。 • a IN (b, c, d) - a がリスト内の任意の値(例では、b、c、d のいずれか)と等しい場 合、true。リストには、コンマで区切って最大 100 個の値を指定できます。 関数 以下の関数を使用して、ある属性が項目に存在するか判定したり、属性の値を評価したりします。こ れらの関数名では大文字と小文字が区別されます。入れ子の属性では、フルパスを指定する必要があ ります。詳細については、「ドキュメントパス (p. 212)」を参照してください。 関数 説明 attribute_exists (path) 項目に、path で指定した属性が含まれる場 合、true。 例: Product テーブルの項目に側面図があるかど うかを確認します。 • attribute_exists (Pictures.SideView) attribute_not_exists (path) path で指定した属性が項目に存在しない場 合、true。 例: 項目に Manufacturer 属性があるかどうか を確認します。 • attribute_not_exists (Manufacturer) attribute_type (path, type) 指定したパスの属性が、特定のデータ型のもの である場合、true。type パラメータは次のいず れかである必要があります。 • S — 文字列 • SS — 文字列セット • N — 数値 • NS — 数値セット • B — バイナリ • BS — バイナリセット • BOOL — Boolean API Version 2012-08-10 218 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み 関数 説明 • NULL — Null • L — リスト • M — マップ type パラメータには、式の属性値を使用する必 要があります。 例: QuantityOnHand 属性がリスト型のも のであるかどうかを確認します。この例で は、:v_sub は文字列 L のプレースホルダーで す。 • attribute_type (ProductReviews.FiveStar, :v_sub) 2 番目のパラメータには、式の属性値を使用する 必要があります。 begins_with (path, substr) path で指定された属性が特定のサブ文字列から 始まる場合、true。 例: 正面図 URL の最初の数文字が http:// かど うかを確認します。 • begins_with (Pictures.FrontView, :v_sub) 式の属性値 :v_sub は、http:// のプレースホ ルダ―です。 API Version 2012-08-10 219 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み 関数 説明 contains (path, operand) path で指定された属性が次の属性である場 合、true。 • 特定のサブ文字列を含む文字列。 • 設定の中に特定の要素を含む設定。 いずれの場合でも、operand は文字列である必 要があります。 パスとオペランドは異なっている必要がありま す。つまり contains (a, a) はエラーを返し ます。 例: ブランド属性にサブ文字列 Company が含ま れているかどうかを確認します。 • contains (Brand, :v_sub) 式の属性値 :v_sub は、Company のプレースホ ルダ―です。 例: 製品が赤で入手可能かどうかを確認します。 • contains (Color, :v_sub) 式の属性値 :v_sub は、Red のプレースホルダ― です。 API Version 2012-08-10 220 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み 関数 説明 size (path) 属性のサイズを表す数値を返します。以下 は、size で使用できる有効なデータ型です。 属性は文字列型で、size は文字列の長さを返し ます。 例: 文字列ブランドが 20 文字以下であるかどう かを確認します。式の属性値 :v_sub は、20 の プレースホルダ―です。 • size (Brand) <= :v_sub 属性がバイナリ型の場合、size は属性値のバイ ト数を返します。 例: ProductCatalog 項目に VideoClip という 名前のバイナリ属性があるとします。この属性 には使用中の製品の短いビデオが含まれます。 次の式は、VideoClip が 64,000 バイトを超え るかどうかを確認します。式の属性値 :v_sub は、64000 のプレースホルダ―です。 • size(VideoClip) > :v_sub 属性がセットデータ型の場合、size は設定の要 素数を返します。 例: 製品が複数の色で入手可能かどうかを確認し ます。式の属性値 :v_sub は、1 のプレースホ ルダ―です。 • size (Color) < :v_sub 属性がリスト型またはマップのものである場 合、size は子要素の数を返します。 例: OneStar のレビューの数が特定のしきい値 を超えたかどうかを確認します。式の属性値 :v_sub は、3 のプレースホルダ―です。 • size(ProductReviews.OneStar) > :v_sub 論理評価 論理評価を実行するには、AND、OR、NOT キーワードを使用します。以下のリストでは、a と b は評 価される条件を示しています。 • a AND b - a と b の両方が true である場合、true。 • a OR b - a または b のどちらか(または両方)が true の場合、true。 API Version 2012-08-10 221 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み • NOT a - a が false の場合、true。a が true の場合、false。 括弧 論理評価の優先順位を変更するには括弧を使用します。たとえば、条件 a と b が true で、条件 c が false であるとします。次の式は true と評価されます。 • a OR b AND c しかし、条件を括弧で囲むと、それが最初に評価されます。たとえば、次の式は false と評価されま す。 • (a OR b) AND c Note 式では括弧を入れ子にできます。最も内側の括弧が最初に評価されます。 条件の優先順位 DynamoDB では、条件は次の優先順位ルールを使用して左から右に評価されます。 • = <> < <= > >= • IN • BETWEEN • attribute_exists attribute_not_exists begins_with contains • 括弧 • NOT • AND • OR 更新式を使用した項目および属性の変更 テーブルから項目を削除するには、DeleteItem オペレーションを使用します。削除する項目のキー を指定する必要があります。 テーブルの既存の項目を更新するには、UpdateItem オペレーションを使用します。更新する項目の キーを指定する必要があります。また、変更する属性を示す更新式と、その式に割り当てる値も指定 する必要があります。詳細については、「更新式 (p. 223)」を参照してください。 DeleteItem および UpdateItem オペレーションは条件付き書き込みをサポートします。条件付き 書き込みでは、条件式を指定して、オペレーションが成功するために満たす必要がある条件を示しま す。詳細については、「条件付き書き込みオペレーション (p. 227)」を参照してください。 DynamoDB が項目を正常に変更する際は、HTTP 200 ステータスコード(OK)でこれを通知しま す。応答でそれ以上のデータは返されませんが、項目またはその属性を返すようにリクエストするこ とができます。これは、更新前または更新後の表示どおりにリクエストできます。詳細については、 「戻り値 (p. 228)」を参照してください。 Note 以下のセクションの例は、「導入事例: ProductCatalog 項目 (p. 210)」の ProductCatalog 項 目に基づいています。 API Version 2012-08-10 222 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み トピック • 更新式 (p. 223) • 条件付き書き込みオペレーション (p. 227) • 戻り値 (p. 228) 更新式 更新式は、変更する属性を、それらの属性用の新しい値とともに指定します。更新式は、スカラー値 の設定、リストやマップでの要素の削除など、属性を変更する方法も指定します。これは、属性名、 ドキュメントパス、演算子、および関数を含めることができるフリーフォームの文字列です。これに は、属性を変更する方法を示すキーワードも含まれます。 PutItem、UpdateItem、DeleteItem の各オペレーションではプライマリキー値が必要で、その キーを持つ項目のみが変更されます。条件付き更新を実行する場合、更新式と条件式の両方を指定す る必要があります。条件式では、更新が成功するために満たす必要がある条件を指定します。更新式 の構文の概要を次に示します。 update-expression ::= SET set-action , ... | REMOVE remove-action , ... | ADD add-action , ... | DELETE delete-action , ... 更新式は、セクションで構成されます。各セクションは、SET、REMOVE、ADD、または DELETE キー ワードで始まります。これらのいずれのセクションも、任意の順序で更新式に含めることができま す。ただし、各セクションキーワードは 1 回のみ表示できます。同時に複数の属性を変更できます。 更新式のいくつかの例を次に示します。 • SET list[0] = :val1 • REMOVE #m.nestedField1, #m.nestedField2 • ADD aNumber :val2, anotherNumber :val3 • DELETE aSet :val4 以下の例は、複数のセクションを持つ 1 つの更新式を示しています。 • SET list[0] = :val1 REMOVE #m.nestedField1, #m.nestedField2 ADD aNumber :val2, anotherNumber :val3 DELETE aSet :val4 最初の文字が a-z または A-Z であり、2 番目の文字(ある場合)が a-z、A-Z、または 0-9 である場 合は、更新式で任意の属性値を使用できます。属性名がこの要件を満たさない場合は、式の属性名を プレースホルダーとして定義する必要があります。詳細については、「式の属性名 (p. 213)」を参照 してください。 更新式でリテラル値を指定するには、式の属性値を使用します。詳細については、「式の属性 値 (p. 215)」を参照してください。 トピック • Set (p. 224) • REMOVE (p. 225) • ADD (p. 226) • DELETE (p. 227) API Version 2012-08-10 223 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み Set 1 つ以上の属性と値を項目に追加するには、更新式で SET アクションを使用します。これらのいずれ かの属性が既に存在する場合、新しい値で置き換えられます。ただし、SET を使用して、数値型であ る属性を増減することもできます。複数の属性に SET を使用するには、属性をカンマで区切ります。 次の構文の概要について説明します。 • path 要素は、項目へのドキュメントパスです。詳細については、「ドキュメントパス (p. 212)」 を参照してください。 • operand 要素は、項目へのドキュメントパスまたは関数とすることができます。詳細については、 「属性を更新するための関数 (p. 225)」を参照してください。 set-action ::= path = value value ::= operand | operand '+' operand | operand '-' operand operand ::= path | function SET アクションを使用した更新式のいくつかの例を次に示します。 • 以下の例では、Brand および Price 属性を更新します。式の属性値 :b は文字列で、:p は数値で す。 SET Brand = :b, Price = :p • 以下の例では、RelatedItems リストの属性を更新します。式の属性値 :ri は数値です。 SET RelatedItems[0] = :ri • 以下の例では、いくつかのネストされたマップ属性を更新します。式の属性名 #pr は ProductReviews で、属性値 :r1 および :r2 は文字列です。 SET #pr.FiveStar[0] = :r1, #pr.FiveStar[1] = :r2 数値属性の増減 既存の数値属性は増減することができます。これを行うには、+(プラス)および -(マイナス)演算 子を使用します。 以下の例では、項目の Price 値を減らします。式の属性値 :p は数値です。 • SET Price = Price - :p Price を増やすには、代わりに + 演算子を使用します。 リスト要素での SET の使用 SET を使用してリスト要素を更新すると、その要素のコンテンツは、指定した新しいデータで置き換 えられます。要素が既に存在していない場合、SET は配列の末尾に新しい要素を追加します。 API Version 2012-08-10 224 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み 1 つの SET オペレーションに複数の要素を追加すると、要素は要素番号で順にソートされます。たと えば、次のリストを考えてみます。 MyNumbers: { ["Zero","One","Two","Three","Four"] } リストには、要素 [0]、[1]、[2]、[3]、[4] があります。ここでは、SET アクションを使用して 2 つの新しい要素を追加します。 set MyNumbers[8]="Eight", MyNumbers[10] = "Ten" リストには、要素 [0]、[1]、[2]、[3]、[4]、[5]、[6] が、各要素で次のデータとともに含まれ るようになりました。 MyNumbers: { ["Zero","One","Two","Three","Four","Eight","Ten"] } Note リストの末尾に新しい要素が追加され、使用可能な次の要素番号が割り当てられます。 属性を更新するための関数 SET アクションは、次の関数をサポートします。 • if_not_exists (path, operand) - 指定された path で項目が属性を含まない場 合、if_not_exists は operand に評価されます。それ以外の場合は、path に評価されます。こ の関数を使用して、既に項目に存在する属性への上書きを防ぐことができます。 • list_append (operand, operand) – この関数は、追加された新しい要素でリストに対して評 価を実行します。新しい要素がリストに含まれている必要があります。たとえば、2 をリストに追 加するには、オペランドを [2] にします。オペランドの順序を入れ替えて、リストの先頭または末 尾に新しい要素を追加できます。 Important これらの関数名では大文字と小文字は区別されません。 以下に、これらの関数とともに SET アクションを使用するいくつかの例を示します。 • 属性が既に存在する場合、以下の例では何も実行されません。それ以外の場合は、属性がデフォル ト値に設定されます。 SET Price = if_not_exists(Price, 100) • 以下の例では、FiveStar 評価リストに新しい要素を追加します。式の属性名 #pr は ProductReviews で、属性値 :r は 1 つの要素のリストです。リストに以前に 2 つの要素([0] およ び [1])があった場合、新しい要素は [2] になります。 SET #pr.FiveStar = list_append(#pr.FiveStar, :r) • 以下の例では、FiveStar 評価リストに別の要素を追加しますが、今回、要素は [0] でリストの先頭 に追加されます。リストのその他のすべての要素は、1 つずつ変わります。 SET #pr.FiveStar = list_append(:r, #pr.FiveStar) REMOVE 1 つ以上の属性を項目から削除するには、更新式で REMOVE アクションを使用します。複数の REMOVE オペレーションを実行するには、オペレーションをカンマで区切ります。 API Version 2012-08-10 225 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み 更新式の REMOVE の構文の概要を次に示します。唯一のオペランドは、削除する属性のドキュメント パスです。 remove-action ::= path 以下に、REMOVE アクションを使用した更新式の例を示します。 項目から複数の属性が削除されま す。 • REMOVE Title, RelatedItems[2], Pictures.RearView リスト要素での REMOVE の使用 既存のリスト要素を削除すると、残りの要素は変わります。たとえば、次のリストを考えてみます。 • MyNumbers: { ["Zero","One","Two","Three","Four"] } リストには、要素 [0]、[1]、[2]、[3]、[4] があります。ここで、REMOVE アクションを使用して 2 つの要素を削除してみましょう。 • REMOVE MyNumbers[1], MyNumbers[3] 残りの要素は右に移り、要素 [0]、[1]、[2] が、各要素で次のデータとともに残ります。 • MyNumbers: { ["Zero","Two","Four"] } Note REMOVE を使用して、リストの最後の要素以降の存在しない項目を削除しても、何も起こりま せん。これは、削除するデータがないためです。たとえば、次の式は MyNumbers リストに対 して効果がありません。 • REMOVE MyNumbers[11] ADD Important ADD アクションでは、数値とセットデータ型のみがサポートされます。通常は、ADD ではな く SET を使用することをお勧めします。 更新式で ADD アクションを使用して、次のいずれかを行います。 • 属性が既に存在しない場合は、新しい属性とその値を項目に追加します。 • 属性が既に存在する場合、ADD の動作は属性のデータ型によって決まります。 • 属性が数値で、追加する値も数値である場合、値は既存の属性に数学的に追加されます(値が負 の数値である場合は、既存の属性から減算されます)。 • 属性が設定され、追加する値も設定された場合、値は既存のセットに付加されます。 複数の ADD オペレーションを実行するには、オペレーションをカンマで区切ります。 次の構文の概要について説明します。 API Version 2012-08-10 226 Amazon DynamoDB 開発者ガイド 式を使用した項目の読み取りと書き込み • path 要素は、属性へのドキュメントパスです。属性は数値またはセットデータ型である必要があり ます。 • value 要素は、属性に追加する数値(数値データ型の場合)、または属性に付加するセット(セッ トデータ型の場合)です。 add-action ::= path value add アクションを使用した更新式のいくつかの例を次に示します。 • 以下の例では、数値を増やします。式の属性値 :n は数値で、この値は Price に追加されます。 ADD Price :n • 以下の例では、Color セットに 1 つ以上の値を追加します。式の属性値 :c は文字列セットです。 ADD Color :c DELETE Important DELETE アクションは、セットデータ型のみをサポートします。 セットから要素を削除するには、更新式で DELETE アクションを使用します。複数の DELETE オペ レーションを実行するには、オペレーションをカンマで区切ります。 次の構文の概要について説明します。 • path 要素は、属性へのドキュメントパスです。属性はセットデータ型である必要があります。 • value 要素は、セットで削除する要素です。 delete-action ::= path value 以下の例では、DELETE アクションを使用して Color セットから要素を削除します。式の属性値 :c は文字列セットです。 DELETE Color :c 条件付き書き込みオペレーション 条件付き削除を実行するには、条件式とともに DeleteItem オペレーションを使用します。条件式 は、オペレーションが成功するためには true に評価される必要があります。それ以外の場合、オペ レーションは失敗します。 項目を削除したいが、関連項目がない場合のみにするとします。これを行うには、次の式を使用でき ます。 • 条件式: attribute_not_exists(RelatedItems) API Version 2012-08-10 227 Amazon DynamoDB 開発者ガイド 項目の操作 : Java 条件付き更新を実行するには、UpdateItem オペレーションを更新式と条件式の両方とともに使用し ます。条件式は、オペレーションが成功するためには true に評価される必要があります。それ以外の 場合、オペレーションは失敗します。 「:amt」で定義されているように、項目の価格を特定量上げたいが、結果が上限価格を超えない場合 のみにするとします。これは、増加が許可される現在の最大価格を計算し、最大額から増加分 :amt を引くことで行うことができます。結果を :limit として定義し、次の条件式を使用します。 • 条件式: Price <= :limit) • 更新式: SET Price = Price + :amt 項目の正面の写真を設定したいが、その項目が既にそのような写真を持っていない場合のみにする (既存の要素の上書きは避けたい)とします。これを行うには、次の式を使用できます。 • 更新式: SET Pictures.FrontView = :myURL (:myURL は、http://example.com/picture.jpg のような、項目の写真の場所であるとします。) • 条件式: attribute_not_exists(Pictures.FrontView) 戻り値 DeleteItem または UpdateItem オペレーションを実行するときに、DynamoDB はオプションで一 部またはすべての項目を応答で返すことができます。これを行うには、ReturnValues パラメータを 設定します。ReturnValues のデフォルト値は NONE であるため、データは返されません。この動作 は以下のように変更できます。 項目の削除 DeleteItem オペレーションでは、ReturnValues を ALL_OLD に設定できます。この操作を行う と、DynamoDB は、削除オペレーションが発生した前に表示されたように、項目全体を返します。 項目の更新 UpdateItem オペレーションでは、ReturnValues を次のいずれかに設定できます。 • ALL_OLD - 更新の発生前に表示されたように、項目全体が返されます。 • ALL_NEW – 更新後に表示されるように、項目全体が返されます。 • UPDATED_OLD – 更新の発生前に表示されたように、更新した値のみが返されます。 • UPDATED_NEW – 更新後に表示されるように、更新した値のみが返されます。 項目の操作 : Java トピック • 項目の置換 (p. 229) • 項目の取得 (p. 232) • バッチ書き込み: 複数の項目の書き込みおよび削除 (p. 234) • バッチ取得: 複数の項目の取得 (p. 235) • 項目の更新 (p. 236) • 項目の削除 (p. 238) • 例: AWS SDK for Java ドキュメント API を使用した CRUD オペレーション (p. 238) • 例: AWS SDK for Java ドキュメント API を使用したバッチオペレーション (p. 243) • 例: AWS SDK for Java ドキュメント API を使用したバイナリタイプ属性の処理 (p. 247) API Version 2012-08-10 228 Amazon DynamoDB 開発者ガイド 項目の操作 : Java AWS SDK for Java ドキュメント API を使用して、テーブル内の項目に対して、一般的な作成、読み 込み、更新、削除(CRUD)のオペレーションを実行できます。 Note SDK for Java には、オブジェクト永続性モデルも用意されています。このモデルにより、ク ライアント側のクラスを DynamoDB テーブルにマッピングすることができます。この方法 により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java: DynamoDBMapper (p. 78)」を参照してください。 項目の置換 putItem メソッドによって、項目をテーブルに格納します。項目が存在する場合、その項目全体が置 き換えられます。項目全体を置き換える代わりに固有の属性のみを更新する場合は、updateItem メ ソッドを使用できます。詳細については、「項目の更新 (p. 236)」を参照してください。 以下の手順に従ってください: 1. DynamoDB クラスのインスタンスを作成します。 2. 操作対象のテーブルを表すために、Table クラスのインスタンスを作成します。 3. 新しい項目を表す Item クラスのインスタンスを作成します。新しい項目のプライマリキーと属性 を指定する必要があります。 4. 前の手順で作成した Item を使用して、Table オブジェクトの putItem メソッドを呼び出しま す。 次の Java コードスニペットは、前述のタスクの例です。このスニペットでは、ProductCatalog テーブルに新しい自転車項目を書き込みます。(これは、「導入事例: ProductCatalog 項 目 (p. 210)」で説明した項目と同じです)。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); Table table = dynamoDB.getTable("ProductCatalog"); // Build a list of related items List<Number> relatedItems = new ArrayList<Number>(); relatedItems.add(341); relatedItems.add(472); relatedItems.add(649); //Build a map of product pictures Map<String, String> pictures = new HashMap<String, String>(); pictures.put("FrontView", "http://example.com/products/206_front.jpg"); pictures.put("RearView", "http://example.com/products/206_rear.jpg"); pictures.put("SideView", "http://example.com/products/206_left_side.jpg"); //Build a map of product reviews Map<String, List<String>> reviews = new HashMap<String, List<String>>(); List<String> fiveStarReviews = new ArrayList<String>(); fiveStarReviews.add("Excellent! Can't recommend it highly enough! fiveStarReviews.add("Do yourself a favor and buy this"); reviews.put("FiveStar", fiveStarReviews); List<String> oneStarReviews = new ArrayList<String>(); oneStarReviews.add("Terrible product! Do not buy this."); API Version 2012-08-10 229 Buy it!"); Amazon DynamoDB 開発者ガイド 項目の操作 : Java reviews.put("OneStar", oneStarReviews); // Build the item Item item = new Item() .withPrimaryKey("Id", 206) .withString("Title", "20-Bicycle 206") .withString("Description", "206 description") .withString("BicycleType", "Hybrid") .withString("Brand", "Brand-Company C") .withNumber("Price", 500) .withStringSet("Color", new HashSet<String>(Arrays.asList("Red", "Black"))) .withString("ProductCategory", "Bike") .withBoolean("InStock", true) .withNull("QuantityOnHand") .withList("RelatedItems", relatedItems) .withMap("Pictures", pictures) .withMap("Reviews", reviews); // Write the item to the table PutItemOutcome outcome = table.putItem(item); 前の例では、項目はスカラー(文字列、数値、ブール値、Null)、セット(文字列セット)、ドキュ メント型(リスト、マップ)を持っています。 オプションパラメータの指定 必須のパラメータに加え、putItem メソッドにはオプションパラメータも指定できます。 たとえば、以下の Java コードスニペットでは、オプションパラメータを使用して、項目 のアップロード条件を指定します。指定した条件を満たさない場合は、AWS Java SDK が ConditionalCheckFailedExceptionをスローします。このコードスニペットでは、putItem メ ソッドに以下のオプションパラメータを指定します。 • リクエストの条件を定義する ConditionExpression。このスニペットでは、特定の値に等しい ISBN 属性が既存の項目にある場合にのみ同じプライマリキーを持つ既存の項目を置き換えるという 条件を定義します。 • 条件で使用される ExpressionAttributeValues のマップ。この場合、必要な置き換えは 1 つだ けです。条件式のプレースホルダー :val が、実行時に、チェックする実際の ISBN 値に置き換え られます。 以下の例では、これらのオプションパラメータを使用して新しい書籍項目を追加します。 Item item = new Item() .withPrimaryKey("Id", 104) .withString("Title", "Book 104 Title") .withString("ISBN", "444-4444444444") .withNumber("Price", 20) .withStringSet("Authors", new HashSet<String>(Arrays.asList("Author1", "Author2"))); Map<String, Object> expressionAttributeValues = new HashMap<String, Object>(); expressionAttributeValues.put(":val", "444-4444444444"); PutItemOutcome outcome = table.putItem( item, "ISBN = :val", // ConditionExpression parameter API Version 2012-08-10 230 Amazon DynamoDB 開発者ガイド 項目の操作 : Java null, // ExpressionAttributeNames parameter - we're not using it for this example expressionAttributeValues); PutItem および JSON ドキュメント JSON ドキュメントは、DynamoDB テーブルに属性として格納できます。これを行うには、項目 の withJSON メソッドを使用します。このメソッドは、JSON ドキュメントを解析し、各要素を DynamoDB のネイティブデータ型にマッピングします。 特定の製品の注文を処理できるベンダーを含む、次の JSON ドキュメントを格納するとします。 { "V01": { "Name": "Acme Books", "Offices": [ "Seattle" ] }, "V02": { "Name": "New Publishers, Inc.", "Offices": ["London", "New York" ] }, "V03": { "Name": "Better Buy Books", "Offices": [ "Tokyo", "Los Angeles", "Sydney" ] } } withJSON メソッドを使用して、VendorInfo という名前のマップ属性でこれを ProductCatalog テーブルに格納することができます。次の Java コードスニペットはそれを行う方法を示していま す。 // Convert the document into a String. Must escape all double-quotes. String vendorDocument = "{" + " \"V01\": {" + " \"Name\": \"Acme Books\"," + " \"Offices\": [ \"Seattle\" ]" + " }," + " \"V02\": {" + " \"Name\": \"New Publishers, Inc.\"," + " \"Offices\": [ \"London\", \"New York\"" + "]" + "}," + " \"V03\": {" + " \"Name\": \"Better Buy Books\"," + "\"Offices\": [ \"Tokyo\", \"Los Angeles\", \"Sydney\"" + " ]" + " }" + " }"; Item item = new Item() .withPrimaryKey("Id", 210) .withString("Title", "Book 210 Title") .withString("ISBN", "210-2102102102") .withNumber("Price", 30) .withJSON("VendorInfo", vendorDocument); PutItemOutcome outcome = table.putItem(item); API Version 2012-08-10 231 Amazon DynamoDB 開発者ガイド 項目の操作 : Java 項目の取得 単一の項目を取り出すには、Table オブジェクトの getItem メソッドを使用します。以下の手順に 従ってください: 1. DynamoDB クラスのインスタンスを作成します。 2. 操作対象のテーブルを表すために、Table クラスのインスタンスを作成します。 3. Table インスタンスの getItem メソッドを呼び出します。取り出す項目のプライマリキーを指定 する必要があります。 次の Java コードスニペットは、前述のステップを示しています。このコードスニペットでは、指定 したパーティションキーを持つ項目を取得します。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); Table table = dynamoDB.getTable("ProductCatalog"); Item item = table.getItem("Id", 101); オプションパラメータの指定 必須のパラメータに加え、getItem メソッドにはオプションパラメータも指定できます。たとえば、 以下の Java コードスニペットでは、オプションメソッドを使用して、特定の属性リストのみを取り 出します。また、強い整合性のある戻り値をリクエストします。読み込み整合性の詳細については、 「読み込み整合性 (p. 16)」を参照してください。 ProjectionExpression を使用すると、項目全体ではなく特定の属性または要素のみを取り出すこ とができます。ProjectionExpression は、ドキュメントのパスを使用して最上位の属性または入 れ子になった属性を指定できます。詳細については、プロジェクション式 (p. 211) および ドキュメ ントパス (p. 212) を参照してください。 getItem メソッドのパラメーターでは、読み込み整合性を指定することはできません。ただし、すべ ての低レベル GetItem オペレーションの入力へのフルアクセスを提供する GetItemSpec を作成で きます。 以下のコード例では、GetItemSpec を作成し、その仕様を getItem メソッドへの入力と して使用します。 GetItemSpec spec = new GetItemSpec() .withPrimaryKey("Id", 206) .withProjectionExpression("Id, Title, RelatedItems[0], Reviews.FiveStar") .withConsistentRead(true); Item item = table.getItem(spec); System.out.println(item.toJSONPretty()); Tip Item を人間が読める形式で出力するには、toJSONPretty メソッドを使用します。上の例に よる出力は次のようになります。 { "RelatedItems" : [ 341 ], "Reviews" : { API Version 2012-08-10 232 Amazon DynamoDB 開発者ガイド 項目の操作 : Java "FiveStar" : [ "Excellent! Can't recommend it highly enough! it!", "Do yourself a favor and buy this" ] }, "Id" : 206, "Title" : "20-Bicycle 206" Buy } GetItem および JSON ドキュメント PutItem および JSON ドキュメント (p. 231) セクションでは、VendorInfo という名前のマップ属 性に JSON ドキュメントを格納しました。getItem メソッドを使用して JSON 形式のドキュメント 全体を取り出すか、ドキュメントパス表記を使用してドキュメント内の一部の要素のみ取り出しま す。次の Java コードスニペットは、この手法を示しています。 GetItemSpec spec = new GetItemSpec() .withPrimaryKey("Id", 210); System.out.println("All vendor info:"); spec.withProjectionExpression("VendorInfo"); System.out.println(table.getItem(spec).toJSON()); System.out.println("A single vendor:"); spec.withProjectionExpression("VendorInfo.V03"); System.out.println(table.getItem(spec).toJSON()); System.out.println("First office location for this vendor:"); spec.withProjectionExpression("VendorInfo.V03.Offices[0]"); System.out.println(table.getItem(spec).toJSON()); 上の例による出力は次のようになります。 All vendor info: {"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los Angeles","Sydney"]},"V02":{"Name":"New Publishers, Inc.","Offices": ["London","New York"]},"V01":{"Name":"Acme Books","Offices":["Seattle"]}}} A single vendor: {"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los Angeles","Sydney"]}}} First office location for a single vendor: {"VendorInfo":{"V03":{"Offices":["Tokyo"]}}} Tip toJSON メソッドを使用して、任意の項目(またはその属性)を JSON 形式文字列に変 換できます。次のコードスニペットは、最上位の属性と入れ子になった属性を複数取り出 し、JSON として結果を出力します。 GetItemSpec spec = new GetItemSpec() .withPrimaryKey("Id", 210) .withProjectionExpression("VendorInfo.V01, Title, Price"); Item item = table.getItem(spec); System.out.println(item.toJSON()); API Version 2012-08-10 233 Amazon DynamoDB 開発者ガイド 項目の操作 : Java 出力は次のようになります。 {"VendorInfo":{"V01":{"Name":"Acme Books","Offices": ["Seattle"]}},"Price":30,"Title":"Book 210 Title"} バッチ書き込み: 複数の項目の書き込みおよび削除 バッチ書き込みは、複数の項目の書き込みと削除をバッチで行うことを意味しま す。batchWriteItem メソッドによって、単一の コール内にある 1 つまたは複数のテーブルから複 数の項目を置換および削除できます。以下に、AWS SDK for Java ドキュメント API を使用して複数 の項目を入力および削除する手順を示します。 1. DynamoDB クラスのインスタンスを作成します。 2. テーブルのすべての入力および削除オペレーションを記述する TableWriteItems クラスのイン スタンスを作成します。1 つのバッチ書き込みオペレーションで複数のテーブルに書き込む場合、 テーブルごとに TableWriteItems インスタンスを 1 つずつ作成する必要があります。 3. 前の手順で作成した TableWriteItems オブジェクトを指定して、batchWriteItem メソッドを 呼び出します。 4. 応答を処理します。返された未処理のリクエスト項目が応答内に存在していたかどうかをチェック する必要があります。これは、プロビジョニングされたスループットの制限または他の何らかの一 時的エラーに達する場合に、発生する可能性があります。また、DynamoDB によって、リクエスト のサイズ、およびリクエスト内で指定できるオペレーションの数が制限されます。これらの制限を 超えると、DynamoDB によってリクエストが却下されます。詳細については、「DynamoDB での 制限 (p. 558)」を参照してください。 次の Java コードスニペットは、前述のステップを示しています。この例では、2 つのテーブル (Forum と Thread)で batchWriteItem オペレーションを実行します。対応する TableWriteItems オブジェクトは、次のアクションを定義します。 • Forum テーブル内で項目を入力 • Thread テーブル内で項目を入力および削除 その後、コードは batchWriteItem を呼び出してオペレーションを実行します。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); TableWriteItems forumTableWriteItems = new TableWriteItems("Forum") .withItemsToPut( new Item() .withPrimaryKey("Name", "Amazon RDS") .withNumber("Threads", 0)); TableWriteItems threadTableWriteItems = new TableWriteItems(Thread) .withItemsToPut( new Item() .withPrimaryKey("ForumName","Amazon RDS","Subject","Amazon RDS Thread 1") .withHashAndRangeKeysToDelete("ForumName","Some partition key value", "Amazon S3", "Some sort key value"); BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(forumTableWriteItems, threadTableWriteItems); API Version 2012-08-10 234 Amazon DynamoDB 開発者ガイド 項目の操作 : Java // Code for checking unprocessed items is omitted in this example 実例については、「例: AWS SDK for Java ドキュメント API を使用したバッチ書き込みオペレーショ ン (p. 243)」を参照してください。 バッチ取得: 複数の項目の取得 batchGetItem メソッドによって、1 つまたは複数のテーブルから複数の項目を取得できます。単一 の項目を取り出すために、getItem メソッドを使用できます。 以下の手順に従ってください: 1. DynamoDB クラスのインスタンスを作成します。 2. テーブルから取り出すプライマリキーのリストを記述する TableKeysAndAttributes クラスの インスタンスを作成します。1 つのバッチ取得オペレーションで複数のテーブルから読み込む場 合、テーブルごとに TableKeysAndAttributes インスタンスを 1 つずつ作成する必要がありま す。 3. 前の手順で作成した TableKeysAndAttributes オブジェクトを指定して、batchGetItem メ ソッドを呼び出します。 次の Java コードスニペットは、前述のステップを示しています。この例では、Forum テーブル内の 2 つの項目、および Thread テーブル内の 3 つの項目を取り出します。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes(forumTableName); forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name", "Amazon S3", "Amazon DynamoDB"); TableKeysAndAttributes threadTableKeysAndAttributes = new TableKeysAndAttributes(threadTableName); threadTableKeysAndAttributes.addHashAndRangePrimaryKeys("ForumName", "Subject", "Amazon DynamoDB","DynamoDB Thread 1", "Amazon DynamoDB","DynamoDB Thread 2", "Amazon S3","S3 Thread 1"); BatchGetItemOutcome outcome = dynamoDB.batchGetItem( forumTableKeysAndAttributes, threadTableKeysAndAttributes); for (String tableName : outcome.getTableItems().keySet()) { System.out.println("Items in table " + tableName); List<Item> items = outcome.getTableItems().get(tableName); for (Item item : items) { System.out.println(item); } } オプションパラメータの指定 必須のパラメータに加え、batchGetItem を使用する場合はオプションパラメータも指定できます。 たとえば、定義した TableKeysAndAttributes ごとに ProjectionExpression を指定できま す。これにより、テーブルから取り出す属性を指定することができます。 API Version 2012-08-10 235 Amazon DynamoDB 開発者ガイド 項目の操作 : Java 次のコードスニペットでは、Forum テーブルの 2 つの項目を取り出しま す。withProjectionExpression パラメータは、Threads 属性のみを取得することを指定しま す。 TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes("Forum") .withProjectionExpression("Threads"); forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name", "Amazon S3", "Amazon DynamoDB"); BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes); 項目の更新 Table オブジェクトの updateItem メソッドは、既存の属性値の更新、新しい属性の追加、または既 存の項目からの属性の削除を実行できます。 updateItem メソッドは、以下のように動作します。 • 項目が存在しない(指定されたプライマリキーを持つ項目がテーブル内にない)場 合、updateItem はテーブルに新しい項目を追加します • 項目が存在する場合、updateItem は UpdateExpression パラメータで指定されたとおりに更新 を実行します。 Note putItem を使用して項目を「更新」することもできます。たとえば、putItem を呼び出して 項目をテーブルに追加したが、指定されたプライマリーキーを持つ項目がすでに存在する場 合、putItem は項目全体を置き換えます。入力で指定されていない属性が既存の項目内にあ る場合、putItem は項目からそれらの属性を削除します。 一般に、項目属性を変更するときは必ず updateItem を使用することをお勧めしま す。updateItem メソッドは、入力で指定した項目属性のみを変更し、項目内の他の属性は 変更されません。 以下の手順に従ってください: 1. 操作対象のテーブルを表すために、Table クラスのインスタンスを作成します。 2. Table インスタンスの updateTable メソッドを呼び出します。変更する属性とその変更方法を記 述する UpdateExpression と同時に、取り出す項目のプライマリーキーを指定する必要がありま す。 次の Java コードスニペットは、前述のタスクの例です。このスニペットでは、ProductCatalog テー ブルで書籍項目を更新します。この例では、Authors のセットに著者を追加し、既存の ISBN 属性を削 除します。また、価格を 1 引き下げます。 ExpressionAttributeValues マップは UpdateExpression で使用されます。プレースホルダー :val1 および :val2 は、実行時に、Authors と Price の実際の値に置き換えられます。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); Table table = dynamoDB.getTable("ProductCatalog"); API Version 2012-08-10 236 Amazon DynamoDB 開発者ガイド 項目の操作 : Java Map<String, String> expressionAttributeNames = new HashMap<String, String>(); expressionAttributeNames.put("#A", "Authors"); expressionAttributeNames.put("#P", "Price"); expressionAttributeNames.put("#I", "ISBN"); Map<String, Object> expressionAttributeValues = new HashMap<String, Object>(); expressionAttributeValues.put(":val1", new HashSet<String>(Arrays.asList("Author YY","Author ZZ"))); expressionAttributeValues.put(":val2", 1); //Price UpdateItemOutcome outcome = table.updateItem( "Id", // key attribute name 101, // key attribute value "add #A :val1 set #P = #P - :val2 remove #I", // UpdateExpression expressionAttributeNames, expressionAttributeValues); オプションパラメータの指定 必須のパラメータに加えて、更新を実行するために満たす必要がある条件も含めて、updateItem メ ソッドのオプションパラメータを指定することもできます。指定した条件を満たさない場合は、AWS Java SDK が ConditionalCheckFailedExceptionをスローします。たとえば、以下の Java コー ドスニペットでは、書籍項目の価格を条件付きで 25 に更新します。現在の価格が 20 である場合にの み価格を更新する必要があることを示す ConditionExpression を指定します。 Table table = dynamoDB.getTable("ProductCatalog"); Map<String, String> expressionAttributeNames = new HashMap<String, String>(); expressionAttributeNames.put("#P", "Price"); Map<String, Object> expressionAttributeValues = new HashMap<String, Object>(); expressionAttributeValues.put(":val1", 25); // update Price to 25... expressionAttributeValues.put(":val2", 20); //...but only if existing Price is 20 UpdateItemOutcome outcome = table.updateItem( new PrimaryKey("Id",101), "set #P = :val1", // UpdateExpression "#P = :val2", // ConditionExpression expressionAttributeNames, expressionAttributeValues); アトミックカウンター updateItem を使用してアトミックカウンターを実装できます。アトミックカウンターでは、他の書 き込みリクエストを妨げることなく、既存の属性の値をインクリメントまたはデクリメントします。 アトミックカウンターをインクリメントするには、UpdateExpression を使用して、set アクショ ンで既存の数値型の属性に数値を加算します。 次のコード例はアトミックカウンターを示しており、Quantity 属性を 1 ずつインクリメントさせてい ます。さらに、UpdateExpression での ExpressionAttributeNames パラメータの使用方法も示 します。 Table table = dynamoDB.getTable("ProductCatalog"); API Version 2012-08-10 237 Amazon DynamoDB 開発者ガイド 項目の操作 : Java Map<String,String> expressionAttributeNames = new HashMap<String,String>(); expressionAttributeNames.put("#p", "PageCount"); Map<String,Object> expressionAttributeValues = new HashMap<String,Object>(); expressionAttributeValues.put(":val", 1); UpdateItemOutcome outcome = table.updateItem( "Id", 121, "set #p = #p + :val", expressionAttributeNames, expressionAttributeValues); 項目の削除 deleteItem メソッドによって、テーブルから項目を削除します。削除する項目のプライマリキーを 指定する必要があります。 以下の手順に従ってください: 1. DynamoDB クライアントのインスタンスを作成します。 2. 削除する項目のキーを指定して、deleteItem メソッドを呼び出します。 次の Java コードスニペットは、このタスクを示しています。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); Table table = dynamoDB.getTable("ProductCatalog"); DeleteItemOutcome outcome = table.deleteItem("Id", 101); オプションパラメータの指定 deleteItem のオプションパラメータを指定できます。たとえば、次の Java コードスニペット は、ProductCatalog 内の書籍項目は書籍が絶版になった(InPublication 属性が false)場合のみ削 除可能であることを示す ConditionExpression を指定します。 Map<String,Object> expressionAttributeValues = new HashMap<String,Object>(); expressionAttributeValues.put(":val", false); DeleteItemOutcome outcome = table.deleteItem("Id",103, "InPublication = :val", null, // ExpressionAttributeNames - not used in this example expressionAttributeValues); 例: AWS SDK for Java ドキュメント API を使用した CRUD オ ペレーション 以下のコード例は、項目に対する CRUD オペレーションの例です。 この例では、項目の作成、項目 の取得、さまざまな更新の実行、さらに項目の削除を行います。 Note SDK for Java には、オブジェクト永続性モデルも用意されています。このモデルにより、ク ライアント側のクラスを DynamoDB テーブルにマッピングすることができます。この方法 API Version 2012-08-10 238 Amazon DynamoDB 開発者ガイド 項目の操作 : Java により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java: DynamoDBMapper (p. 78)」を参照してください。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。 以下の例を実行するための詳しい手順については、「Java コードサンプル (p. 171)」を参照 してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import import import import import java.io.IOException; java.util.Arrays; java.util.HashMap; java.util.HashSet; java.util.Map; import import import import import import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.Table; com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome; com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec; com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec; com.amazonaws.services.dynamodbv2.document.utils.NameMap; com.amazonaws.services.dynamodbv2.document.utils.ValueMap; com.amazonaws.services.dynamodbv2.model.ReturnValue; public class DocumentAPIItemCRUDExample { static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); static String tableName = "ProductCatalog"; public static void main(String[] args) throws IOException { createItems(); retrieveItem(); // Perform various updates. updateMultipleAttributes(); updateAddNewAttribute(); updateExistingAttributeConditionally(); // Delete the item. deleteItem(); API Version 2012-08-10 239 Amazon DynamoDB 開発者ガイド 項目の操作 : Java } private static void createItems() { Table table = dynamoDB.getTable(tableName); try { Item item = new Item() .withPrimaryKey("Id", 120) .withString("Title", "Book 120 Title") .withString("ISBN", "120-1111111111") .withStringSet( "Authors", new HashSet<String>(Arrays.asList("Author12", "Author22"))) .withNumber("Price", 20) .withString("Dimensions", "8.5x11.0x.75") .withNumber("PageCount", 500) .withBoolean("InPublication", false) .withString("ProductCategory", "Book"); table.putItem(item); item = new Item() .withPrimaryKey("Id", 121) .withString("Title", "Book 121 Title") .withString("ISBN", "121-1111111111") .withStringSet( "Authors", new HashSet<String>(Arrays.asList("Author21", "Author 22"))) .withNumber("Price", 20) .withString("Dimensions", "8.5x11.0x.75") .withNumber("PageCount", 500) .withBoolean("InPublication", true) .withString("ProductCategory", "Book"); table.putItem(item); } catch (Exception e) { System.err.println("Create items failed."); System.err.println(e.getMessage()); } } private static void retrieveItem() { Table table = dynamoDB.getTable(tableName); try { Item item = table.getItem("Id", 120, "Id, ISBN, Title, Authors", null); System.out.println("Printing item after retrieving it...."); System.out.println(item.toJSONPretty()); } catch (Exception e) { System.err.println("GetItem failed."); System.err.println(e.getMessage()); } } API Version 2012-08-10 240 Amazon DynamoDB 開発者ガイド 項目の操作 : Java private static void updateAddNewAttribute() { Table table = dynamoDB.getTable(tableName); try { Map<String, String> expressionAttributeNames = new HashMap<String, String>(); expressionAttributeNames.put("#na", "NewAttribute"); UpdateItemSpec updateItemSpec = new UpdateItemSpec() .withPrimaryKey("Id", 121) .withUpdateExpression("set #na = :val1") .withNameMap(new NameMap() .with("#na", "NewAttribute")) .withValueMap(new ValueMap() .withString(":val1", "Some value")) .withReturnValues(ReturnValue.ALL_NEW); UpdateItemOutcome outcome = table.updateItem(updateItemSpec); // Check the response. System.out.println("Printing item after adding new attribute..."); System.out.println(outcome.getItem().toJSONPretty()); } catch (Exception e) { System.err.println("Failed to add new attribute in " + tableName); System.err.println(e.getMessage()); } } private static void updateMultipleAttributes() { Table table = dynamoDB.getTable(tableName); try { UpdateItemSpec updateItemSpec = new UpdateItemSpec() .withPrimaryKey("Id", 120) .withUpdateExpression("add #a :val1 set #na=:val2") .withNameMap(new NameMap() .with("#a", "Authors") .with("#na", "NewAttribute")) .withValueMap(new ValueMap() .withStringSet(":val1", "Author YY", "Author ZZ") .withString(":val2", "someValue")) .withReturnValues(ReturnValue.ALL_NEW); UpdateItemOutcome outcome = table.updateItem(updateItemSpec); // Check the response. System.out .println("Printing item after multiple attribute update..."); System.out.println(outcome.getItem().toJSONPretty()); } catch (Exception e) { System.err.println("Failed to update multiple attributes in " API Version 2012-08-10 241 Amazon DynamoDB 開発者ガイド 項目の操作 : Java + tableName); System.err.println(e.getMessage()); } } private static void updateExistingAttributeConditionally() { Table table = dynamoDB.getTable(tableName); try { // Specify the desired price (25.00) and also the condition (price = // 20.00) UpdateItemSpec updateItemSpec = new UpdateItemSpec() .withPrimaryKey("Id", 120) .withReturnValues(ReturnValue.ALL_NEW) .withUpdateExpression("set #p = :val1") .withConditionExpression("#p = :val2") .withNameMap(new NameMap() .with("#p", "Price")) .withValueMap(new ValueMap() .withNumber(":val1", 25) .withNumber(":val2", 20)); UpdateItemOutcome outcome = table.updateItem(updateItemSpec); // Check the response. System.out .println("Printing item after conditional update to new attribute..."); System.out.println(outcome.getItem().toJSONPretty()); } catch (Exception e) { System.err.println("Error updating item in " + tableName); System.err.println(e.getMessage()); } } private static void deleteItem() { Table table = dynamoDB.getTable(tableName); try { DeleteItemSpec deleteItemSpec = new DeleteItemSpec() .withPrimaryKey("Id", 120) .withConditionExpression("#ip = :val") .withNameMap(new NameMap() .with("#ip", "InPublication")) .withValueMap(new ValueMap() .withBoolean(":val", false)) .withReturnValues(ReturnValue.ALL_OLD); DeleteItemOutcome outcome = table.deleteItem(deleteItemSpec); // Check the response. API Version 2012-08-10 242 Amazon DynamoDB 開発者ガイド 項目の操作 : Java System.out.println("Printing item that was deleted..."); System.out.println(outcome.getItem().toJSONPretty()); } catch (Exception e) { System.err.println("Error deleting item in " + tableName); System.err.println(e.getMessage()); } } } 例: AWS SDK for Java ドキュメント API を使用したバッチオ ペレーション トピック • 例: AWS SDK for Java ドキュメント API を使用したバッチ書き込みオペレーション (p. 243) • 例: AWS SDK for Java ドキュメント API を使用したバッチ取得オペレーション (p. 245) このセクションでは、AWS SDK for Java ドキュメント API を使用したバッチ書き込みおよびバッチ 取得オペレーションの例を示します。 Note SDK for Java には、オブジェクト永続性モデルも用意されています。このモデルにより、ク ライアント側のクラスを DynamoDB テーブルにマッピングすることができます。この方法 により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java: DynamoDBMapper (p. 78)」を参照してください。 例: AWS SDK for Java ドキュメント API を使用したバッチ書き込みオペレー ション 以下の Java コード例では、batchWriteItem メソッドを使用して、以下の置換および削除のオペ レーションを実行します。 • Forum テーブル内で 1 つの項目を置換 • Thread テーブルに対して 1 つの項目を置換および削除 バッチの書き込みリクエストを作成すると、1 つまたは複数のテーブルに対して多数の置換リクエス トと削除リクエストを指定できます。ただし、batchWriteItem では、1 回のバッチ書き込みオペ レーションで可能なバッチ書き込みリクエストのサイズ、置換および削除のオペレーションの数を制 限しています。 これらの制限を超えるリクエストは却下されます。プロビジョニングされたスルー プットがテーブルに不足しているためにこのリクエストを処理できない場合は、応答時に未処理のリ クエスト項目が返されます。 以下の例では、未処理のリクエスト項目がないか、応答を確認します。未処理のリクエスト項目があ る場合は、batchWriteItem リクエストをループバックして再送信します。「テーブルの作成とサン プルデータのロード (p. 166)」セクションの手順に従っていれば、Forum テーブルと Thread テーブル は作成済みです。プログラムで、これらのテーブルを作成し、サンプルデータをアップロードするこ ともできます。詳細については、「AWS SDK for Java を使用した、サンプルテーブルの作成とデー タのアップロード (p. 600)」を参照してください。 次のサンプルをテストするための詳しい手順については、「Java コードサンプル (p. 171)」を参照し てください。 API Version 2012-08-10 243 Amazon DynamoDB 開発者ガイド 項目の操作 : Java // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import import import import import java.io.IOException; java.util.Arrays; java.util.HashSet; java.util.List; java.util.Map; import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.BatchWriteItemOutcome; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.TableWriteItems; com.amazonaws.services.dynamodbv2.model.WriteRequest; public class DocumentAPIBatchWrite { static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); static String forumTableName = "Forum"; static String threadTableName = "Thread"; public static void main(String[] args) throws IOException { writeMultipleItemsBatchWrite(); } private static void writeMultipleItemsBatchWrite() { try { // Add a new item to Forum TableWriteItems forumTableWriteItems = new TableWriteItems(forumTableName) //Forum .withItemsToPut(new Item() .withPrimaryKey("Name", "Amazon RDS") .withNumber("Threads", 0)); // Add a new item, and delete an existing item, from Thread // This table has a partition key and range key, so need to specify both of them TableWriteItems threadTableWriteItems = new TableWriteItems(threadTableName) .withItemsToPut(new Item() .withPrimaryKey("ForumName","Amazon RDS","Subject","Amazon RDS Thread 1") .withString("Message", "ElastiCache Thread 1 message") .withStringSet("Tags", new HashSet<String>( Arrays.asList("cache", "in-memory")))) .withHashAndRangeKeysToDelete("ForumName","Subject", "Amazon S3", "S3 Thread 100"); System.out.println("Making the request."); API Version 2012-08-10 244 Amazon DynamoDB 開発者ガイド 項目の操作 : Java BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(forumTableWriteItems, threadTableWriteItems); do { // Check for unprocessed keys which could happen if you exceed provisioned throughput Map<String, List<WriteRequest>> unprocessedItems = outcome.getUnprocessedItems(); if (outcome.getUnprocessedItems().size() == 0) { System.out.println("No unprocessed items found"); } else { System.out.println("Retrieving the unprocessed items"); outcome = dynamoDB.batchWriteItemUnprocessed(unprocessedItems); } } while (outcome.getUnprocessedItems().size() > 0); } catch (Exception e) { System.err.println("Failed to retrieve items: "); e.printStackTrace(System.err); } } } 例: AWS SDK for Java ドキュメント API を使用したバッチ取得オペレーショ ン 以下の Java コード例では、batchGetItem メソッドを使用して、Forum テーブルおよび Thread テーブルから複数の項目を取り出します。BatchGetItemRequest は、取得する各項目のテーブル名 とキーのリストを指定します。この例では、取得した項目を印刷して応答を処理します。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。 以下の例を実行するための詳しい手順については、「Java コードサンプル (p. 171)」を参照 してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import java.io.IOException; import java.util.List; import java.util.Map; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; API Version 2012-08-10 245 Amazon DynamoDB 開発者ガイド 項目の操作 : Java import import import import import com.amazonaws.services.dynamodbv2.document.BatchGetItemOutcome; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.TableKeysAndAttributes; com.amazonaws.services.dynamodbv2.model.KeysAndAttributes; public class DocumentAPIBatchGet { static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); static String forumTableName = "Forum"; static String threadTableName = "Thread"; public static void main(String[] args) throws IOException { retrieveMultipleItemsBatchGet(); } private static void retrieveMultipleItemsBatchGet() { try { TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes(forumTableName); //Add a partition key forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name", "Amazon S3", "Amazon DynamoDB"); TableKeysAndAttributes threadTableKeysAndAttributes = new TableKeysAndAttributes(threadTableName); //Add a partition key and a sort key threadTableKeysAndAttributes.addHashAndRangePrimaryKeys("ForumName", "Subject", "Amazon DynamoDB","DynamoDB Thread 1", "Amazon DynamoDB","DynamoDB Thread 2", "Amazon S3","S3 Thread 1"); System.out.println("Making the request."); BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes, threadTableKeysAndAttributes); Map<String, KeysAndAttributes> unprocessed = null; do { for (String tableName : outcome.getTableItems().keySet()) { System.out.println("Items in table " + tableName); List<Item> items = outcome.getTableItems().get(tableName); for (Item item : items) { System.out.println(item.toJSONPretty()); } } // Check for unprocessed keys which could happen if you exceed provisioned API Version 2012-08-10 246 Amazon DynamoDB 開発者ガイド 項目の操作 : Java // throughput or reach the limit on response size. unprocessed = outcome.getUnprocessedKeys(); if (unprocessed.isEmpty()) { System.out.println("No unprocessed keys found"); } else { System.out.println("Retrieving the unprocessed keys"); outcome = dynamoDB.batchGetItemUnprocessed(unprocessed); } } while (!unprocessed.isEmpty()); } catch (Exception e) { System.err.println("Failed to retrieve items."); System.err.println(e.getMessage()); } } } 例: AWS SDK for Java ドキュメント API を使用したバイナリ タイプ属性の処理 以下の Java コード例は、バイナリタイプ属性の処理の例です。この例では、Reply テーブルに項目 を追加します。この項目には、圧縮データを格納するバイナリタイプ属性(ExtendedMessage)な どがあります。また、この例では、項目を取得し、すべての属性値を印刷します。説明のため、こ の例では GZIPOutputStream クラスを使用して、サンプルストリームを圧縮し、圧縮したデータを ExtendedMessage 属性に割り当てます。バイナリ属性が取得されると、GZIPInputStream クラス を使用して展開されます。 Note SDK for Java には、オブジェクト永続性モデルも用意されています。このモデルにより、ク ライアント側のクラスを DynamoDB テーブルにマッピングすることができます。この方法 により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java: DynamoDBMapper (p. 78)」を参照してください。 「テーブルの作成とサンプルデータのロード (p. 166)」セクションの手順に従っていれば、Reply テー ブルは作成済みです。このテーブルは、プログラムで作成することもできます。詳細については、 「AWS SDK for Java を使用した、サンプルテーブルの作成とデータのアップロード (p. 600)」を参 照してください。 次のサンプルをテストするための詳しい手順については、「Java コードサンプル (p. 171)」を参照し てください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import import import import java.io.ByteArrayInputStream; java.io.ByteArrayOutputStream; java.io.IOException; java.nio.ByteBuffer; API Version 2012-08-10 247 Amazon DynamoDB 開発者ガイド 項目の操作 : Java import import import import import java.text.SimpleDateFormat; java.util.Date; java.util.TimeZone; java.util.zip.GZIPInputStream; java.util.zip.GZIPOutputStream; import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.Table; com.amazonaws.services.dynamodbv2.document.spec.GetItemSpec; public class DocumentAPIItemBinaryExample { static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); static String tableName = "Reply"; static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MMdd'T'HH:mm:ss.SSS'Z'"); public static void main(String[] args) throws IOException { try { // Format the primary key values String threadId = "Amazon DynamoDB#DynamoDB Thread 2"; dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); String replyDateTime = dateFormatter.format(new Date()); // Add a new reply with a binary attribute type createItem(threadId, replyDateTime); // Retrieve the reply with a binary attribute type retrieveItem(threadId, replyDateTime); // clean up by deleting the item deleteItem(threadId, replyDateTime); } catch (Exception e) { System.err.println("Error running the binary attribute type example: " + e); e.printStackTrace(System.err); } } public static void createItem(String threadId, String replyDateTime) throws IOException { Table table = dynamoDB.getTable(tableName); // Craft a long message String messageInput = "Long message to be compressed in a lengthy forum reply"; // Compress the long message ByteBuffer compressedMessage = compressString(messageInput.toString()); API Version 2012-08-10 248 Amazon DynamoDB 開発者ガイド 項目の操作 : Java table.putItem(new Item() .withPrimaryKey("Id", threadId) .withString("ReplyDateTime", replyDateTime) .withString("Message", "Long message follows") .withBinary("ExtendedMessage", compressedMessage) .withString("PostedBy", "User A")); } public static void retrieveItem(String threadId, String replyDateTime) throws IOException { Table table = dynamoDB.getTable(tableName); GetItemSpec spec = new GetItemSpec() .withPrimaryKey("Id", threadId, "ReplyDateTime", replyDateTime) .withConsistentRead(true); Item item = table.getItem(spec); // Uncompress the reply message and print String uncompressed = uncompressString(ByteBuffer.wrap(item.getBinary("ExtendedMessage"))); System.out.println("Reply message:\n" + " Id: " + item.getString("Id") + "\n" + " ReplyDateTime: " + item.getString("ReplyDateTime") + "\n" + " PostedBy: " + item.getString("PostedBy") + "\n" + " Message: " + item.getString("Message") + "\n" + " ExtendedMessage (uncompressed): " + uncompressed + "\n"); } public static void deleteItem(String threadId, String replyDateTime) { Table table = dynamoDB.getTable(tableName); table.deleteItem("Id", threadId, "ReplyDateTime", replyDateTime); } private static ByteBuffer compressString(String input) throws IOException { // Compress the UTF-8 encoded String into a byte[] ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPOutputStream os = new GZIPOutputStream(baos); os.write(input.getBytes("UTF-8")); os.close(); baos.close(); byte[] compressedBytes = baos.toByteArray(); // The following code writes the compressed bytes to a ByteBuffer. // A simpler way to do this is by simply calling ByteBuffer.wrap(compressedBytes); // However, the longer form below shows the importance of resetting the position of the buffer // back to the beginning of the buffer if you are writing bytes directly to it, since the SDK // will consider only the bytes after the current position when sending data to DynamoDB. // Using the "wrap" method automatically resets the position to zero. API Version 2012-08-10 249 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET ByteBuffer buffer = ByteBuffer.allocate(compressedBytes.length); buffer.put(compressedBytes, 0, compressedBytes.length); buffer.position(0); // Important: reset the position of the ByteBuffer to the beginning return buffer; } private static String uncompressString(ByteBuffer input) throws IOException { byte[] bytes = input.array(); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPInputStream is = new GZIPInputStream(bais); int chunkSize = 1024; byte[] buffer = new byte[chunkSize]; int length = 0; while ((length = is.read(buffer, 0, chunkSize)) != -1) { baos.write(buffer, 0, length); } String result = new String(baos.toByteArray(), "UTF-8"); is.close(); baos.close(); bais.close(); return result; } } 項目の操作 : .NET トピック • 項目の置換 (p. 251) • 項目の取得 (p. 252) • 項目の更新 (p. 253) • アトミックカウンター (p. 255) • 項目の削除 (p. 256) • バッチ書き込み: 複数の項目の書き込みおよび削除 (p. 257) • バッチ取得: 複数の項目の取得 (p. 259) • 例: AWS SDK for .NET の低レベル API を使用した CRUD オペレーション (p. 261) • 例: AWS SDK for .NET の低レベル API を使用した、バッチオペレーション (p. 265) • 例: AWS SDK for .NET の低レベル API を使用した、バイナリタイプ属性の処理 (p. 271) AWS SDK for .NET 低レベル API を使用して、テーブル内の項目に対して、一般的な作成、読み込 み、更新、削除(CRUD)のオペレーションを実行できます。 以下に、.NET の低レベル API を使用してデータ CRUD オペレーションを実行する手順を示します。 1. AmazonDynamoDBClient クラスのインスタンス(クライアント)を作成します。 2. 対応するリクエストオブジェクト内に、オペレーション固有の必須パラメータを指定します。 たとえば、項目をアップロードするには PutItemRequest リクエストオブジェクトを使用し、既 存の項目を取り出すには GetItemRequest リクエストオブジェクトを使用します。 API Version 2012-08-10 250 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET リクエストオブジェクトを使用して、必須パラメータとオプションパラメータの両方を指定できま す。 3. 前の手順で作成したリクエストオブジェクト内でパスすることにより、クライアントから提供され た適切なメソッドを実行します。 AmazonDynamoDBClient クライアントは、CRUD オペレーション用のメソッドとし て、PutItem、GeItem、UpdateItem、DeleteItem を提供します。 項目の置換 PutItem メソッドによって、項目をテーブルにアップロードします。項目が存在する場合、その項目 全体が置き換えられます。 Note 項目全体を置き換える代わりに固有の属性のみを更新する場合は、UpdateItem メソッドを 使用できます。詳細については、「項目の更新 (p. 253)」を参照してください。 以下に、低レベルの .NET SDK API を使用して項目をアップロードする手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. PutItemRequest クラスのインスタンスを作成し、必須パラメータを指定します。 項目を置き換えるには、テーブル名と項目を指定する必要があります。 3. 前の手順で作成した PutItemRequest オブジェクトを指定して、PutItem メソッドを実行しま す。 次の C# コードスニペットは、前述のステップを示しています。この例では、ProductCatalog テーブ ルに項目がアップロードされています。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ProductCatalog"; var request = new PutItemRequest { TableName = tableName, Item = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "201" }}, { "Title", new AttributeValue { S = "Book 201 Title" }}, { "ISBN", new AttributeValue { S = "11-11-11-11" }}, { "Price", new AttributeValue { S = "20.00" }}, { "Authors", new AttributeValue { SS = new List<string>{"Author1", "Author2"} } } } }; client.PutItem(request); 上記の例では、Id、Title、ISBN、Authors の属性を持つ書籍項目をアップロードしています。Id は数 値型の属性で、それ以外の属性はすべて文字列型です。Authors は文字列セットです。 API Version 2012-08-10 251 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET オプションパラメータの指定 以下の C# コードスニペットに示すように、PutItemRequest オブジェクトを使用してオプションの パラメータを指定することもできます。このサンプルでは、次のオプションパラメータが指定されて います。 • ExpressionAttributeNames、ExpressionAttributeValues、および ConditionExpression は、特定の値が設定された ISBN 属性が既存の項目にある場合にのみ項目 を置き換えるという条件を指定します。 • ReturnValues パラメータ。応答内で古い項目をリクエストします。 var request = new PutItemRequest { TableName = tableName, Item = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "104" }}, { "Title", new AttributeValue { S = "Book 104 Title" }}, { "ISBN", new AttributeValue { S = "444-4444444444" }}, { "Authors", new AttributeValue { SS = new List<string>{"Author3"}}} }, // Optional parameters. ExpressionAttributeNames = new Dictionary<string,string>() { {"#I", "ISBN"} }, ExpressionAttributeValues = new Dictionary<string, AttributeValue>() { {":isbn",new AttributeValue {S = "444-4444444444"}} }, ConditionExpression = "#I = :isbn" }; var response = client.PutItem(request); 詳細については、PutItem を参照してください。 項目の取得 GetItem メソッドにより、項目を取り出します。 Note 複数の項目を取り出すために、BatchGetItem メソッドを使用できます。詳細については、 「バッチ取得: 複数の項目の取得 (p. 259)」を参照してください。 以下に、低レベルの .NET SDK API を使用して既存の項目を取り出す手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. GetItemRequest クラスのインスタンスを作成し、必須パラメータを指定します。 項目を取得するには、その項目のテーブル名とプライマリキーを指定する必要があります。 3. 前の手順で作成した GetItemRequest オブジェクトを指定して、GetItem メソッドを実行しま す。 API Version 2012-08-10 252 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET 次の C# コードスニペットは、前述のステップを示しています。ProductCatalog テーブルから項目を 取り出す例を以下に示します。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ProductCatalog"; var request = new GetItemRequest { TableName = tableName, Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } }, }; var response = client.GetItem(request); // Check the response. var result = response.GetItemResult; var attributeMap = result.Item; // Attribute list in the response. オプションパラメータの指定 以下の C# コードスニペットに示すように、GetItemRequest オブジェクトを使用してオプションの パラメータを指定することもできます。このサンプルでは、次のオプションパラメータが指定されて います。 • 取得対象の属性を指定する ProjectionExpression パラメータ。 • 強力な整合性のある読み込みを実行する ConsistentRead パラメータ。読み込みの整合性に関す る詳細については、「読み込み整合性 (p. 16)」を参照してください。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ProductCatalog"; var request = new GetItemRequest { TableName = tableName, Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } }, // Optional parameters. ProjectionExpression = "Id, ISBN, Title, Authors", ConsistentRead = true }; var response = client.GetItem(request); // Check the response. var result = response.GetItemResult; var attributeMap = result.Item; 詳細については、GetItem を参照してください。 項目の更新 既存の項目がある場合に、UpdateItem メソッドにより、その項目を更新します。UpdateItem オペ レーションを使用して、既存の属性値の更新、新しい属性の追加、または既存のコレクションからの 属性の削除ができます。指定のプライマリキーのある項目が見つからない場合は、新しい項目を追加 します。 API Version 2012-08-10 253 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET UpdateItem オペレーションは、以下のガイドラインに従います。 • 項目が存在しない場合、UpdateItem は入力で指定されたプライマリキーを使用して、新しい項目 を追加します。 • 項目が存在する場合、UpdateItem は次のように更新を適用します。 • 既存の属性値を更新内の値に置き換えます。 • 入力内で指定した属性が存在しない場合は、項目に新しい属性を追加します。 • 入力属性が null の場合、属性がある場合は、削除します。 • Action に ADD を使用すると、既存のセット(文字列または数セット)に値を追加できます。ある いは、既存の数値属性の値に対して足し算(正の数を使用)したり、引き算(負の数を使用)す ることもできます。 Note また、PutItem オペレーションにより、更新を実行できます。詳細については、「項目の置 換 (p. 251)」を参照してください。たとえば、PutItem を呼び出して項目をアップロードし た場合にプライマリキーが存在すれば、PutItem オペレーションによって項目全体が置き換 えられます。既存の項目内に属性がある場合、入力に指定されていない属性は、PutItem オ ペレーションによって削除されます。ただし、UpdateItem は指定された入力属性のみを更 新します。その項目の他の既存の属性は変更されません。 以下に、低レベルの .NET SDK API を使用して既存の項目を更新する手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. UpdateItemRequest クラスのインスタンスを作成し、必須パラメータを指定します。 これは、属性の追加、既存の属性の更新、属性の削除など、すべての更新を記述するリクエストオ ブジェクトです。既存の属性を削除するには、null 値の属性名を指定します。 3. 前の手順で作成した UpdateItemRequest オブジェクトを指定して、UpdateItem メソッドを実 行します。 次の C# コードスニペットは、前述のステップを示しています。ProductCatalog テーブルで書籍項目 を更新する例を以下に示します。この例では、Authors コレクションに著者を追加し、既存の ISBN 属 性を削除します。また、価格を 1 引き下げます。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ProductCatalog"; var request = new UpdateItemRequest { TableName = tableName, Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } }, ExpressionAttributeNames = new Dictionary<string,string>() { {"#A", "Authors"}, {"#P", "Price"}, {"#NA", "NewAttribute"}, {"#I", "ISBN"} }, ExpressionAttributeValues = new Dictionary<string, AttributeValue>() { {":auth",new AttributeValue { SS = {"Author YY","Author ZZ"}}}, {":p",new AttributeValue {N = "1"}}, API Version 2012-08-10 254 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET {":newattr",new AttributeValue {S = "someValue"}}, }, // This expression does the following: // 1) Adds two new authors to the list // 2) Reduces the price // 3) Adds a new attribute to the item // 4) Removes the ISBN attribute from the item UpdateExpression = "ADD #A :auth SET #P = #P - :p, #NA = :newattr REMOVE #I" }; var response = client.UpdateItem(request); オプションパラメータの指定 以下の C# コードスニペットに示すように、UpdateItemRequest オブジェクトを使用してオプショ ンのパラメータを指定することもできます。以下のオプションパラメータを指定します。 • ExpressionAttributeValues および ConditionExpression パラメータ。既存の価格が 20.00 USD である場合にのみ価格を更新できることを指定します。 • ReturnValues パラメータ。応答内で更新された項目をリクエストします。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ProductCatalog"; var request = new UpdateItemRequest { Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } }, // Update price only if the current price is 20.00. ExpressionAttributeNames = new Dictionary<string,string>() { {"#P", "Price"} }, ExpressionAttributeValues = new Dictionary<string, AttributeValue>() { {":newprice",new AttributeValue {N = "22"}}, {":currprice",new AttributeValue {N = "20"}} }, UpdateExpression = "SET #P = :newprice", ConditionExpression = "#P = :currprice", TableName = tableName, ReturnValues = "ALL_NEW" // Return all the attributes of the updated item. }; var response = client.UpdateItem(request); 詳細については、UpdateItem を参照してください。 アトミックカウンター updateItem を使用してアトミックカウンターを実装できます。アトミックカウンターでは、他の書 き込みリクエストを妨げることなく、既存の属性の値をインクリメントまたはデクリメントします。 アトミックカウンターを更新するには、updateItem の UpdateExpression パラメータで数値型の属 性を使用し、Action として ADD を使用します。 API Version 2012-08-10 255 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET 次のコード例はアトミックカウンターを示しており、Quantity 属性を 1 ずつインクリメントさせてい ます。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ProductCatalog"; var request = new UpdateItemRequest { Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "121" } } }, ExpressionAttributeNames = new Dictionary<string, string>() { {"#Q", "Quantity"} }, ExpressionAttributeValues = new Dictionary<string, AttributeValue>() { {":incr",new AttributeValue {N = "1"}} }, UpdateExpression = "SET #Q = #Q + :incr", TableName = tableName }; var response = client.UpdateItem(request); 項目の削除 DeleteItem メソッドによって、テーブルから項目を削除します。 以下に、低レベルの .NET SDK API を使用して項目を削除する手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. DeleteItemRequest クラスのインスタンスを作成し、必須パラメータを指定します。 項目を削除するには、テーブル名とその項目のプライマリキーが必要です。 3. 前の手順で作成した DeleteItemRequest オブジェクトを指定して、DeleteItem メソッドを実 行します。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "ProductCatalog"; var request = new DeleteItemRequest { TableName = tableName, Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "201" } } }, }; var response = client.DeleteItem(request); オプションパラメータの指定 以下の C# コードスニペットに示すように、DeleteItemRequest オブジェクトを使用してオプショ ンのパラメータを指定することもできます。以下のオプションパラメータを指定します。 • ExpressionAttributeValues および ConditionExpression パラメータ。廃刊になっている (InPublication の属性値が false)場合にのみ書籍項目を削除するという条件を指定します。 API Version 2012-08-10 256 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET • ReturnValues パラメータ。応答内で削除済みの項目をリクエストします。 var request = new DeleteItemRequest { TableName = tableName, Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "201" } } }, // Optional parameters. ReturnValues = "ALL_OLD", ExpressionAttributeNames = new Dictionary<string, string>() { {"#IP", "InPublication"} }, ExpressionAttributeValues = new Dictionary<string, AttributeValue>() { {":inpub",new AttributeValue {BOOL = false}} }, ConditionExpression = "#IP = :inpub" }; var response = client.DeleteItem(request); 詳細については、DeleteItem を参照してください。 バッチ書き込み: 複数の項目の書き込みおよび削除 バッチ書き込みは、複数の項目の書き込みと削除をバッチで行うことを意味しま す。BatchWriteItem メソッドによって、単一の コール内にある 1 つまたは複数のテーブルから複 数の項目を置換および削除できます。以下に、低レベルの .NET SDK API を使用して複数の項目を取 り出す手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. BatchWriteItemRequest クラスのインスタンスを作成して、置換および削除のすべてのオペ レーションを説明します。 3. 前の手順で作成した BatchWriteItemRequest オブジェクトを指定して、BatchWriteItem メ ソッドを実行します。 4. 応答を処理します。返された未処理のリクエスト項目が応答内に存在していたかどうかをチェック する必要があります。これは、プロビジョニングされたスループットの制限または他の何らかの一 時的エラーに達する場合に、発生する可能性があります。また、DynamoDB によって、リクエスト のサイズ、およびリクエスト内で指定できるオペレーションの数が制限されます。これらの制限を 超えると、DynamoDB によってリクエストが却下されます。詳細については、BatchWriteItem を 参照してください。 次の C# コードスニペットは、前述のステップを示しています。この例で は、BatchWriteItemRequest を作成して、以下の書き込みオペレーションを実行します。 • Forum テーブル内で項目を置換します。 • Thread テーブルに対して項目の置換および削除を実行します。 コードにより、BatchWriteItem が実行され、バッチオペレーションが行われます。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); API Version 2012-08-10 257 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET string table1Name = "Forum"; string table2Name = "Thread"; var request = new BatchWriteItemRequest { RequestItems = new Dictionary<string, List<WriteRequest>> { { table1Name, new List<WriteRequest> { new WriteRequest { PutRequest = new PutRequest { Item = new Dictionary<string,AttributeValue> { { "Name", new AttributeValue { S = "Amazon S3 forum" } }, { "Threads", new AttributeValue { N = "0" }} } } } } } , { table2Name, new List<WriteRequest> { new WriteRequest { PutRequest = new PutRequest { Item = new Dictionary<string,AttributeValue> { { "ForumName", new AttributeValue { S = "Amazon S3 forum" } }, { "Subject", new AttributeValue { S = "My sample question" } }, { "Message", new AttributeValue { S = "Message Text." } }, { "KeywordTags", new AttributeValue { SS = new List<string> { "Amazon S3", "Bucket" } } } } } }, new WriteRequest { DeleteRequest = new DeleteRequest { Key = new Dictionary<string,AttributeValue>() { { "ForumName", new AttributeValue { S = "Some forum name" } }, { "Subject", new AttributeValue { S = "Some subject" } } } } } } } } }; API Version 2012-08-10 258 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET response = client.BatchWriteItem(request); 実例については、「例: AWS SDK for .NET の低レベル API を使用した、バッチオペレーショ ン (p. 265)」を参照してください。 バッチ取得: 複数の項目の取得 BatchGetItem メソッドによって、1 つまたは複数のテーブルから複数の項目を取得できます。 Note 単一の項目を取り出すために、GetItem メソッドを使用できます。 以下に、低レベルの .NET SDK API を使用して複数の項目を取り出す手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. BatchGetItemRequest クラスのインスタンスを作成し、必須パラメータを指定します。 複数の項目を取り出すには、テーブル名、およびプライマリキー値のリストが必要です。 3. 前の手順で作成した BatchGetItemRequest オブジェクトを指定して、BatchGetItem メソッド を実行します。 4. 応答を処理します。未処理キーがなかったかどうかをチェックする必要があります。これは、プロ ビジョニングされたスループットの制限または他の何らかの一時的エラーに達する場合に、発生す る可能性があります。 次の C# コードスニペットは、前述のステップを示しています。この例では、Forum と Thread の 2 つのテーブルから項目を取り出します。このリクエストには、Forum テーブル内の 2 つの項目、およ び Thread テーブル内の 3 つの項目を指定します。応答には、両方のテーブルの項目が含まれます。 このコードには、応答を処理する方法が示されます。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string table1Name = "Forum"; string table2Name = "Thread"; var request = new BatchGetItemRequest { RequestItems = new Dictionary<string, KeysAndAttributes>() { { table1Name, new KeysAndAttributes { Keys = new List<Dictionary<string, AttributeValue>>() { new Dictionary<string, AttributeValue>() { { "Name", new AttributeValue { S = "DynamoDB" } } }, new Dictionary<string, AttributeValue>() { { "Name", new AttributeValue { S = "Amazon S3" } } } } } API Version 2012-08-10 259 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET }, { table2Name, new KeysAndAttributes { Keys = new List<Dictionary<string, AttributeValue>>() { new Dictionary<string, AttributeValue>() { { "ForumName", new AttributeValue { S = "DynamoDB" } }, { "Subject", new AttributeValue { S = "DynamoDB Thread 1" } } }, new Dictionary<string, AttributeValue>() { { "ForumName", new AttributeValue { S = "DynamoDB" } }, { "Subject", new AttributeValue { S = "DynamoDB Thread 2" } } }, new Dictionary<string, AttributeValue>() { { "ForumName", new AttributeValue { S = "Amazon S3" } }, { "Subject", new AttributeValue { S = "Amazon S3 Thread 1" } } } } } } } }; var response = client.BatchGetItem(request); // Check the response. var result = response.BatchGetItemResult; var responses = result.Responses; // The attribute list in the response. var table1Results = responses[table1Name]; Console.WriteLine("Items in table {0}" + table1Name); foreach (var item1 in table1Results.Items) { PrintItem(item1); } var table2Results = responses[table2Name]; Console.WriteLine("Items in table {1}" + table2Name); foreach (var item2 in table2Results.Items) { PrintItem(item2); } // Any unprocessed keys? could happen if you exceed ProvisionedThroughput or some other error. Dictionary<string, KeysAndAttributes> unprocessedKeys = result.UnprocessedKeys; foreach (KeyValuePair<string, KeysAndAttributes> pair in unprocessedKeys) { Console.WriteLine(pair.Key, pair.Value); } API Version 2012-08-10 260 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET オプションパラメータの指定 以下の C# コードスニペットに示すように、BatchGetItemRequest オブジェクトを使用してオプ ションのパラメータを指定することもできます。このサンプルコードでは、Forum テーブルの 2 つの 項目を取り出します。次のオプションパラメータが指定されています。 • 取得対象の属性を指定する ProjectionExpression パラメータ。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string table1Name = "Forum"; var request = new BatchGetItemRequest { RequestItems = new Dictionary<string, KeysAndAttributes>() { { table1Name, new KeysAndAttributes { Keys = new List<Dictionary<string, AttributeValue>>() { new Dictionary<string, AttributeValue>() { { "Name", new AttributeValue { S = "DynamoDB" } } }, new Dictionary<string, AttributeValue>() { { "Name", new AttributeValue { S = "Amazon S3" } } } } }, // Optional - name of an attribute to retrieve. ProjectionExpression = "Title" } } }; var response = client.BatchGetItem(request); 詳細については、BatchGetItem を参照してください。 例: AWS SDK for .NET の低レベル API を使用した CRUD オ ペレーション 以下の C# コード例は、項目に対する CRUD オペレーションの例です。この例では、ProductCatalog テーブルへの項目の追加、項目の取得、さまざまな更新の実行、さらに項目の削除を行います。 「テーブルの作成とサンプルデータのロード (p. 166)」のステップに従っていれば、ProductCatalog テーブルは作成済みです。これらのサンプルテーブルは、プログラムで作成することもできます。 詳細については、「AWS SDK for .NET を使用した、サンプルテーブルの作成とデータのアップロー ド (p. 608)」を参照してください。 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照し てください。 using System; using System.Collections.Generic; using Amazon.DynamoDBv2; API Version 2012-08-10 261 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET using Amazon.DynamoDBv2.Model; using Amazon.Runtime; using Amazon.SecurityToken; namespace com.amazonaws.codesamples { class LowLevelItemCRUDExample { private static string tableName = "ProductCatalog"; private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { CreateItem(); RetrieveItem(); // Perform various updates. UpdateMultipleAttributes(); UpdateExistingAttributeConditionally(); // Delete item. DeleteItem(); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } } private static void CreateItem() { var request = new PutItemRequest { TableName = tableName, Item = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "1000" }}, { "Title", new AttributeValue { S = "Book 201 Title" }}, { "ISBN", new AttributeValue { S = "11-11-11-11" }}, { "Authors", new AttributeValue { SS = new List<string>{"Author1", "Author2" }}}, { "Price", new AttributeValue { N = "20.00" }}, { "Dimensions", new AttributeValue { S = "8.5x11.0x.75" }}, { "InPublication", new AttributeValue { BOOL = false } } } }; client.PutItem(request); } private static void RetrieveItem() { API Version 2012-08-10 262 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET var request = new GetItemRequest { TableName = tableName, Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "1000" } } }, ProjectionExpression = "Id, ISBN, Title, Authors", ConsistentRead = true }; var response = client.GetItem(request); // Check the response. var attributeList = response.Item; // attribute list in the response. Console.WriteLine("\nPrinting item after retrieving it ............"); PrintItem(attributeList); } private static void UpdateMultipleAttributes() { var request = new UpdateItemRequest { Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "1000" } } }, // Perform the following updates: // 1) Add two new authors to the list // 1) Set a new attribute // 2) Remove the ISBN attribute ExpressionAttributeNames = new Dictionary<string,string>() { {"#A","Authors"}, {"#NA","NewAttribute"}, {"#I","ISBN"} }, ExpressionAttributeValues = new Dictionary<string, AttributeValue>() { {":auth",new AttributeValue {SS = {"Author YY", "Author ZZ"}}}, {":new",new AttributeValue {S = "New Value"}} }, UpdateExpression = "ADD #A :auth SET #NA = :new REMOVE #I", TableName = tableName, ReturnValues = "ALL_NEW" // Give me all attributes of the updated item. }; var response = client.UpdateItem(request); // Check the response. var attributeList = response.Attributes; // attribute list in the response. // print attributeList. API Version 2012-08-10 263 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET Console.WriteLine("\nPrinting item after multiple attribute update ............"); PrintItem(attributeList); } private static void UpdateExistingAttributeConditionally() { var request = new UpdateItemRequest { Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "1000" } } }, ExpressionAttributeNames = new Dictionary<string,string>() { {"#P", "Price"} }, ExpressionAttributeValues = new Dictionary<string, AttributeValue>() { {":newprice",new AttributeValue {N = "22.00"}}, {":currprice",new AttributeValue {N = "20.00"}} }, // This updates price only if current price is 20.00. UpdateExpression = "SET #P = :newprice", ConditionExpression = "#P = :currprice", TableName = tableName, ReturnValues = "ALL_NEW" // Give me all attributes of the updated item. }; var response = client.UpdateItem(request); // Check the response. var attributeList = response.Attributes; // attribute list in the response. Console.WriteLine("\nPrinting item after updating price value conditionally ............"); PrintItem(attributeList); } private static void DeleteItem() { var request = new DeleteItemRequest { TableName = tableName, Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "1000" } } }, // Return the entire item as it appeared before the update. ReturnValues = "ALL_OLD", ExpressionAttributeNames = new Dictionary<string,string>() { {"#IP", "InPublication"} }, ExpressionAttributeValues = new Dictionary<string, AttributeValue>() API Version 2012-08-10 264 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET { {":inpub",new AttributeValue {BOOL = false}} }, ConditionExpression = "#IP = :inpub" }; var response = client.DeleteItem(request); // Check the response. var attributeList = response.Attributes; // Attribute list in the response. // Print item. Console.WriteLine("\nPrinting item that was just deleted ............"); PrintItem(attributeList); } private static void PrintItem(Dictionary<string, AttributeValue> attributeList) { foreach (KeyValuePair<string, AttributeValue> kvp in attributeList) { string attributeName = kvp.Key; AttributeValue value = kvp.Value; Console.WriteLine( attributeName + " " + (value.S == null ? "" : "S=[" + (value.N == null ? "" : "N=[" + (value.SS == null ? "" : "SS=[" value.SS.ToArray()) + "]") + (value.NS == null ? "" : "NS=[" value.NS.ToArray()) + "]") ); } value.S + "]") + value.N + "]") + + string.Join(",", + string.Join(",", Console.WriteLine("************************************************"); } } } 例: AWS SDK for .NET の低レベル API を使用した、バッチオ ペレーション トピック • 例: AWS SDK for .NET の低レベル API を使用した、バッチ書き込みオペレーション (p. 266) • 例: AWS SDK for .NET の低レベル API を使用した、バッチ取得オペレーション (p. 269) このセクションでは、DynamoDB でサポートするバッチオペレーションの例(バッチの書き込み、取 得)を説明します。 API Version 2012-08-10 265 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET 例: AWS SDK for .NET の低レベル API を使用した、バッチ書き込みオペレー ション 以下の C# コード例では、BatchWriteItem メソッドを使用して、以下の置換および削除のオペレー ションを実行します。 • Forum テーブル内で 1 つの項目を置換 • Thread テーブルに対して 1 つの項目を置換および削除 バッチの書き込みリクエストを作成すると、1 つまたは複数のテーブルに対して多数の置換リクエス トと削除リクエストを指定できます。ただし、DynamoDB BatchWriteItem では、1 回のバッチ書 き込みオペレーションで可能なバッチ書き込みリクエストのサイズ、置換および削除のオペレーショ ンの数を制限しています。 詳細については、BatchWriteItem を参照してください。これらの制限を超 えるリクエストは却下されます。プロビジョニングされたスループットがテーブルに不足しているた めにこのリクエストを処理できない場合は、応答時に未処理のリクエスト項目が返されます。 以下の例では、未処理のリクエスト項目がないか、応答を確認します。未処理のリクエスト項目があ る場合は、BatchWriteItem リクエストをループバックして再送信します。「テーブルの作成とサン プルデータのロード (p. 166)」のステップに従っていれば、Forum テーブルと Thread テーブルは作 成済みです。プログラムで、これらのサンプルテーブルを作成し、サンプルデータをアップロードす ることもできます。詳細については、「AWS SDK for .NET を使用した、サンプルテーブルの作成と データのアップロード (p. 608)」を参照してください。 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照し てください。 using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.Model; Amazon.Runtime; namespace com.amazonaws.codesamples { class LowLevelBatchWrite { private static string table1Name = "Forum"; private static string table2Name = "Thread"; private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { TestBatchWrite(); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void TestBatchWrite() { API Version 2012-08-10 266 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET var request = new BatchWriteItemRequest { ReturnConsumedCapacity = "TOTAL", RequestItems = new Dictionary<string, List<WriteRequest>> { { table1Name, new List<WriteRequest> { new WriteRequest { PutRequest = new PutRequest { Item = new Dictionary<string, AttributeValue> { { "Name", new AttributeValue { S = "S3 forum" } }, { "Threads", new AttributeValue { N = "0" }} } } } } }, { table2Name, new List<WriteRequest> { new WriteRequest { PutRequest = new PutRequest { Item = new Dictionary<string, AttributeValue> { { "ForumName", new AttributeValue { S = "S3 forum" } }, { "Subject", new AttributeValue { S = "My sample question" } }, { "Message", new AttributeValue { S = "Message Text." } }, { "KeywordTags", new AttributeValue { SS = new List<string> { "S3", "Bucket" } } } } } }, new WriteRequest { // For the operation to delete an item, if you provide a primary key value // that does not exist in the table, there is no error, it is just a no-op. DeleteRequest = new DeleteRequest { Key = new Dictionary<string, AttributeValue>() { { "ForumName", new AttributeValue { S = "Some partition key value" } }, { "Subject", new AttributeValue { S = "Some sort key value" } } } } } } } API Version 2012-08-10 267 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET } }; CallBatchWriteTillCompletion(request); } private static void CallBatchWriteTillCompletion(BatchWriteItemRequest request) { BatchWriteItemResponse response; int callCount = 0; do { Console.WriteLine("Making request"); response = client.BatchWriteItem(request); callCount++; // Check the response. var tableConsumedCapacities = response.ConsumedCapacity; var unprocessed = response.UnprocessedItems; Console.WriteLine("Per-table consumed capacity"); foreach (var tableConsumedCapacity in tableConsumedCapacities) { Console.WriteLine("{0} - {1}", tableConsumedCapacity.TableName, tableConsumedCapacity.CapacityUnits); } Console.WriteLine("Unprocessed"); foreach (var unp in unprocessed) { Console.WriteLine("{0} - {1}", unp.Key, unp.Value.Count); } Console.WriteLine(); // For the next iteration, the request will have unprocessed items. request.RequestItems = unprocessed; } while (response.UnprocessedItems.Count > 0); Console.WriteLine("Total # of batch write API calls made: {0}", callCount); } } } API Version 2012-08-10 268 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET 例: AWS SDK for .NET の低レベル API を使用した、バッチ取得オペレーショ ン 以下の C# コード例では、BatchGetItem メソッドを使用して、Forum テーブルおよび Thread テー ブルから複数の項目を取り出します。BatchGetItemRequest は、各テーブルにテーブル名とプライ マリキーのリストを指定します。この例では、取得した項目を印刷して応答を処理します。 「テーブルの作成とサンプルデータのロード (p. 166)」のステップに従っていれば、サンプルデータ を使用したこれらのテーブルは作成済みです。プログラムで、これらのサンプルテーブルを作成し、 サンプルデータをアップロードすることもできます。詳細については、「AWS SDK for .NET を使用 した、サンプルテーブルの作成とデータのアップロード (p. 608)」を参照してください。 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照し てください。 using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.Model; Amazon.Runtime; namespace com.amazonaws.codesamples { class LowLevelBatchGet { private static string table1Name = "Forum"; private static string table2Name = "Thread"; private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { RetrieveMultipleItemsBatchGet(); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } private static void RetrieveMultipleItemsBatchGet() { var request = new BatchGetItemRequest { RequestItems = new Dictionary<string, KeysAndAttributes>() { { table1Name, new KeysAndAttributes { Keys = new List<Dictionary<string, AttributeValue>>() { new Dictionary<string, AttributeValue>() { { "Name", new AttributeValue { S = "Amazon DynamoDB" } } }, API Version 2012-08-10 269 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET new Dictionary<string, AttributeValue>() { { "Name", new AttributeValue { S = "Amazon S3" } } } } } }, { table2Name, new KeysAndAttributes { Keys = new List<Dictionary<string, AttributeValue>>() { new Dictionary<string, AttributeValue>() { { "ForumName", new AttributeValue { S = "Amazon DynamoDB" } }, { "Subject", new AttributeValue { S = "DynamoDB Thread 1" } } }, new Dictionary<string, AttributeValue>() { { "ForumName", new AttributeValue { S = "Amazon DynamoDB" } }, { "Subject", new AttributeValue { S = "DynamoDB Thread 2" } } }, new Dictionary<string, AttributeValue>() { { "ForumName", new AttributeValue { S = "Amazon S3" } }, { "Subject", new AttributeValue { S = "S3 Thread 1" } } } } } } } }; BatchGetItemResponse response; do { Console.WriteLine("Making request"); response = client.BatchGetItem(request); // Check the response. var responses = response.Responses; // Attribute list in the response. foreach (var tableResponse in responses) { var tableResults = tableResponse.Value; Console.WriteLine("Items retrieved from table {0}", tableResponse.Key); foreach (var item1 in tableResults) { PrintItem(item1); } } API Version 2012-08-10 270 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET // Any unprocessed keys? could happen if you exceed ProvisionedThroughput or some other error. Dictionary<string, KeysAndAttributes> unprocessedKeys = response.UnprocessedKeys; foreach (var unprocessedTableKeys in unprocessedKeys) { // Print table name. Console.WriteLine(unprocessedTableKeys.Key); // Print unprocessed primary keys. foreach (var key in unprocessedTableKeys.Value.Keys) { PrintItem(key); } } request.RequestItems = unprocessedKeys; } while (response.UnprocessedKeys.Count > 0); } private static void PrintItem(Dictionary<string, AttributeValue> attributeList) { foreach (KeyValuePair<string, AttributeValue> kvp in attributeList) { string attributeName = kvp.Key; AttributeValue value = kvp.Value; Console.WriteLine( attributeName + " " + (value.S == null ? "" : "S=[" + (value.N == null ? "" : "N=[" + (value.SS == null ? "" : "SS=[" value.SS.ToArray()) + "]") + (value.NS == null ? "" : "NS=[" value.NS.ToArray()) + "]") ); } value.S + "]") + value.N + "]") + + string.Join(",", + string.Join(",", Console.WriteLine("************************************************"); } } } 例: AWS SDK for .NET の低レベル API を使用した、バイナリ タイプ属性の処理 以下の C# コード例は、バイナリタイプ属性の処理の例です。この例では、Reply テーブルに項目 を追加します。この項目には、圧縮データを格納するバイナリタイプ属性(ExtendedMessage) などがあります。また、この例では、項目を取得し、すべての属性値を印刷します。説明のため、 この例では GZipStream クラスを使用して、サンプルストリームを圧縮し、圧縮したデータを ExtendedMessage 属性に割り当て、属性値の印刷時に展開します。 「テーブルの作成とサンプルデータのロード (p. 166)」のステップに従っていれば、Reply テーブルは 作成済みです。これらのサンプルテーブルは、プログラムで作成することもできます。詳細について は、「AWS SDK for .NET を使用した、サンプルテーブルの作成とデータのアップロード (p. 608)」 を参照してください。 API Version 2012-08-10 271 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照し てください。 using using using using using using using System; System.Collections.Generic; System.IO; System.IO.Compression; Amazon.DynamoDBv2; Amazon.DynamoDBv2.Model; Amazon.Runtime; namespace com.amazonaws.codesamples { class LowLevelItemBinaryExample { private static string tableName = "Reply"; private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { // Reply table primary key. string replyIdPartitionKey = "Amazon DynamoDB#DynamoDB Thread 1"; string replyDateTimeSortKey = Convert.ToString(DateTime.UtcNow); try { CreateItem(replyIdPartitionKey, replyDateTimeSortKey); RetrieveItem(replyIdPartitionKey, replyDateTimeSortKey); // Delete item. DeleteItem(replyIdPartitionKey, replyDateTimeSortKey); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } private static void CreateItem(string partitionKey, string sortKey) { MemoryStream compressedMessage = ToGzipMemoryStream("Some long extended message to compress."); var request = new PutItemRequest { TableName = tableName, Item = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { S = partitionKey }}, { "ReplyDateTime", new AttributeValue { S = sortKey }}, { "Subject", new AttributeValue { S = "Binary type " }}, { "Message", new AttributeValue { S = "Some message about the binary type" }}, { "ExtendedMessage", new AttributeValue { B = compressedMessage }} } }; API Version 2012-08-10 272 Amazon DynamoDB 開発者ガイド 項目の操作 : .NET client.PutItem(request); } private static void RetrieveItem(string partitionKey, string sortKey) { var request = new GetItemRequest { TableName = tableName, Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { S = partitionKey } }, { "ReplyDateTime", new AttributeValue { S = sortKey } } }, ConsistentRead = true }; var response = client.GetItem(request); // Check the response. var attributeList = response.Item; // attribute list in the response. Console.WriteLine("\nPrinting item after retrieving it ............"); PrintItem(attributeList); } private static void DeleteItem(string partitionKey, string sortKey) { var request = new DeleteItemRequest { TableName = tableName, Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { S = partitionKey } }, { "ReplyDateTime", new AttributeValue { S = sortKey } } } }; var response = client.DeleteItem(request); } private static void PrintItem(Dictionary<string, AttributeValue> attributeList) { foreach (KeyValuePair<string, AttributeValue> kvp in attributeList) { string attributeName = kvp.Key; AttributeValue value = kvp.Value; Console.WriteLine( attributeName + " " + (value.S == null ? "" : "S=[" + (value.N == null ? "" : "N=[" + (value.SS == null ? "" : "SS=[" value.SS.ToArray()) + "]") + (value.NS == null ? "" : "NS=[" value.NS.ToArray()) + "]") + API Version 2012-08-10 273 value.S + "]") + value.N + "]") + + string.Join(",", + string.Join(",", Amazon DynamoDB 開発者ガイド 項目の操作 : PHP (value.B == null ? "" : "B=[" + FromGzipMemoryStream(value.B) + "]") ); } Console.WriteLine("************************************************"); } private static MemoryStream ToGzipMemoryStream(string value) { MemoryStream output = new MemoryStream(); using (GZipStream zipStream = new GZipStream(output, CompressionMode.Compress, true)) using (StreamWriter writer = new StreamWriter(zipStream)) { writer.Write(value); } return output; } private static string FromGzipMemoryStream(MemoryStream stream) { using (GZipStream zipStream = new GZipStream(stream, CompressionMode.Decompress)) using (StreamReader reader = new StreamReader(zipStream)) { return reader.ReadToEnd(); } } } } 項目の操作 : PHP トピック • 項目の置換 (p. 275) • 項目の取得 (p. 276) • バッチ書き込み: 複数の項目の書き込みおよび削除 (p. 277) • バッチ取得: 複数の項目の取得 (p. 278) • 項目の更新 (p. 279) • • • • アトミックカウンター (p. 281) 項目の削除 (p. 281) 例: AWS SDK for PHP の低レベル API を使用した CRUD オペレーション (p. 283) 例: AWS SDK for PHP を使用した、バッチオペレーション (p. 285) AWS SDK for PHP を使用して、テーブル内の項目に対して、一般的な作成、読み込み、更新、削除 (CRUD)のオペレーションを実行できます。SDK オペレーションは、基盤となる DynamoDB の低 レベルアクションにマッピングされます。 詳細については、「PHP コードサンプル (p. 175)」を参照 してください。 以下に、AWS SDK for PHP を使用してデータ CRUD オペレーションを実行する一般的な手順を示し ます。 1. DynamoDB クライアントのインスタンスを作成します。 API Version 2012-08-10 274 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP 2. オプションのパラメーターを含む DynamoDB オペレーションのパラメーターを指定します。 3. DynamoDB からの応答をアプリケーションのローカル変数にロードします。 項目の置換 PHP putItem 関数によって、項目をテーブルにアップロードします。項目が存在する場合、そ の項目全体が置き換えられます。項目全体を置き換える代わりに固有の属性のみを更新する場合 は、updateItem 関数を使用できます。詳細については、「項目の更新 (p. 279)」を参照してくだ さい。 以下の PHP コードスニペットは、前述のタスクの例です。このコードでは、ProductCatalog テーブ ルに項目をアップロードします。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。あるいは、「AWS SDK for PHP を使用した、サンプルテー ブルの作成とデータのアップロード (p. 617)」のトピックに記載されている手順に従って データをロードすることもできます。 以下の例を実行するための詳しい手順については、「PHP コードサンプル (p. 175)」を参照 してください。 require 'vendor/autoload.php'; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $response = $dynamodb->putItem([ 'TableName' => 'ProductCatalog', 'Item' => [ 'Id' => ['N' => '104' ], // Primary Key 'Title' => ['S' => 'Book 104 Title' ], 'ISBN' => ['S' => '111-1111111111' ], 'Price' => ['N' => '25' ], 'Authors' => ['SS' => ['Author1', 'Author2'] ] ] ]); print_r($response); オプションパラメータの指定 必須のパラメータに加え、putItem 関数にはオプションパラメータも指定できます。た とえば、以下の PHP コードスニペットでは、オプションパラメータを使用して、項目の アップロード条件を指定します。指定した条件を満たさない場合は、AWS PHP SDK が ConditionalCheckFailedException をスローします。このコードでは、putItem に以下のオプ ションパラメータを指定します。 • ConditionExpression パラメータ。特定の値に等しい ISBN 属性が既存の項目にある場合にのみ 既存の項目を置き換えるという条件など、リクエストに対する条件を定義します。 API Version 2012-08-10 275 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP • ReturnValue パラメータに対応する ALL_OLD 値。項目に対するすべての属性値を、PutItem オペ レーションの前に提供します。この場合、古い項目には 2 人の著者のみが含まれ、新しい項目値に は 3 人の著者が含まれています。 $tableName = 'ProductCatalog'; $result = $dynamodb->putItem ([ 'TableName' => $tableName, 'Item' => [ 'Id' => [ 'N' => '104' ], // Primary Key 'Title' => [ 'S' => 'Book 104 Title' ], 'ISBN' => [ 'S' => '333-3333333333' ], 'Price' => [ 'N' => '2000' ], 'Authors' => [ 'SS' => [ 'Author1', 'Author2', 'Author3' ] ] ], 'ExpressionAttributeNames' => [ '#I' => 'ISBN'] , 'ExpressionAttributeValues' => [ ':val1' => ['S' => '333-3333333333']] , 'ConditionExpression' => '#I = :val1', 'ReturnValues' => 'ALL_OLD' ]); print_r ($result); 詳細については、PutItem を参照してください。 項目の取得 getItem 関数によって、単一の項目を取り出します。複数の項目を取り出すために、batchGetItem メソッドを使用できます(「バッチ取得: 複数の項目の取得 (p. 278)」参照)。 以下の PHP コードスニペットは、前述のステップの例です。このコードでは、指定したパーティショ ンキーを持つ項目を取得します。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。あるいは、「AWS SDK for PHP を使用した、サンプルテー ブルの作成とデータのアップロード (p. 617)」のトピックに記載されている手順に従って データをロードすることもできます。 以下の例を実行するための詳しい手順については、「PHP コードサンプル (p. 175)」を参照 してください。 $response = $dynamodb->getItem([ 'TableName' => 'ProductCatalog', 'Key' => [ 'Id' => [ 'N' => '104' ] ] ]); API Version 2012-08-10 276 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP print_r ($response['Item']); オプションパラメータの指定 必須のパラメータに加え、getItem 関数にはオプションパラメータも指定できます。たとえば、以下 の PHP コードスニペットでは、オプションメソッドを使用して、特定の属性リストのみを取り出し ます。また、強い整合性のある戻り値をリクエストします。このコードでは、以下のオプションパラ メータを指定します。 • 属性名の特定のリスト(Id や Authors など)。 • 強い整合性のある読み込み値をリクエストするブール値。読み込み結果は、デフォルトで結果整合 性があります。読み込み結果が強い整合性を持つようにリクエストできます。読み込み整合性の詳 細については、「読み込み整合性 (p. 16)」を参照してください。 $response = $dynamodb->getItem([ 'TableName' => 'ProductCatalog', 'Key' => [ 'Id' => ['N' => '104'], ], 'ProjectionExpression' => 'Id, Authors', 'ConsistentRead' => true ]); 詳細については、GetItem を参照してください。 バッチ書き込み: 複数の項目の書き込みおよび削除 AWS SDK for PHP batchWriteItem 関数を使用すると、単一のリクエスト内にある複数のテーブル に対して、複数の項目の置換または削除を実行することができます。 以下の PHP コードスニペットは、次の書き込みオペレーションを実行します。 • Forum テーブル内で項目を置換。 • Thread テーブルに対して項目の置換および削除を実行。 詳細については、BatchWriteItem を参照してください。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。あるいは、「AWS SDK for PHP を使用した、サンプルテー ブルの作成とデータのアップロード (p. 617)」のトピックに記載されている手順に従って データをロードすることもできます。 以下の例を実行するための詳しい手順については、「PHP コードサンプル (p. 175)」を参照 してください。 $tableNameOne = 'Forum'; $tableNameTwo = 'Thread'; $response = $dynamodb->batchWriteItem([ 'RequestItems' => [ API Version 2012-08-10 277 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP $tableNameOne => [ [ 'PutRequest' => [ 'Item' => [ 'Name' => ['S' => 'Amazon S3 Forum'], 'Threads' => ['N' => '0'] ]] ] ], $tableNameTwo => [ [ 'PutRequest' => [ 'Item' => [ 'ForumName' => ['S' => 'Amazon S3 Forum'], 'Subject' => ['S' => 'My sample question'], 'Message'=> ['S' => 'Message Text.'], 'KeywordTags'=>['SS' => ['Amazon S3', 'Bucket']] ]] ], [ 'DeleteRequest' => [ 'Key' => [ 'ForumName' =>['S' => 'Some partition key value'], 'Subject' => ['S' => 'Some sort key value'] ]] ] ] ] ]); print_r ($response['Item']); バッチ取得: 複数の項目の取得 AWS SDK for PHP の batchGetItem 関数を使用すると、1 つまたは複数のテーブルから複数の項目 を取得できます。単一の項目を取り出すために、getItem メソッドを使用できます。 次の PHP コードスニペットでは、Forum テーブル内の 2 つの項目、および Thread テーブル内の 3 つの項目を取り出します。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。あるいは、「AWS SDK for PHP を使用した、サンプルテー ブルの作成とデータのアップロード (p. 617)」のトピックに記載されている手順に従って データをロードすることもできます。 以下の例を実行するための詳しい手順については、「PHP コードサンプル (p. 175)」を参照 してください。 date_default_timezone_set('UTC'); $sevenDaysAgo = date('Y-m-d H:i:s', strtotime('-7 days')); $twentyOneDaysAgo = date('Y-m-d H:i:s', strtotime('-21 days')); $response = $dynamodb->batchGetItem([ 'RequestItems' => [ API Version 2012-08-10 278 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP 'Forum' => [ 'Keys' => [ [ 'Name' => [ 'S' => 'DynamoDB' ] ] ] ], 'Reply' => [ 'Keys' => [ [ 'Id' => [ 'S' => 'DynamoDB#DynamoDB Thread 2'], 'ReplyDateTime' => [ 'S' => $sevenDaysAgo], ], [ 'Id' => [ 'S' => 'DynamoDB#DynamoDB Thread 2'], 'ReplyDateTime' => [ 'S' => $twentyOneDaysAgo], ], ] ] ] ]); print_r($response['Responses']); オプションパラメータの指定 必須のパラメータに加え、batchGetItem 関数にはオプションパラメータも指定できます。たとえ ば、以下の PHP コードスニペットに示すように、取り出す属性のリストを指定することができます。 このコードでは、Forum テーブル内の 2 つの項目を取得し、ProjectionExpression パラメータを 使用して、各テーブル内のスレッド数を取り出します。 $response = $dynamodb->batchGetItem([ 'RequestItems' => [ 'Forum' => [ 'Keys' => [ [ 'Name' => [ 'S' => 'Amazon S3' ] ], [ 'Name' => [ 'S' => 'DynamoDB' ] ] ], 'ProjectionExpression' => 'Threads' ], ] ]); print_r($response); 詳細については、BatchGetItem を参照してください。 項目の更新 updateItem 関数を使用して、既存の属性値の更新、既存のコレクションへの新しい属性の追加、ま たは既存のコレクションからの属性の削除を実行します。 updateItem 関数は、以下のガイドラインに従います。 API Version 2012-08-10 279 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP • 項目が存在しない場合、updateItem 関数が、入力で指定したプライマリキーを使用して新しい項 目を追加します。 • 項目が存在する場合、updateItem 関数が以下のように更新を適用します。 • 既存の属性値を更新に含まれる値に置き換えます。 • 入力内で指定した属性が存在しない場合は、項目に新しい属性を追加します。 • Action に ADD を使用すると、既存のセット(文字列または数セット)に値を追加できます。ある いは、既存の数値属性の値に対して足し算(正の数を使用)したり、引き算(負の数を使用)す ることもできます。 Note putItem 関数(項目の置換 (p. 275))は項目も更新します。たとえば、putItem を使用し て項目をアップロードした場合にプライマリキーが存在すれば、 オペレーションによって項 目全体が置き換えられます。既存の項目内に属性がある場合、入力に指定されていない属性 は、putItem オペレーションによって削除されます。ただし、updateItem は指定された入 力属性のみを更新するため、その項目の他の既存の属性は変更されません。 次の PHP コードスニペットでは、ProductCatalog テーブルの書籍項目を更新します。この例で は、Authors のセットに著者を追加し、既存の ISBN 属性を削除します。また、価格を 1 引き下げま す。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。あるいは、「AWS SDK for PHP を使用した、サンプルテー ブルの作成とデータのアップロード (p. 617)」のトピックに記載されている手順に従って データをロードすることもできます。 以下の例を実行するための詳しい手順については、「PHP コードサンプル (p. 175)」を参照 してください。 $response = $dynamodb->updateItem([ 'TableName' => 'ProductCatalog', 'Key' => [ 'Id' => [ 'N' => '201' ] ], 'ExpressionAttributeValues' => [ ':val1' => [ 'S' => 'Author YY', 'S' => 'Author ZZ'], ':val2' => ['N' => '1'] ] , 'UpdateExpression' => 'set Authors = :val1, Price = Price - :val2 remove ISBN' ]); print_r($response); オプションパラメータの指定 必須のパラメータに加え、updateItem 関数にはオプションパラメータも指定できます。これには、 更新が発生する場合に属性に必要な期待値も含まれます。指定した条件を満たさない場合は、AWS SDK for PHP が ConditionalCheckFailedException をスローします。たとえば、以下の PHP API Version 2012-08-10 280 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP コードスニペットでは、書籍項目の価格を条件付きで 25 に更新します。以下のオプションパラメー タを指定します。 • ConditionExpression パラメータ。現在の価格が 20.00 USD である場合にのみ価格を更新する という条件を設定します。 • ReturnValues パラメータに対応する ALL_NEW 値。項目の更新後の現在の全属性値を応答に含め るよう指定します。 $response = $dynamodb->updateItem([ 'TableName' => 'ProductCatalog', 'Key' => [ 'Id' => [ 'N' => '201' ] ], 'ExpressionAttributeValues' => [ ':val1' => ['N' => '22'], ':val2' => ['N' => '20'] ] , 'UpdateExpression' => 'set Price = :val1', 'ConditionExpression' => 'Price = :val2', 'ReturnValues' => 'ALL_NEW' ]); print_r($response); 詳細については、UpdateItem を参照してください。 アトミックカウンター updateItem を使用してアトミックカウンターを実装できます。アトミックカウンターでは、他の書 き込みリクエストを妨げることなく、既存の属性の値をインクリメントまたはデクリメントします。 アトミックカウンタを更新するには、適切な UpdateExpression と共に updateItem を使用しま す。 次のコード例はアトミックカウンターを示しており、Quantity 属性を 1 ずつインクリメントさせてい ます。 $response = $dynamodb->updateItem([ 'TableName' => 'ProductCatalog', 'Key' => [ 'Id' => ['N' => '201'] ], 'ExpressionAttributeValues' => [ ':val1' => ['N' => '1'] ] , 'UpdateExpression' => 'set Quantity = Quantity + :val1', 'ReturnValues' => 'ALL_NEW' ]); print_r($response['Attributes']); 項目の削除 deleteItem 関数によって、テーブルから項目を削除します。 API Version 2012-08-10 281 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。あるいは、「AWS SDK for PHP を使用した、サンプルテー ブルの作成とデータのアップロード (p. 617)」のトピックに記載されている手順に従って データをロードすることもできます。 以下の例を実行するための詳しい手順については、「PHP コードサンプル (p. 175)」を参照 してください。 $response = $dynamodb->deleteItem([ 'TableName' => 'ProductCatalog', 'Key' => [ 'Id' => [ 'N' => '101' ] ] ]); print_r($response); オプションパラメータの指定 必須のパラメータに加え、deleteItem 関数にはオプションパラメータも指定できます。たとえば、 以下の PHP コードスニペットでは、以下のオプションパラメータを指定します。 • Expected パラメーター。対象の書籍が廃刊になっている場合にのみ ProductCatalog テーブル内の Id 値が「103」の Book 項目を削除するように指定します。具体的には、InPublication の属性が false の場合に、書籍を削除します。 • ReturnValues パラメータに対応する RETURN_ALL_OLD 列挙値。削除された項目およびその項目 の削除前の属性を応答に含めるようリクエストします。 $$tableName = 'ProductCatalog'; $response = $dynamodb->deleteItem ([ 'TableName' => $tableName, 'Key' => [ 'Id' => [ 'N' => '103' ] ], 'ExpressionAttributeValues' => [ ':val1' => ['BOOL' => false] ], 'ConditionExpression' => 'InPublication = :val1', 'ReturnValues' => 'ALL_OLD' ]); print_r($response); 詳細については、DeleteItem を参照してください。 API Version 2012-08-10 282 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP 例: AWS SDK for PHP の低レベル API を使用した CRUD オペ レーション 以下の PHP コード例は、項目に対する CRUD(作成、読み込み、更新、削除)オペレーションの例 です。この例では、項目の作成、項目の取得、さまざまな更新の実行、さらに項目の削除を行いま す。 Note 次に示すコード例を実行するための詳しい手順については、「PHP コードサンプ ル (p. 175)」を参照してください。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'ProductCatalog'; // ################################################################### // Adding data to the table echo "# Adding data to table $tableName...\n"; $response = $dynamodb->putItem([ 'TableName' => $tableName, 'Item' => [ 'Id' => ['N' => '120'], 'Title' => ['S' => 'Book 120 Title'], 'ISBN' => ['S' => '120-1111111111'], 'Authors' => ['SS' => ['Author12', 'Author22']], 'Price' => ['N' => '20'], 'Category' => ['S' => 'Book'], 'Dimensions' => ['S' => '8.5x11.0x.75'], 'InPublication' => ['BOOL' => false], ], 'ReturnConsumedCapacity' => 'TOTAL' ]); echo "Consumed capacity: " . $response ["ConsumedCapacity"] ["CapacityUnits"] . "\n"; $response = $dynamodb->putItem([ 'TableName' => $tableName, 'Item' => [ 'Id' => ['N' => '121'], 'Title' => ['S' => 'Book 121 Title'], API Version 2012-08-10 283 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP 'ISBN' => ['S' => '121-1111111111'], 'Authors' => ['SS' => ['Author21', 'Author22']], 'Price' => ['N' => '20'], 'Category' => ['S' => 'Book'], 'Dimensions' => ['S' => '8.5x11.0x.75'], 'InPublication' => ['BOOL' => true], ], 'ReturnConsumedCapacity' => 'TOTAL' ]); echo "Consumed capacity: " . $response ["ConsumedCapacity"] ["CapacityUnits"] . "\n"; // ################################################################### // Getting an item from the table echo "\n\n"; echo "# Getting an item from table $tableName...\n"; $response = $dynamodb->getItem ([ 'TableName' => $tableName, 'ConsistentRead' => true, 'Key' => [ 'Id' => [ 'N' => '120' ] ], 'ProjectionExpression' => 'Id, ISBN, Title, Authors' ] ); print_r ( $response ['Item'] ); // ################################################################### // Updating item attributes echo "\n\n"; echo "# Updating an item and returning the whole new item in table $tableName...\n"; $response = $dynamodb->updateItem ( [ 'TableName' => $tableName, 'Key' => [ 'Id' => [ 'N' => '120' //was 121 ] ], 'ExpressionAttributeNames' => [ '#NA' => 'NewAttribute', '#A' => 'Authors' ], 'ExpressionAttributeValues' => [ ':val1' => ['S' => 'Some Value'], ':val2' => ['SS' => ['Author YY','Author ZZ']] ] , 'UpdateExpression' => 'set #NA = :val1, #A = :val2', 'ReturnValues' => 'ALL_NEW' ]); print_r ( $response ['Attributes'] ); // ################################################################### API Version 2012-08-10 284 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP // Conditionally updating the Price attribute, only if it has not changed. echo "\n\n"; echo "# Updating an item attribute only if it has not changed in table $tableName...\n"; $response = $dynamodb->updateItem ( [ 'TableName' => $tableName, 'Key' => [ 'Id' => [ 'N' => '121' ] ], 'ExpressionAttributeNames' => [ '#P' => 'Price' ], 'ExpressionAttributeValues' => [ ':val1' => ['N' => '25'], ':val2' => ['N' => '20'], ], 'UpdateExpression' => 'set #P = :val1', 'ConditionExpression' => '#P = :val2', 'ReturnValues' => 'ALL_NEW' ]); print_r ( $response ['Attributes'] ); // ################################################################### // Deleting an item echo "\n\n"; echo "# Deleting an item and returning its previous values from in table $tableName...\n"; $response = $dynamodb->deleteItem ( [ 'TableName' => $tableName, 'Key' => [ 'Id' => [ 'N' => '121' ] ], 'ReturnValues' => 'ALL_OLD' ]); print_r ( $response ['Attributes']); ?> 例: AWS SDK for PHP を使用した、バッチオペレーション 例: AWS SDK for PHP を使用した、バッチ書き込みオペレーション 次の PHP コード例は、次のタスクを実行します。 • Forum テーブル内で項目を入力。 • Thread テーブル内で項目を入力および削除。 API Version 2012-08-10 285 Amazon DynamoDB 開発者ガイド 項目の操作 : PHP バッチ書き込みオペレーションの詳細については、「バッチ書き込み: 複数の項目の書き込みおよび削 除 (p. 277)」を参照してください。 このコード例では、「テーブルの作成とサンプルデータのロード (p. 166)」のステップに従って Forum テーブルと Thread テーブルを作成済みであると仮定します。あるいは、「AWS SDK for PHP を使用した、サンプルテーブルの作成とデータのアップロード (p. 617)」のトピックに記載する手順 に従って、プログラムでデータをロードすることもできます。 Note 次に示すコード例を実行するための詳しい手順については、「PHP コードサンプ ル (p. 175)」を参照してください。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableNameOne = 'Forum'; $tableNameTwo = 'Thread'; $response = $dynamodb->batchWriteItem([ 'RequestItems' => [ $tableNameOne => [ [ 'PutRequest' => [ 'Item' => [ 'Name' => ['S' => 'Amazon S3 Forum'], 'Threads' => ['N' => '0'] ]] ] ], $tableNameTwo => [ [ 'PutRequest' => [ 'Item' => [ 'ForumName' => ['S' => 'Amazon S3 Forum'], 'Subject' => ['S' => 'My sample question'], 'Message'=> ['S' => 'Message Text.'], 'KeywordTags'=>['SS' => ['Amazon S3', 'Bucket']] ]] ], [ 'DeleteRequest' => [ 'Key' => [ 'ForumName' =>['S' => 'Some partition key value'], 'Subject' => ['S' => 'Some sort key value'] ]] API Version 2012-08-10 286 Amazon DynamoDB 開発者ガイド クエリおよびスキャンの使用 ] ] ] ]); print_r($response); ?> クエリおよびスキャンの使用 トピック • Query (p. 287) • スキャン (p. 289) • クエリまたはスキャンからの結果のフィルタリング (p. 289) • クエリおよびスキャンオペレーションによって消費されるキャパシティーユニット (p. 290) • ページ単位の出力件数を指定 (p. 290) • 制限 (p. 290) • 応答での項目のカウント (p. 291) • 読み込み整合性 (p. 291) • クエリおよびスキャンのパフォーマンス (p. 292) • 並列スキャン (p. 292) • DynamoDB のクエリ (p. 294) • DynamoDB のスキャン (p. 310) Amazon DynamoDB では、プライマリキーを使用した項目へのアクセスに加えて、データの検索用に Query および Scan という 2 つのオペレーションも用意されています。 Tip テーブルのクエリと同じ方法で セカンダリインデックス のクエリまたはスキャンを実行で きます。これを行うには、Query または Scan に、パラメーターとして IndexName および TableName を指定する必要があります。詳細については、「セカンダリインデックスを使用 したデータアクセス性の向上 (p. 333)」を参照してください。 ベストプラクティスについては、クエリおよびスキャンのガイドライン (p. 581) を参照してくださ い。 Query Query オペレーションでは、プライマリキーの属性値を使用してテーブルまたは セカンダリインデッ クス の項目を検索します。パーティションキーの名前と検索対象の値を指定する必要があります。必 要に応じて、ソートキーの名前と値を指定し、比較演算子を使用して、検索結果をさらに絞り込むこ とができます。デフォルトでは、Query オペレーションは、指定したプライマリキーを持つ項目のす べてのデータ属性を返します。ただし、ProjectionExpression パラメーターを使用して、Query オペレーションがすべての属性ではなく一部の属性のみを返すようにすることもできます。 Query オペレーションでは、KeyConditionExpression パラメータを使用してテーブルまたはイン デックスから読み込む項目を決定します。等価条件としてパーティションキーの名前と値を指定する API Version 2012-08-10 287 Amazon DynamoDB 開発者ガイド Query 必要があります。オプションで、ソートキーに 2 番目の条件を指定できます (存在する場合)。ソート キーの条件では、次の比較演算子の 1 つを使用する必要があります。 • a = b - 属性 a が値 b と等しい場合、true • a < b - a が b より小さい場合、true • a <= b - a が b 以下である場合、true • a > b - a が b より大きい場合、true • a >= b - a が b 以上である場合、true • a BETWEEN b AND c - a が b 以上で、c 以下である場合、true。 次の関数もサポートされます。 • begins_with (a, substr) - 属性の値 a が特定のサブ文字列から始まる場合、true。 キー条件式のいくつかの例を次に示します。これらの式では、実際の値の代わりにプレースホルダー (:name や :subj など)を使用しています。詳細については、「式の属性名 (p. 213)」および「式 の属性値 (p. 215)」を参照してください。 • Thread テーブルに対して、特定の ForumName (パーティションキー) についてのクエリを実行し ます。その ForumName の値を持つすべての項目はクエリによって読み込まれます。これはソート キー (Subject) が KeyConditionExpression に含まれないためです。 ForumName = :name • Thread に対して、特定の ForumName (パーティションキー) についてのクエリを実行しますが、今 回は指定の Subject (ソートキー) を持つ項目のみを返します。 Forum = :name and Subject = :subj • Reply テーブルに対して、特定の Id (パーティションキー) についてのクエリを実行します が、ReplyDateTime (ソートキー) が特定の文字で始まる項目のみを返します。 Id = :id and begins_with(ReplyDateTime, :dt) 最初の文字が a-z または A-Z であり、2 番目の文字(ある場合)が a-z、A-Z、または 0-9 である場 合は、キー条件式で任意の属性値を使用できます。さらに、属性名は DynamoDB の予約語ではない 必要があります(フィールドの一覧については、「DynamoDB の予約語 (p. 668)」を参照してくだ さい)。属性名がこれらの要件を満たさない場合は、式の属性名をプレースホルダーとして定義する 必要があります。詳細については、「式の属性名 (p. 213)」を参照してください。 特定のパーティションキー値を持つ項目は、DynamoDB によって、ソートキーの値で並べ替えられた 順序で近くに配置されて保存されます。Query オペレーションでは、DynamoDB は並べ替えられた順 序で項目を取得し、KeyConditionExpression や存在する任意の FilterExpression を使用して 項目を処理します。その後、Query の結果がクライアントに返されます。 Query オペレーションは常に結果セットを返します。一致する項目が見つからない場合、結果セット は空になります。 Query の結果は常にソートキーの値によってソートされます。ソートキーのデータ型が Number であ る場合は、結果が番号順で返されます。その他の場合は、UTF-8 バイトの順序で結果が返されます。 デフォルトの並べ替え順序は昇順です。順序を反転させるには、ScanIndexForward パラメーター を false に設定します。 1 回の Query または Scan オペレーションで、最大 1 MB のデータを取得できます。この制限は、 結果への FilterExpression の適用前に適用されます。レスポンスに LastEvaluatedKey が存 在し、Null 以外の場合、結果セットをページ分割する必要があります (ページ単位の出力件数を指 定 (p. 290) を参照)。 API Version 2012-08-10 288 Amazon DynamoDB 開発者ガイド スキャン スキャン Scan オペレーションは、テーブルまたは セカンダリインデックス のすべての項目を読み込みます。 デフォルトでは、Scan オペレーションはテーブルまたはインデックスのすべての項目のデータ属性を 返します。ProjectionExpression パラメータを使用し、Scan がすべての属性ではなく一部のみを 返すようにできます。 Scan は常に結果セットを返します。一致する項目がない場合、結果セットは空になります。 1 回の Scan リクエストで、最大 1 MB のデータを取得できます。DynamoDB では、必要に応じて このデータにフィルタ式を適用して、結果をユーザーに返す前に絞り込むことができます。(フィル ターの詳細については「クエリまたはスキャンからの結果のフィルタリング (p. 289)」を参照)。 クエリまたはスキャンからの結果のフィルタリング Query または Scan オペレーションでは、必要に応じてフィルタ式を指定して、返された結果を絞り 込むことができます。フィルタ式では、データに条件を適用できます。条件は、データをクエリまた はスキャンした後、ユーザーに返す前に適用されます。条件を満たす項目のみが返されます。 フィルタ式のいくつかの例を次に示します。これらの式では、実際の値の代わりにプレースホルダー (:num や :name など)を使用しています。詳細については、「式の属性名 (p. 213)」および「式 の属性値 (p. 215)」を参照してください。 • Thread テーブルで特定の ForumName (パーティションキー) および Subject (ソートキー) に対する クエリを実行します。見つかった項目のうち、最も一般的なディスカッションスレッドだけを返し ます(たとえば、Views が特定の数を超えるスレッド)。 #V > :num Views は DynamoDB の予約語であるため(「DynamoDB の予約語 (p. 668)」を参照)、代わりに 式の属性名を使用していることに注意してください。 • Thread テーブルをスキャンして、特定のユーザーによって最後に投稿された項目のみを返します。 LastPostedBy = :name Note FilterExpression の構文は ConditionExpression と同じです。ま た、FilterExpression は、ConditionExpression と同じコンパレータ、関数、および 論理演算子を使用します。 Query オペレーションの場合、パーティションキーまたはソートキーに基づいて FilterExpression を定義することはできません (これは Sort オペレーションには適用さ れません)。 ConditionExpression 構文の詳細については、「条件式リファレンス (p. 217)」を参照 してください。 1 回の Query または Scan オペレーションで、最大 1 MB のデータを取得できます。この制限は、結 果への任意のフィルタ式の適用前に適用されます。 API Version 2012-08-10 289 Amazon DynamoDB 開発者ガイド クエリおよびスキャンオペレーションに よって消費されるキャパシティーユニット クエリおよびスキャンオペレーションによって消費 されるキャパシティーユニット テーブルを作成する場合には、読み込みおよび書き込みキャパシティーユニット要件を指定します。 テーブルにグローバルセカンダリインデックスを追加する場合、そのインデックスのスループット要 件も指定する必要があります。 Query および Scan オペレーションは、テーブルで使用するのと同じ方法でセカンダリインデックス で使用することができます。local secondary index で Query または Scan を実行する場合、キャパ シティーユニットはテーブルのプロビジョンドスループットから消費されます。ただし、これらのオ ペレーションをグローバルセカンダリインデックスで行うと、キャパシティーユニットは、インデッ クスのプロビジョニングされたスループットから消費されます。これは、グローバルセカンダリイン デックス には独自のプロビジョンドスループット設定があり、テーブルのものとは別になっているた めです。 オペレーションによって消費されるキャパシティーユニットを DynamoDB が計算する方法の詳細に ついては、「キャパシティーユニットの計算 (p. 181)」を参照してください。 Note Query と Scan のオペレーションの場合、DynamoDB では、アプリケーションに返 されるデータの量ではなく項目のサイズに基づいて、消費されるプロビジョンドス ループットの量が計算されます。このため、消費されるキャパシティーユニットの数 は、ProjectionExpression パラメーターで属性のすべてをリクエストしても(デフォル トの動作)一部をリクエストしても、同じになります。 消費されるキャパシティーユニットの数も、FilterExpression オペレーションを指定して も指定しなくても、同じになります。 ページ単位の出力件数を指定 DynamoDB では、Query および Scan オペレーションで得られた結果のページ分割を行うことができ ます。ページ分割を行うことで Query および Scan の結果が分割されるため、アプリケーションでは 結果の最初のページ、次に 2 番目のページというように、順次処理していくことができます。Query または Scan オペレーションによって返されるデータは、1 MB に限定されます。これは、結果セット のデータが 1 MB を超えた場合、新たに Query または Scan オペレーションを実行して次のデータを 1 MB 取得する必要があることを意味しています。 特定の属性に対するクエリまたはスキャンを実行して、一致する値の合計データが 1 MB を超える 場合には、次の 1 MB のデータに対する Query または Scan リクエストを別に実行する必要があり ます。そのためには、前のリクエストから LastEvaluatedKey の値を取得し、次のリクエストで ExclusiveStartKey として使用します。このアプローチにより、新しいデータを 1 MB ずつインク リメントさせて段階的にクエリまたはスキャンできるようになります。 Query または Scan からの結果セット全体が処理されると、LastEvaluatedKey は null になりま す。これは、結果セットが完了したこと(つまり、オペレーションによってデータの「最後のペー ジ」が処理されたこと)を意味します。 LastEvaluatedKey が null 以外の値の場合、結果セットにまだ値があることを必ずしも意味するわ けではありません。結果セットの最後まで到達したことを確認できるのは、LastEvaluatedKey が null になったときだけです。 制限 DynamoDB の Query および Scan API では、Limit の値によって結果のサイズを制限できます。 リクエストでは、Limit パラメータに、DynamoDB が結果を返す前に処理する項目数を設定します。 API Version 2012-08-10 290 Amazon DynamoDB 開発者ガイド 応答での項目のカウント 応答では、DynamoDB は Limit の値の範囲で一致したすべての結果を返します。たとえば、Limit 値が 6 でフィルタ式のない Query リクエストまたは Scan リクエストを発行した場合、DynamoDB は、リクエストで指定されたキー条件に一致するテーブル内の最初の 6 つの項目を返します(また は、フィルタのない Scan の場合はそのまま最初の 6 つの項目)。FilterExpression 値も指定し た場合、DynamoDB は、フィルタ要件にも一致する最初の 6 つの中から項目を返します(返される結 果の数は 6 以下です)。 Query または Scan オペレーションでは、テーブル内で一致する項目の一部が返されるとき は、DynamoDB によって LastEvaluatedKey の値が返される場合があります。一致する項目の 総数を取得するには、前のリクエストから LastEvaluatedKey の値を取得し、次のリクエストで ExclusiveStartKey の値として使用します。DynamoDB から LastEvaluatedKey の値が返されな くなるまで、この処理を繰り返します。 応答での項目のカウント Query または Scan オペレーションからの応答には、条件に一致する項目に加えて次の要素が含まれ ます。 • ScannedCount — フィルタ式が結果に適用される前にクエリまたはスキャンされた項目の数。 • Count — 応答で返された項目の数。 FilterExpression を使用しない場合、ScannedCount と Count は同じ値を持ちます。 1000 項目がある TestTable というテーブルがあり、各項目のサイズは正確に 250 バイトであると します。このテーブルに Scan (フィルタなし) を実行する場合、ScannedCount と Count は同じ 値 (1000) を持ちます。ここで、FilterExpression を追加し、300 項目のみが返されるとしま す。DynamoDB はそれでも 1000 個の項目を TestTable からすべて読み込みますが、条件に一致す る 300 項目を除くこれらのすべての結果を破棄します。この場合、ScannedCount は 1000 になりま すが、Count は 300 になります。 結果セットのサイズが 1 MB を超えた場合、ScannedCount および Count は、合計項目数の一部の 数のみを表します。TestTable に 100 万の項目があり、各項目のサイズが 250 KB であるとします。 この場合、テーブル全体をスキャンするために、複数の Scan リクエストを実行する必要がありま す。(詳細については、「ページ単位の出力件数を指定 (p. 290)」を参照してください)。各応答 には、特定の Scan リクエストによって処理された項目の ScannedCount および Count が含まれま す。すべての Scan リクエストの合計を取得するには、ScannedCount および Count の実行中の集 計を維持することができます。 読み込み整合性 クエリの読み込み整合性 Query の結果は結果整合性のある読み込みですが、必要に応じて強力な整合性のある読み込みを リクエストすることもできます。結果整合性のある読み込みには、最近完了した PutItem または UpdateItem オペレーションの結果が反映されない可能性があります。詳細については、「読み込み 整合性 (p. 16)」を参照してください。 スキャンの読み込み整合性 Scan リクエストを発行すると、DynamoDB は結果的に整合性のある読み込みを使用します。 つまり、テーブルでスキャンの実行直前に加えられたデータの変更は、スキャン結果に含まれ ない可能性があります。データの整合性のあるコピーが必要な場合は、Scan が開始する時間 に、ConsistentRead パラメーターを true に設定できます。これにより、Scan が開始する前に完了 した書き込みオペレーションがすべて Scan 応答に含められます。これは、 DynamoDB ストリーム と同時に使用すると、テーブルのバックアップまたはレプリケーションシナリオで役立ちます。最初 に、テーブル内のデータの整合性のあるコピーを取得するため、ConsistentRead を true に設定し API Version 2012-08-10 291 Amazon DynamoDB 開発者ガイド クエリおよびスキャンのパフォーマンス て Scan を使用します。Scan の実行中、DynamoDB ストリーム はテーブルで発生した追加の書き込 みアクティビティをすべて記録します。Scan が完了したら、ストリームからテーブルへの書き込みア クティビティを適用できます。 ConsistentRead を true に設定した Scan オペレーションでは、ConsistentRead をデフォルト値 (false) のままにした場合と比較して、2 倍の読み込みキャパシティーユニットが使用されます。 クエリおよびスキャンのパフォーマンス 一般的に、Query オペレーションは Scan オペレーションよりも効率的です。 Scan オペレーションでは常にテーブル全体またはセカンダリインデックスがスキャンされ、目的の結 果を得るために値にフィルタが適用され、基本的に結果セットからデータを削除するステップが追加 されます。フィルタによって多数の結果が除外されるようなサイズの大きいテーブルまたはインデッ クスでは、可能な限り Scan オペレーションを使用しないことをお勧めします。また、テーブルやイ ンデックスが大きくなるに従って、Scan オペレーションは低速になります。Scan オペレーションで は、リクエストした値に対するすべての項目が調べられるため、サイズの大きいテーブルまたはイン デックスでは、プロビジョニングされたスループットが 1 回のオペレーションで枯渇する可能性があ ります。高速な応答時間を得るには、アプリケーションが Scan ではなく Query を使用できるように テーブルとインデックスを設計します(テーブルの場合は、GetItem および BatchGetItem API の 使用を検討することもできます)。 または、Scan オペレーションを使用してもリクエスト率に対する影響が最小になるように、アプリ ケーションを設計します。詳細については、「クエリおよびスキャンのガイドライン (p. 581)」を参 照してください。 Query オペレーションは、指定した一連のキー条件を満たす特定範囲のキーを検索します。フィルタ 式を指定した場合、DynamoDB は結果セットからデータを削除する追加の手順を実行する必要があり ます。Query オペレーションでは、次のいずれかのイベントが発生するまで、指定された複合プライ マリキーまたは一定範囲のキーが検索されます。 • 結果セットが枯渇する。 • 取り出した項目数が、指定した Limit パラメータの値に達する。 • 取り出したデータの量が、結果セットの最大サイズ制限 1 MB に達する。 Query のパフォーマンスは、テーブルまたはセカンダリインデックス内のプライマリキーの全体数 ではなく、取り出されたデータの量によって決まります。クエリのパフォーマンスは、Query オペ レーションのパラメータ(および結果的に一致したキーの数)によって決まります。たとえば、1 つ のパーティションキー値に対するソートキー値の数が少ないテーブルに対するクエリよりも、1 つの パーティションキー値に対する多量のソートキー値が含まれる別のテーブルに対するクエリのほう が、最初のテーブルで一致するキーの数が 2 番目のテーブルよりも少ない場合には効率的です。どち らのテーブルでも、プライマリキーの合計数によって、Query オペレーションの効率性が決まること はありません。フィルタ式は Query オペレーションの効率に影響を与えることがあります。フィルタ に一致しない項目を結果セットから削除する必要があるためです。フィルタによって多数の結果が除 外されるようなサイズの大きいテーブルまたはセカンダリインデックスでは、可能な限り Query オペ レーションを使用しないことをお勧めします。 特定のパーティションキー値にサイズの大きいソートキー値のセットがあり、1 つの Query リクエス トでは結果を取り出せない場合には、ExclusiveStartKey 継続パラメーターによって、最後に取り 出した項目から新しいクエリリクエストを送信できます。すでに取り出されたデータを再処理する必 要はありません。 並列スキャン デフォルトでは、Scan オペレーションはデータを連続的に処理します。DynamoDB は 1 MB の増分 でアプリケーションにデータを返し、アプリケーションは追加の Scan オペレーションを実行して、 次の 1 MB 分のデータを取り出します。 API Version 2012-08-10 292 Amazon DynamoDB 開発者ガイド 並列スキャン スキャンされるテーブルまたはインデックスが大きいほど、Scan の完了に要する時間は長くなりま す。さらに、シーケンシャルな Scan では、プロビジョニングされた読み込みスループットキャパシ ティーが完全に利用されない場合があります。DynamoDB がサイズの大きいテーブルのデータを複 数の物理パーティションに分散しても、Scan オペレーションでは一度に 1 つのパーティションしか 読み込むことができません。そのため Scan のスループットは、単一のパーティションの最大スルー プットによって制限されます。 これらの問題に対処するために、Scan オペレーションではテーブルまたはセカンダリインデックスを 複数のセグメントに論理的に分割して、複数のアプリケーションワーカーがセグメントに対する並列 スキャンを行うことができます。各ワーカーは、スレッド(マルチスレッドをサポートするプログラ ミング言語を使用)またはオペレーティングシステムのプロセスにすることができます。並列スキャ ンを実行するには、各ワーカーが次のパラメータを使用して、別個に Scan リクエストを行います。 • Segment — 特定のワーカーがスキャンするセグメント。各ワーカーは Segment にそれぞれ異なる 値を指定します。 • TotalSegments — 並列スキャンの対象となるセグメントの合計数。この値は、アプリケーション で使用されるワーカーの数と同じでなければなりません。 次の図は、マルチスレッドアプリケーションが 3 段階の並列処理で実行する並列 Scan を示していま す。 API Version 2012-08-10 293 Amazon DynamoDB 開発者ガイド クエリ この図では、アプリケーションが 3 つのスレッドをスポーンして、各スレッドに番号を割り当ててい ます(セグメントはゼロベースであるため、最初の数字は必ず 0 になります)。各スレッドは Scan リクエストを発行し、Segment を指定された数値に設定して、TotalSegments を 3 に設定します。 各スレッドは指定されたセグメントをスキャンし、一度に 1 MB のデータを取り出し、アプリケー ションのメインスレッドにデータを返します。 Segment および TotalSegments の値は個々の Scan リクエストに適用され、また異なる値をいつ でも使用できます。これらの値、および使用するワーカー数を決定するには、アプリケーションのパ フォーマンスが最高になるまで実験を行う必要があるかもしれません。 Note 多数のワーカーで行う並列スキャンでは、スキャンされるテーブルまたはインデックスのた めにプロビジョニングされたスループットがすぐにすべて使用されます。テーブルまたはイ ンデックスでも他のアプリケーションからの重い読み込みや書き込みが発生させる場合は、 このようなスキャンは避けるのが最善です。 リクエストごとに返されるデータの量を制御するには、Limit パラメータを使用します。そ れによって、1 つのワーカーがプロビジョニングされたスループットを使い果たして、他の ワーカーが制約を受ける状況が避けられます。詳細については、「読み込みアクティビティ の急激な増大の回避 (p. 581)」の「ページサイズを小さくする」を参照してください。 DynamoDB のクエリ トピック • テーブルおよびインデックスにクエリを実行 : Java (p. 294) • テーブルおよびインデックスにクエリを実行: .NET (p. 300) • テーブルおよびインデックスにクエリを実行 : PHP (p. 307) このセクションでは、基本的なクエリとその結果を示します。 テーブルおよびインデックスにクエリを実行 : Java Query オペレーションを使用すると、テーブルまたは セカンダリインデックス をクエリできます。 この関数ではパーティションキー値と等価条件を指定する必要があります。テーブルまたはインデッ クスにソートキーがある場合は、ソートキー値と条件を指定することで結果を絞り込むことができま す。 Note SDK for Java には、オブジェクト永続性モデルも用意されています。このモデルにより、ク ライアント側のクラスを DynamoDB テーブルにマッピングすることができます。この方法 により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java: DynamoDBMapper (p. 78)」を参照してください。 次に、AWS SDK for Java ドキュメント API を使用して項目を取り出すステップを示します。 1. DynamoDB クラスのインスタンスを作成します。 2. 操作対象のテーブルを表すために、Table クラスのインスタンスを作成します。 3. Table インスタンスの query メソッドを呼び出します。任意のオプションクエリパラメーターと ともに、取得する項目のパーティションキー値を指定する必要があります。 応答には、クエリによって返されたすべての項目を示す ItemCollection オブジェクトが含まれて います。 API Version 2012-08-10 294 Amazon DynamoDB 開発者ガイド クエリ 次の Java コードスニペットは、前述のタスクの例です。このスニペットでは、フォーラムスレッド の返信を格納する Reply テーブルがあることを前提としています。詳細については、「テーブルの作 成とサンプルデータのロード (p. 166)」を参照してください。 Reply ( Id, ReplyDateTime, ... ) 各フォーラムスレッドには一意の ID があり、0 またはそれ以上の返信を受け取ることができます。つ まり、Reply テーブルの Id 属性は、フォーラム名とフォーラムの件名の両方で構成されています。Id (パーティションキー) と ReplyDateTime (ソートキー) が、テーブルの複合プライマリキーを構成して います。 次のクエリでは、特定のスレッド件名に対するすべての返信を取り出します。このクエリでは、テー ブル名と件名の両方が必要になります。 DynamoDB dynamoDB = new DynamoDB( new AmazonDynamoDBClient(new ProfileCredentialsProvider())); Table table = dynamoDB.getTable("Reply"); QuerySpec spec = new QuerySpec() .withKeyConditionExpression("Id = :v_id") .withValueMap(new ValueMap() .withString(":v_id", "Amazon DynamoDB#DynamoDB Thread 1")); ItemCollection<QueryOutcome> items = table.query(spec); Iterator<Item> iterator = items.iterator(); Item item = null; while (iterator.hasNext()) { item = iterator.next(); System.out.println(item.toJSONPretty()); } オプションパラメータの指定 query メソッドでは、複数のオプションパラメータがサポートされています。たとえば、必要に応じ て条件を指定して前述のクエリの結果を絞り込み、過去 2 週間の返信が返されるようにできます。こ の条件をソートキー条件と呼びます。指定したクエリ条件が DynamoDB によってプライマリキーの ソートキーに対して評価されるためです。その他のオプションパラメータを指定して、クエリ結果の 項目から特定の属性のリストだけを取り出すこともできます。 次の Java コードスニペットでは、過去 15 日間に投稿されたフォーラムスレッドの返信が取り出され ます。このスニペットでは、次のものを使用してオプションパラメータを指定しています。 • KeyConditionExpression - 特定のディスカッションフォーラムからの返信を取得し (パーティ ションキー)、その項目のセット内では、過去 15 日の間に投稿された返信を取得します (ソート キー)。 • FilterExpression - 特定のユーザーからの返信だけを返します。フィルタは、クエリの処理の終 了後、ユーザーに結果が返される前に適用されます。 • ValueMap - KeyConditionExpression プレースホルダーの実際の値を定義します。 • ConsistentRead - true に設定すると、強力な整合性のある読み込みをリクエストします。 このスニペットでは、すべての低レベルクエリ入力パラメータにアクセスできる QuerySpec オブ ジェクトを使用します。 API Version 2012-08-10 295 Amazon DynamoDB 開発者ガイド クエリ Table table = dynamoDB.getTable("Reply"); long twoWeeksAgoMilli = (new Date()).getTime() - (15L*24L*60L*60L*1000L); Date twoWeeksAgo = new Date(); twoWeeksAgo.setTime(twoWeeksAgoMilli); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); String twoWeeksAgoStr = df.format(twoWeeksAgo); QuerySpec spec = new QuerySpec() .withKeyConditionExpression("Id = :v_id and ReplyDateTime > :v_reply_dt_tm") .withFilterExpression("PostedBy = :v_posted_by") .withValueMap(new ValueMap() .withString(":v_id", "Amazon DynamoDB#DynamoDB Thread 1") .withString(":v_reply_dt_tm", twoWeeksAgoStr) .withString(":v_posted_by", "User B")) .withConsistentRead(true); ItemCollection<QueryOutcome> items = table.query(spec); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } また、withMaxPageSize メソッドを使用して、ページあたりの項目数を制限することもできま す。query メソッドを呼び出すと、結果の項目が含まれている ItemCollection が返されます。そ の後、結果を 1 ページずつ、最後のページまで処理していくことができます。 次の Java コードスニペットは、上記のクエリの仕様を変更します。今回、クエリの仕様は withMaxPageSize メソッドを使用します。Page クラスには、コードが各ページの項目を処理でき るようにするイテレータがあります。 spec.withMaxPageSize(10); ItemCollection<QueryOutcome> items = table.query(spec); // Process each page of results int pageNum = 0; for (Page<Item, QueryOutcome> page : items.pages()) { System.out.println("\nPage: " + ++pageNum); // Process each item on the current page Iterator<Item> item = page.iterator(); while (item.hasNext()) { System.out.println(item.next().toJSONPretty()); } } 例 – Java を使用したクエリ 以下のテーブルには、フォーラムのコレクションに関する情報が格納されています。詳細について は、「テーブルの作成とサンプルデータのロード (p. 166)」を参照してください。 API Version 2012-08-10 296 Amazon DynamoDB 開発者ガイド クエリ Note SDK for Java には、オブジェクト永続性モデルも用意されています。このモデルにより、ク ライアント側のクラスを DynamoDB テーブルにマッピングすることができます。この方法 により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java: DynamoDBMapper (p. 78)」を参照してください。 Forum ( Name, ... ) Thread ( ForumName, Subject, Message, LastPostedBy, LastPostDateTime, ...) Reply ( Id, ReplyDateTime, Message, PostedBy, ...) この Java コード例では、"DynamoDB" フォーラムで "DynamoDB Thread 1" スレッドに対する返信を 検索するのバリエーションを実行します。 • スレッドに対する返信を検索します。 • 結果のページあたりの項目数に対する制限を指定して、スレッドへの返信を探します。結果セット の項目数がページサイズを超えた場合は、結果の最初のページだけが得られます。このコーディン グパターンによって、確実にクエリ結果の全ページがコードで処理されます。 • 過去 15 日間の返信を検索します。 • 特定の日付範囲の返信を検索します。 前述の 2 つのクエリはどちらも、ソートキー条件を指定してクエリ結果を絞り込む方法、必要に応 じてその他のクエリパラメーターを使用する方法を示しています。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。 以下の例を実行するための詳しい手順については、「Java コードサンプル (p. 171)」を参照 してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import import import import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.ItemCollection; com.amazonaws.services.dynamodbv2.document.Page; com.amazonaws.services.dynamodbv2.document.QueryOutcome; com.amazonaws.services.dynamodbv2.document.Table; com.amazonaws.services.dynamodbv2.document.spec.QuerySpec; com.amazonaws.services.dynamodbv2.document.utils.ValueMap; public class DocumentAPIQuery { API Version 2012-08-10 297 Amazon DynamoDB 開発者ガイド クエリ static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider())); static String tableName = "Reply"; public static void main(String[] args) throws Exception { String forumName = "Amazon DynamoDB"; String threadSubject = "DynamoDB Thread 1"; findRepliesForAThread(forumName, threadSubject); findRepliesForAThreadSpecifyOptionalLimit(forumName, threadSubject); findRepliesInLast15DaysWithConfig(forumName, threadSubject); findRepliesPostedWithinTimePeriod(forumName, threadSubject); findRepliesUsingAFilterExpression(forumName, threadSubject); } private static void findRepliesForAThread(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withKeyConditionExpression("Id = :v_id") .withValueMap(new ValueMap() .withString(":v_id", replyId)); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesForAThread results:"); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } } private static void findRepliesForAThreadSpecifyOptionalLimit(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withKeyConditionExpression("Id = :v_id") .withValueMap(new ValueMap() .withString(":v_id", replyId)) .withMaxPageSize(1); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesForAThreadSpecifyOptionalLimit results:"); API Version 2012-08-10 298 Amazon DynamoDB 開発者ガイド クエリ // Process each page of results int pageNum = 0; for (Page<Item, QueryOutcome> page : items.pages()) { System.out.println("\nPage: " + ++pageNum); // Process each item on the current page Iterator<Item> item = page.iterator(); while (item.hasNext()) { System.out.println(item.next().toJSONPretty()); } } } private static void findRepliesInLast15DaysWithConfig(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); long twoWeeksAgoMilli = (new Date()).getTime() (15L*24L*60L*60L*1000L); Date twoWeeksAgo = new Date(); twoWeeksAgo.setTime(twoWeeksAgoMilli); SimpleDateFormat df = new SimpleDateFormat("yyyy-MMdd'T'HH:mm:ss.SSS'Z'"); String twoWeeksAgoStr = df.format(twoWeeksAgo); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withProjectionExpression("Message, ReplyDateTime, PostedBy") .withKeyConditionExpression("Id = :v_id and ReplyDateTime <= :v_reply_dt_tm") .withValueMap(new ValueMap() .withString(":v_id", replyId) .withString(":v_reply_dt_tm", twoWeeksAgoStr)); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesInLast15DaysWithConfig results:"); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } } private static void findRepliesPostedWithinTimePeriod(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); long startDateMilli = (new Date()).getTime() (15L*24L*60L*60L*1000L); long endDateMilli = (new Date()).getTime() - (5L*24L*60L*60L*1000L); java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyyMM-dd'T'HH:mm:ss.SSS'Z'"); String startDate = df.format(startDateMilli); API Version 2012-08-10 299 Amazon DynamoDB 開発者ガイド クエリ String endDate = df.format(endDateMilli); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withProjectionExpression("Message, ReplyDateTime, PostedBy") .withKeyConditionExpression("Id = :v_id and ReplyDateTime between :v_start_dt and :v_end_dt") .withValueMap(new ValueMap() .withString(":v_id", replyId) .withString(":v_start_dt", startDate) .withString(":v_end_dt", endDate)); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesPostedWithinTimePeriod results:"); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } } private static void findRepliesUsingAFilterExpression(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withProjectionExpression("Message, ReplyDateTime, PostedBy") .withKeyConditionExpression("Id = :v_id") .withFilterExpression("PostedBy = :v_postedby") .withValueMap(new ValueMap() .withString(":v_id", replyId) .withString(":v_postedby", "User B")); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesUsingAFilterExpression results:"); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } } } テーブルおよびインデックスにクエリを実行: .NET Query オペレーションを使用すると、テーブルまたは セカンダリインデックス をクエリできます。 この関数ではパーティションキー値と等価条件を指定する必要があります。テーブルまたはインデッ クスにソートキーがある場合は、ソートキー値と条件を指定することで結果を絞り込むことができま す。 API Version 2012-08-10 300 Amazon DynamoDB 開発者ガイド クエリ 次に、低レベル .NET SDK API を使用してテーブルのクエリを行うステップを示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. QueryRequest クラスのインスタンスを作成して、クエリオペレーションパラメータを指定しま す。 3. Query メソッドを実行し、前述のステップで作成した QueryRequest オブジェクトを指定しま す。 応答には、クエリによって返されたすべての項目を示す QueryResult オブジェクトが含まれてい ます。 次の C# コードスニペットは、前述のタスクの例です。このスニペットでは、フォーラムスレッドの 返信を格納する Reply テーブルがあることを前提としています。詳細については、「テーブルの作成 とサンプルデータのロード (p. 166)」を参照してください。 Reply ( <emphasis role="underline">Id</emphasis>, <emphasis role="underline">ReplyDateTime</emphasis>, ... ) 各フォーラムスレッドには一意の ID があり、0 またはそれ以上の返信を受け取ることができます。し たがってプライマリキーは、Id (パーティションキー) と ReplyDateTime (ソートキー) の両方で構成さ れます。 次のクエリでは、特定のスレッド件名に対するすべての返信を取り出します。このクエリでは、テー ブル名と件名の両方が必要になります。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); var request = new QueryRequest { TableName = "Reply", KeyConditionExpression = "Id = :v_Id", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_Id", new AttributeValue { S = "Amazon DynamoDB#DynamoDB Thread 1" }}} }; var response = client.Query(request); foreach (Dictionary<string, AttributeValue> item in response.Items) { // Process the result. PrintItem(item); } オプションパラメータの指定 Query メソッドでは、複数のオプションパラメータがサポートされています。たとえば、必要に応じ て条件を指定して前述のクエリの結果を絞り込み、過去 2 週間の返信が返されるようにできます。こ の条件をソートキー条件と呼びます。指定したクエリ条件が Amazon DynamoDB によってプライマリ キーのソートキーに対して評価されるためです。その他のオプションパラメータを指定して、クエリ 結果の項目から特定の属性のリストだけを取り出すこともできます。詳細については、Query を参照 してください。 次の C# コードスニペットでは、過去 15 日間に投稿されたフォーラムスレッドの返信が取り出されま す。このスニペットでは、次のオプションパラメータが指定されています。 • 過去 15 日間の返信だけを取り出す KeyConditionExpression。 API Version 2012-08-10 301 Amazon DynamoDB 開発者ガイド クエリ • クエリ結果内の項目について取得する属性のリストを指定する ProjectionExpression パラメー タ。 • 強力な整合性のある読み込みを実行する ConsistentRead パラメータ。 DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15); string twoWeeksAgoString = twoWeeksAgoDate.ToString(AWSSDKUtils.ISO8601DateFormat); var request = new QueryRequest { TableName = "Reply", KeyConditionExpression = "Id = :v_Id and ReplyDateTime > :v_twoWeeksAgo", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_Id", new AttributeValue { S = "Amazon DynamoDB#DynamoDB Thread 2" }}, {":v_twoWeeksAgo", new AttributeValue { S = twoWeeksAgoString }} }, ProjectionExpression = "Subject, ReplyDateTime, PostedBy", ConsistentRead = true }; var response = client.Query(request); foreach (Dictionary<string, AttributeValue> item in response.Items) { // Process the result. PrintItem(item); } また、オプションの Limit パラメータを追加することで、ページサイズ、またはページあたりの項 目数を制限することもできます。Query メソッドを実行するたびに、指定された数の項目が含まれる 結果が 1 ページ取得されます。次のページをフェッチするには、前ページの最後の項目のプライマリ キーの値を入力して次の項目のセットが返されるようにし、Query メソッドを再度実行します。この 情報は、ExclusiveStartKey プロパティを設定することでリクエストに含めます。このプロパティ は最初は null である場合があります。以降のページを取り出すには、このプロパティ値を更新して、 前ページの最後の項目のプライマリキーにする必要があります。 次の C# コードスニペットでは、Reply テーブルのクエリを実行しています。リクエストでは、オ プションの Limit および ExclusiveStartKey パラメータを指定しています。do/while ループ は、LastEvaluatedKey から null 値が返されるまで、一度に 1 ページのスキャンを継続します。 Dictionary<string,AttributeValue> lastKeyEvaluated = null; do { var request = new QueryRequest { TableName = "Reply", KeyConditionExpression = "Id = :v_Id", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_Id", new AttributeValue { S = "Amazon DynamoDB#DynamoDB Thread 2" }} }, // Optional parameters. Limit = 1, API Version 2012-08-10 302 Amazon DynamoDB 開発者ガイド クエリ ExclusiveStartKey = lastKeyEvaluated }; var response = client.Query(request); // Process the query result. foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } lastKeyEvaluated = response.LastEvaluatedKey; } while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0); 例 – AWS SDK for .NET を使用したクエリ 以下のテーブルには、フォーラムのコレクションに関する情報が格納されています。詳細について は、「テーブルの作成とサンプルデータのロード (p. 166)」を参照してください。 Forum ( <emphasis role="underline">Name</emphasis>, ... ) Thread ( <emphasis role="underline">ForumName</emphasis>, <emphasis role="underline">Subject</emphasis>, Message, LastPostedBy, LastPostDateTime, ...) Reply ( <emphasis role="underline">Id</emphasis>, <emphasis role="underline">ReplyDateTime</emphasis>, Message, PostedBy, ...) この C# コード例では、"DynamoDB" フォーラムで "DynamoDB Thread 1" スレッドに対する返信を検 索するのバリエーションを実行します。 • スレッドに対する返信を検索します。 • スレッドに対する返信を検索します。Limit クエリパラメータを指定してページサイズを設定しま す。 この機能は、ページ分割を使用した、複数ページのクエリ結果の処理を示しています。Amazon DynamoDB にはページサイズ制限があり、クエリ結果がページサイズを超えた場合には、結果のう ち最初の 1 ページ分だけが得られます。このコーディングパターンによって、確実にクエリ結果の 全ページがコードで処理されます。 • 過去 15 日間の返信を検索します。 • 特定の日付範囲の返信を検索します。 前述の 2 つのクエリはどちらも、ソートキー条件を指定してクエリ結果を絞り込む方法、必要に応 じてその他のクエリパラメーターを使用する方法を示しています。 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照し てください。 using using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.Model; Amazon.Runtime; Amazon.Util; namespace com.amazonaws.codesamples { API Version 2012-08-10 303 Amazon DynamoDB 開発者ガイド クエリ class LowLevelQuery { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { // Query a specific forum and thread. string forumName = "Amazon DynamoDB"; string threadSubject = "DynamoDB Thread 1"; FindRepliesForAThread(forumName, threadSubject); FindRepliesForAThreadSpecifyOptionalLimit(forumName, threadSubject); FindRepliesInLast15DaysWithConfig(forumName, threadSubject); FindRepliesPostedWithinTimePeriod(forumName, threadSubject); Console.WriteLine("Example complete. To continue, press Enter"); Console.ReadLine(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); Console.ReadLine(); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); Console.ReadLine(); } catch (Exception e) { Console.WriteLine(e.Message); Console.ReadLine(); } } private static void FindRepliesPostedWithinTimePeriod(string forumName, string threadSubject) { Console.WriteLine("*** Executing FindRepliesPostedWithinTimePeriod() ***"); string replyId = forumName + "#" + threadSubject; // You must provide date value based on your test data. DateTime startDate = DateTime.UtcNow - TimeSpan.FromDays(21); string start = startDate.ToString(AWSSDKUtils.ISO8601DateFormat); // You provide date value based on your test data. DateTime endDate = DateTime.UtcNow - TimeSpan.FromDays(5); string end = endDate.ToString(AWSSDKUtils.ISO8601DateFormat); var request = new QueryRequest { TableName = "Reply", ReturnConsumedCapacity = "TOTAL", KeyConditionExpression = "Id = :v_replyId and ReplyDateTime between :v_start and :v_end", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_replyId", new AttributeValue { S = replyId }}, {":v_start", new AttributeValue { S = start }}, API Version 2012-08-10 304 Amazon DynamoDB 開発者ガイド クエリ {":v_end", new AttributeValue { S = end }} } }; var response = client.Query(request); Console.WriteLine("\nNo. of reads used (by query in FindRepliesPostedWithinTimePeriod) {0}", response.ConsumedCapacity.CapacityUnits); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void FindRepliesInLast15DaysWithConfig(string forumName, string threadSubject) { Console.WriteLine("*** Executing FindRepliesInLast15DaysWithConfig() ***"); string replyId = forumName + "#" + threadSubject; DateTime twoWeeksAgoDate = DateTime.UtcNow TimeSpan.FromDays(15); string twoWeeksAgoString = twoWeeksAgoDate.ToString(AWSSDKUtils.ISO8601DateFormat); var request = new QueryRequest { TableName = "Reply", ReturnConsumedCapacity = "TOTAL", KeyConditionExpression = "Id = :v_replyId and ReplyDateTime > :v_interval", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_replyId", new AttributeValue { S = replyId }}, {":v_interval", new AttributeValue { S = twoWeeksAgoString }} }, // Optional parameter. ProjectionExpression = "Id, ReplyDateTime, PostedBy", // Optional parameter. ConsistentRead = true }; var response = client.Query(request); Console.WriteLine("No. of reads used (by query in FindRepliesInLast15DaysWithConfig) {0}", response.ConsumedCapacity.CapacityUnits); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } API Version 2012-08-10 305 Amazon DynamoDB 開発者ガイド クエリ Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void FindRepliesForAThreadSpecifyOptionalLimit(string forumName, string threadSubject) { Console.WriteLine("*** Executing FindRepliesForAThreadSpecifyOptionalLimit() ***"); string replyId = forumName + "#" + threadSubject; Dictionary<string, AttributeValue> lastKeyEvaluated = null; do { var request = new QueryRequest { TableName = "Reply", ReturnConsumedCapacity = "TOTAL", KeyConditionExpression = "Id = :v_replyId", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_replyId", new AttributeValue { S = replyId }} }, Limit = 2, // The Reply table has only a few sample items. So the page size is smaller. ExclusiveStartKey = lastKeyEvaluated }; var response = client.Query(request); Console.WriteLine("No. of reads used (by query in FindRepliesForAThreadSpecifyLimit) {0}\n", response.ConsumedCapacity.CapacityUnits); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } lastKeyEvaluated = response.LastEvaluatedKey; } while (lastKeyEvaluated != null && lastKeyEvaluated.Count ! = 0); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void FindRepliesForAThread(string forumName, string threadSubject) { Console.WriteLine("*** Executing FindRepliesForAThread() ***"); string replyId = forumName + "#" + threadSubject; var request = new QueryRequest { TableName = "Reply", ReturnConsumedCapacity = "TOTAL", API Version 2012-08-10 306 Amazon DynamoDB 開発者ガイド クエリ KeyConditionExpression = "Id = :v_replyId", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_replyId", new AttributeValue { S = replyId }} } }; var response = client.Query(request); Console.WriteLine("No. of reads used (by query in FindRepliesForAThread) {0}\n", response.ConsumedCapacity.CapacityUnits); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void PrintItem( Dictionary<string, AttributeValue> attributeList) { foreach (KeyValuePair<string, AttributeValue> kvp in attributeList) { string attributeName = kvp.Key; AttributeValue value = kvp.Value; Console.WriteLine( attributeName + " " + (value.S == null ? "" : "S=[" + (value.N == null ? "" : "N=[" + (value.SS == null ? "" : "SS=[" value.SS.ToArray()) + "]") + (value.NS == null ? "" : "NS=[" value.NS.ToArray()) + "]") ); } value.S + "]") + value.N + "]") + + string.Join(",", + string.Join(",", Console.WriteLine("************************************************"); } } } テーブルおよびインデックスにクエリを実行 : PHP query 関数を使用すると、テーブルまたは セカンダリインデックス をクエリできます。この関数で はパーティションキー値と等価条件を指定する必要があります。テーブルまたはインデックスにソー トキーがある場合は、ソートキー値と条件を指定することで結果を絞り込むことができます。 以下に、AWS SDK for PHP を使用した一般的な手順を示します。 1. DynamoDB クライアントのインスタンスを作成します。 2. オプションのパラメーターを含む DynamoDB オペレーションのパラメーターを指定します。 3. DynamoDB からの応答をアプリケーションのローカル変数にロードします。 API Version 2012-08-10 307 Amazon DynamoDB 開発者ガイド クエリ フォーラムスレッドに対する返信を格納する、次のような Reply テーブルがあるとします。 Reply ( Id, ReplyDateTime, ... ) 各フォーラムスレッドには一意の ID があり、0 またはそれ以上の返信を受け取ることができます。し たがってプライマリキーは、Id (パーティションキー) と ReplyDateTime (ソートキー) の両方で構成さ れます。 次のクエリでは、特定のスレッド件名に対するすべての返信を取り出します。このクエリでは、テー ブル名と件名が必要になります。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。あるいは、「AWS SDK for PHP を使用した、サンプルテー ブルの作成とデータのアップロード (p. 617)」のトピックに記載されている手順に従って データをロードすることもできます。 以下の例を実行するための詳しい手順については、「PHP コードサンプル (p. 175)」を参照 してください。 require 'vendor/autoload.php'; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $response = $dynamodb->query([ 'TableName' => 'Reply', 'KeyConditionExpression' => 'Id = :v_id', 'ExpressionAttributeValues' => [ ':v_id' => ['S' => 'Amazon DynamoDB#DynamoDB Thread 1'] ] ]); print_r($response['Items']); オプションパラメータの指定 query 関数では、複数のオプションパラメータがサポートされています。たとえば、必要に応じて ソートキー条件を指定して前述のクエリの結果を絞り込み、過去 2 週間の返信が返されるようにでき ます。条件は、ソートキー条件と呼ばれます。これは、指定したクエリ条件を DynamoDB がソート キーに対して評価するためです。その他のオプションパラメータを指定して、クエリ結果の項目から 特定の属性のリストを取り出すこともできます。パラメータの詳細については、Query を参照してく ださい。 次の PHP コード例では、過去 7 日間に投稿されたフォーラムスレッドの返信が取り出されます。こ のサンプルでは、次のオプションパラメータが指定されています。 • 過去 7 日間の返信だけを取り出す、KeyConditionExpression パラメーターのソートキー。 この条件によって、日付の比較に使用する ReplyDateTime の値と比較演算子を指定します。 API Version 2012-08-10 308 Amazon DynamoDB 開発者ガイド クエリ • クエリ結果内の項目について取り出す属性を指定する ProjectionExpression パラメータ。 • 強力な整合性のある読み込みを実行する ConsistentRead パラメータ。これにより、結果整合性 のある読み込みを実行するデフォルトの動作がオーバーライドされます。読み込み整合性の詳細に ついては、「読み込み整合性 (p. 16)」を参照してください。 $sevenDaysAgo = date('Y-m-d H:i:s', strtotime('-7 days')); $response = $dynamodb->query([ 'TableName' => 'Reply', 'KeyConditionExpression' => 'Id = :v_id and ReplyDateTime >= :v_reply_dt', 'ExpressionAttributeValues' => [ ':v_id' => ['S' => 'Amazon DynamoDB#DynamoDB Thread 2'], ':v_reply_dt' => ['S' => $sevenDaysAgo] ], // optional parameters 'ProjectionExpression' => 'Subject, ReplyDateTime, PostedBy', 'ConsistentRead' => true ]); print_r($response['Items']); Limit パラメータを追加することで、ページサイズ、またはページあたりの項目数を制限することも できます。query 機能を実行するたびに、指定された数の項目が含まれる結果が 1 ページ取得されま す。次のページをフェッチするには、前ページの最後の項目のプライマリキーの値を入力して次の項 目のセットが返されるようにし、query 機能を再度実行します。この情報は、ExclusiveStartKey プロパティを設定することでリクエストに含めます。このプロパティは最初は null である場合があり ます。以降のページを取り出すには、このプロパティ値を更新して、前ページの最後の項目のプライ マリキーにする必要があります。 次の PHP コード例では、14 日を経過したエントリについて、Reply テーブルのクエリを行っていま す。リクエストでは、オプションの Limit および ExclusiveStartKey パラメータを指定していま す。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $fourteenDaysAgo = date('Y-m-d H:i:s', strtotime('-14 days')); $tableName = 'Reply'; # The Query API is paginated. Issue the Query request multiple times. do { echo "Querying table $tableName\n"; $request = [ 'TableName' => $tableName, API Version 2012-08-10 309 Amazon DynamoDB 開発者ガイド スキャニング 'KeyConditionExpression' => 'Id = :v_id and ReplyDateTime >= :v_reply_dt', 'ExpressionAttributeValues' => [ ':v_id' => ['S' => 'Amazon DynamoDB#DynamoDB Thread 2'], ':v_reply_dt' => ['S' => $fourteenDaysAgo] ], 'ProjectionExpression' => 'Id, ReplyDateTime, Message, PostedBy', 'ConsistentRead' => true, 'Limit' => 1 ]; # Add the ExclusiveStartKey if we got one back in the previous response if(isset($response) && isset($response['LastEvaluatedKey'])) { $request['ExclusiveStartKey'] = $response['LastEvaluatedKey']; } $response = $dynamodb->query($request); foreach ($response['Items'] as $key => $value) { echo 'Id: ' . $value['Id']['S'] . "\n"; echo 'ReplyDateTime: ' . $value['ReplyDateTime']['S'] . "\n"; echo 'Message: ' . $value['Message']['S'] . "\n"; echo 'PostedBy: ' . $value['PostedBy']['S'] . "\n"; echo "\n"; } # If there is no LastEvaluatedKey in the response, then # there are no more items matching this Query } while(isset($response['LastEvaluatedKey'])); ?> DynamoDB のスキャン トピック • テーブルおよびインデックスのスキャン: Java (p. 310) • テーブルおよびインデックスのスキャン: .NET (p. 318) • スキャンテーブルとインデックス : PHP (p. 327) このセクションでは、基本的なスキャンとその結果を示します。 テーブルおよびインデックスのスキャン: Java Scan オペレーションは、テーブルまたはインデックスの全項目を読み込みます。 スキャンおよび クエリオペレーションに関するパフォーマンスの詳細については、「クエリおよびスキャンの使 用 (p. 287)」を参照してください。 以下に、AWS SDK for Java ドキュメント API を使用してテーブルをスキャンする手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. ScanRequest クラスのインスタンスを作成し、スキャンパラメータを指定します。 必須のパラメータは、テーブル名だけです。 3. scan メソッドを実行し、前述のステップで作成した ScanRequest オブジェクトを指定します。 API Version 2012-08-10 310 Amazon DynamoDB 開発者ガイド スキャニング 以下の Reply テーブルに、フォーラムスレッドに対する応答が格納されます。 Reply ( Id, ReplyDateTime, Message, PostedBy ) このテーブルには、さまざまなフォーラムスレッドに対するすべての応答が保持されています。 したがってプライマリキーは、Id (パーティションキー) と ReplyDateTime (ソートキー) の両方で 構成されます。以下の Java コードスニペットは、テーブル全体をスキャンする例を示していま す。ScanRequest インスタンスで、スキャン対象のテーブルの名前を指定します。 AmazonDynamoDBClient client = new AmazonDynamoDBClient( new ProfileCredentialsProvider()); ScanRequest scanRequest = new ScanRequest() .withTableName("Reply"); ScanResult result = client.scan(scanRequest); for (Map<String, AttributeValue> item : result.getItems()){ printItem(item); } オプションパラメータの指定 scan メソッドでは、複数のオプションパラメータがサポートされています。たとえば、オプション として、フィルタ式を使用してスキャン結果をフィルタリングすることができます。フィルタ式で、 条件や、条件の評価対象となる属性名と値を指定できます。詳細については、Scan を参照してくださ い。 以下の Java コードスニペットは、ProductCatalog テーブルをスキャンして、価格が 0(ゼロ)未満 の項目を検索する例を示しています。このスニペットでは、次のオプションパラメータが指定されて います。 • 価格が 0 未満の項目のみを取り出すフィルタ式(エラー条件)。 • クエリ結果内の項目について取り出す属性のリスト。 Map<String, AttributeValue> expressionAttributeValues = new HashMap<String, AttributeValue>(); expressionAttributeValues.put(":val", new AttributeValue().withN("0")); ScanRequest scanRequest = new ScanRequest() .withTableName("ProductCatalog") .withFilterExpression("Price < :val") .withProjectionExpression("Id") .withExpressionAttributeValues(expressionAttributeValues); ScanResult result = client.scan(scanRequest); for (Map<String, AttributeValue> item : result.getItems()) { printItem(item); } スキャンリクエストの withLimit メソッドを使用し、ページサイズまたはページごとの項目数を必 要に応じて制限することもできます。scan メソッドを実行するたびに、指定された数の項目が含ま API Version 2012-08-10 311 Amazon DynamoDB 開発者ガイド スキャニング れる結果が 1 ページ取得されます。次のページを取り出すには、前のページで最終項目のプライマリ キーの値を指定して、scan メソッドを再度実行します。これにより、scan メソッドで、次の項目の セットを返すことができます。この情報は、withExclusiveStartKey メソッドを使用することでリ クエストに含めます。初期状態では、このメソッドのパラメータは null になる場合があります。以降 のページを取り出すには、このプロパティ値を更新して、前ページの最後の項目のプライマリキーに する必要があります。 以下の Java コードスニペットは、ProductCatalog テーブルをスキャンする例を示しています。リ クエストでは、withLimit および withExclusiveStartKey メソッドが使用されています。do/ while ループは、結果の getLastEvaluatedKey メソッドが null の値を返すまでの時間で、1 ペー ジをスキャンし続けます。 Map<String, AttributeValue> lastKeyEvaluated = null; do { ScanRequest scanRequest = new ScanRequest() .withTableName("ProductCatalog") .withLimit(10) .withExclusiveStartKey(lastKeyEvaluated); ScanResult result = client.scan(scanRequest); for (Map<String, AttributeValue> item : result.getItems()){ printItem(item); } lastKeyEvaluated = result.getLastEvaluatedKey(); } while (lastKeyEvaluated != null); 例 – Java を使用したスキャン 以下の Java コードは、ProductCatalog テーブルをスキャンして、価格が 100(ゼロ)未満の項目を 検索するという、作業サンプル例を示しています。 Note SDK for Java には、オブジェクト永続性モデルも用意されています。このモデルにより、ク ライアント側のクラスを DynamoDB テーブルにマッピングすることができます。この方法 により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java: DynamoDBMapper (p. 78)」を参照してください。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。 以下の例を実行するための詳しい手順については、「Java コードサンプル (p. 171)」を参照 してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import java.util.HashMap; import java.util.Iterator; import java.util.Map; API Version 2012-08-10 312 Amazon DynamoDB 開発者ガイド スキャニング import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.ItemCollection; com.amazonaws.services.dynamodbv2.document.ScanOutcome; com.amazonaws.services.dynamodbv2.document.Table; public class DocumentAPIScan { static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider())); static String tableName = "ProductCatalog"; public static void main(String[] args) throws Exception { findProductsForPriceLessThanZero(); } private static void findProductsForPriceLessThanZero() { Table table = dynamoDB.getTable(tableName); Map<String, Object> expressionAttributeValues = new HashMap<String, Object>(); expressionAttributeValues.put(":pr", 100); ItemCollection<ScanOutcome> items = table.scan( "Price < :pr", //FilterExpression "Id, Title, ProductCategory, Price", //ProjectionExpression null, //ExpressionAttributeNames - not used in this example expressionAttributeValues); System.out.println("Scan of " + tableName + " for items with a price less than 100."); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } } } 例 – Java を使用したパラレルスキャン 以下の Java コード例は、パラレルスキャンの例です。プログラムは、ParallelScanTest という名前の テーブルを削除して再作成し、テーブルにデータをロードします。データのロードが終了すると、複 数のスレッドが生成され、並列の Scan リクエストが発行されます。プログラムは、各並列リクエス トのランタイム統計を表示します。 Note SDK for Java には、オブジェクト永続性モデルも用意されています。このモデルにより、ク ライアント側のクラスを DynamoDB テーブルにマッピングすることができます。この方法 により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java: DynamoDBMapper (p. 78)」を参照してください。 API Version 2012-08-10 313 Amazon DynamoDB 開発者ガイド スキャニング Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。 以下の例を実行するための詳しい手順については、「Java コードサンプル (p. 171)」を参照 してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import import import import import import import import java.util.ArrayList; java.util.Arrays; java.util.HashSet; java.util.Iterator; java.util.List; java.util.concurrent.ExecutorService; java.util.concurrent.Executors; java.util.concurrent.TimeUnit; import import import import import import import import import import import import import com.amazonaws.AmazonServiceException; com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.ItemCollection; com.amazonaws.services.dynamodbv2.document.ScanOutcome; com.amazonaws.services.dynamodbv2.document.Table; com.amazonaws.services.dynamodbv2.document.spec.ScanSpec; com.amazonaws.services.dynamodbv2.model.AttributeDefinition; com.amazonaws.services.dynamodbv2.model.KeySchemaElement; com.amazonaws.services.dynamodbv2.model.KeyType; com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; public class DocumentAPIParallelScan { // total number of sample items static int scanItemCount = 300; // number of items each scan request should return static int scanItemLimit = 10; // number of logical segments for parallel scan static int parallelScanThreads = 16; // table that will be used for scanning static String parallelScanTestTableName = "ParallelScanTest"; static DynamoDB dynamoDB = new DynamoDB( new AmazonDynamoDBClient(new ProfileCredentialsProvider())); public static void main(String[] args) throws Exception { try { // Clean up the table API Version 2012-08-10 314 Amazon DynamoDB 開発者ガイド スキャニング deleteTable(parallelScanTestTableName); createTable(parallelScanTestTableName, 10L, 5L, "Id", "N"); // Upload sample data for scan uploadSampleProducts(parallelScanTestTableName, scanItemCount); // Scan the table using multiple threads parallelScan(parallelScanTestTableName, scanItemLimit, parallelScanThreads); } catch (AmazonServiceException ase) { System.err.println(ase.getMessage()); } } private static void parallelScan(String tableName, int itemLimit, int numberOfThreads) { System.out.println("Scanning " + tableName + " using " + numberOfThreads + " threads " + itemLimit + " items at a time"); ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads); // Divide DynamoDB table into logical segments // Create one task for scanning each segment // Each thread will be scanning one segment int totalSegments = numberOfThreads; for (int segment = 0; segment < totalSegments; segment++) { // Runnable task that will only scan one segment ScanSegmentTask task = new ScanSegmentTask(tableName, itemLimit, totalSegments, segment); // Execute the task executor.execute(task); } shutDownExecutorService(executor); } // Runnable task for scanning a single segment of a DynamoDB table private static class ScanSegmentTask implements Runnable { // DynamoDB table to scan private String tableName; // number of items each scan request should return private int itemLimit; // Total number of segments // Equals to total number of threads scanning the table in parallel private int totalSegments; // Segment that will be scanned with by this task private int segment; public ScanSegmentTask(String tableName, int itemLimit, int totalSegments, int segment) { API Version 2012-08-10 315 Amazon DynamoDB 開発者ガイド スキャニング this.tableName = tableName; this.itemLimit = itemLimit; this.totalSegments = totalSegments; this.segment = segment; } @Override public void run() { System.out.println("Scanning " + tableName + " segment " + segment + " out of " + totalSegments + " segments " + itemLimit + " items at a time..."); int totalScannedItemCount = 0; Table table = dynamoDB.getTable(tableName); try { ScanSpec spec = new ScanSpec() .withMaxResultSize(itemLimit) .withTotalSegments(totalSegments) .withSegment(segment); ItemCollection<ScanOutcome> items = table.scan(spec); Iterator<Item> iterator = items.iterator(); Item currentItem = null; while (iterator.hasNext()) { totalScannedItemCount++; currentItem = iterator.next(); System.out.println(currentItem.toString()); } } catch (Exception e) { System.err.println(e.getMessage()); } finally { System.out.println("Scanned " + totalScannedItemCount + " items from segment " + segment + " out of " + totalSegments + " of " + tableName); } } } private static void uploadSampleProducts(String tableName, int itemCount) { System.out.println("Adding " + itemCount + " sample items to " + tableName); for (int productIndex = 0; productIndex < itemCount; productIndex++) { uploadProduct(tableName, productIndex); } } private static void uploadProduct(String tableName, int productIndex) { Table table = dynamoDB.getTable(tableName); try { System.out.println("Processing record #" + productIndex); API Version 2012-08-10 316 Amazon DynamoDB 開発者ガイド スキャニング Item item = new Item() .withPrimaryKey("Id", productIndex) .withString("Title", "Book " + productIndex + " Title") .withString("ISBN", "111-1111111111") .withStringSet( "Authors", new HashSet<String>(Arrays.asList("Author1"))) .withNumber("Price", 2) .withString("Dimensions", "8.5 x 11.0 x 0.5") .withNumber("PageCount", 500) .withBoolean("InPublication", true) .withString("ProductCategory", "Book"); table.putItem(item); } catch (Exception e) { System.err.println("Failed to create item " + productIndex + " in " + tableName); System.err.println(e.getMessage()); } } private static void deleteTable(String tableName){ try { Table table = dynamoDB.getTable(tableName); table.delete(); System.out.println("Waiting for " + tableName + " to be deleted...this may take a while..."); table.waitForDelete(); } catch (Exception e) { System.err.println("Failed to delete table " + tableName); e.printStackTrace(System.err); } } private static void createTable( String tableName, long readCapacityUnits, long writeCapacityUnits, String partitionKeyName, String partitionKeyType) { createTable(tableName, readCapacityUnits, writeCapacityUnits, partitionKeyName, partitionKeyType, null, null); } private static void createTable( String tableName, long readCapacityUnits, long writeCapacityUnits, String partitionKeyName, String partitionKeyType, String sortKeyName, String sortKeyType) { try { System.out.println("Creating table " + tableName); List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>(); keySchema.add(new KeySchemaElement() .withAttributeName(partitionKeyName) .withKeyType(KeyType.HASH)); //Partition key API Version 2012-08-10 317 Amazon DynamoDB 開発者ガイド スキャニング List<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition() .withAttributeName(partitionKeyName) .withAttributeType(partitionKeyType)); if (sortKeyName != null){ keySchema.add(new KeySchemaElement() .withAttributeName(sortKeyName) .withKeyType(KeyType.RANGE)); //Sort key attributeDefinitions.add(new AttributeDefinition() .withAttributeName(sortKeyName) .withAttributeType(sortKeyType)); } Table table = dynamoDB.createTable(tableName, keySchema, attributeDefinitions, new ProvisionedThroughput() .withReadCapacityUnits(readCapacityUnits) .withWriteCapacityUnits(writeCapacityUnits)); System.out.println("Waiting for " + tableName + " to be created...this may take a while..."); table.waitForActive(); } catch (Exception e) { System.err.println("Failed to create table " + tableName); e.printStackTrace(System.err); } } private static void shutDownExecutorService(ExecutorService executor) { executor.shutdown(); try { if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); // Preserve interrupt status Thread.currentThread().interrupt(); } } } テーブルおよびインデックスのスキャン: .NET Scan オペレーションは、テーブルまたはインデックスの全項目を読み込みます。 スキャンおよび クエリオペレーションに関するパフォーマンスの詳細については、「クエリおよびスキャンの使 用 (p. 287)」を参照してください。 以下に、AWS SDK for .NET の低レベル API を使用してテーブルをスキャンする手順を示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 API Version 2012-08-10 318 Amazon DynamoDB 開発者ガイド スキャニング 2. ScanRequest クラスのインスタンスを作成し、スキャンオペレーションのパラメータを指定しま す。 必須のパラメータは、テーブル名だけです。 3. Scan メソッドを実行し、前述のステップで作成した QueryRequest オブジェクトを指定します。 以下の Reply テーブルに、フォーラムスレッドに対する応答が格納されます。 >Reply ( <emphasis role="underline">Id</emphasis>, <emphasis role="underline">ReplyDateTime</emphasis>, Message, PostedBy ) このテーブルには、さまざまなフォーラムスレッドに対するすべての応答が保持されています。 したがってプライマリキーは、Id (パーティションキー) と ReplyDateTime (ソートキー) の両方 で構成されます。以下の C# コードスニペットは、テーブル全体をスキャンする例を示していま す。ScanRequest インスタンスで、スキャン対象のテーブルの名前を指定します。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); var request = new ScanRequest { TableName = "Reply", }; var response = client.Scan(request); var result = response.ScanResult; foreach (Dictionary<string, AttributeValue> item in response.ScanResult.Items) { // Process the result. PrintItem(item); } オプションパラメータの指定 Scan メソッドでは、複数のオプションパラメータがサポートされています。たとえば、オプション として、スキャンフィルタを使用してスキャン結果をフィルタリングすることができます。スキャン フィルタを使用すると、条件、およびその条件を評価するための属性名を指定できます。詳細につい ては、Scan を参照してください。 以下の C# コードは、ProductCatalog テーブルをスキャンして、値が 0(ゼロ)未満の項目を検索す る例を示しています。このサンプルでは、次のオプションパラメータが指定されています。 • 値が 0 未満(エラー状態)の項目のみを取り出す FilterExpression パラメータ。 • クエリ結果内の項目について取り出す属性のリストを指定する ProjectionExpression パラメー タ。 以下の C# コードスニペットは、ProductCatalog テーブルをスキャンして、値が 0(ゼロ)未満の項 目をすべて検索する例を示しています。 var forumScanRequest = new ScanRequest { TableName = "ProductCatalog", // Optional parameters. API Version 2012-08-10 319 Amazon DynamoDB 開発者ガイド スキャニング ExpressionAttributeValues = new Dictionary<string,AttributeValue> { {":val", new AttributeValue { N = "0" }} }, FilterExpression = "Price < :val", ProjectionExpression = "Id" }; また、オプションの Limit パラメータを追加することで、ページサイズ、またはページあたりの項目 数を制限することもできます。Scan メソッドを実行するたびに、指定された数の項目が含まれる結果 が 1 ページ取得されます。次のページを取り出すには、前のページで最終項目のプライマリキーの値 を指定して、Scan メソッドを再度実行します。これにより、Scan メソッドで、次の項目のセットを 返すことができます。この情報は、ExclusiveStartKey プロパティを設定することでリクエストに 含めます。このプロパティは最初は null である場合があります。以降のページを取り出すには、この プロパティ値を更新して、前ページの最後の項目のプライマリキーにする必要があります。 以下の C# コードスニペットは、ProductCatalog テーブルをスキャンする例を示しています。リク エストでは、オプションの Limit および ExclusiveStartKey パラメータを指定しています。do/ while ループは、LastEvaluatedKey から null 値が返されるまで、一度に 1 ページのスキャンを継 続します。 Dictionary<string, AttributeValue> lastKeyEvaluated = null; do { var request = new ScanRequest { TableName = "ProductCatalog", Limit = 10, ExclusiveStartKey = lastKeyEvaluated }; var response = client.Scan(request); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } lastKeyEvaluated = response.LastEvaluatedKey; } while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0); 例 – .NET を使用したスキャン 以下の C# コードは、ProductCatalog テーブルをスキャンして、値が 0(ゼロ)未満の項目を検索す るという、作業サンプル例を示しています。 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照し てください。 using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.Model; Amazon.Runtime; namespace com.amazonaws.codesamples { class LowLevelScan API Version 2012-08-10 320 Amazon DynamoDB 開発者ガイド スキャニング { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { FindProductsForPriceLessThanZero(); Console.WriteLine("Example complete. To continue, press Enter"); Console.ReadLine(); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } } private static void FindProductsForPriceLessThanZero() { Dictionary<string, AttributeValue> lastKeyEvaluated = null; do { var request = new ScanRequest { TableName = "ProductCatalog", Limit = 2, ExclusiveStartKey = lastKeyEvaluated, ExpressionAttributeValues = new Dictionary<string,AttributeValue> { {":val", new AttributeValue { N = "0" }} }, FilterExpression = "Price < :val", ProjectionExpression = "Id, Title, Price" }; var response = client.Scan(request); foreach (Dictionary<string, AttributeValue> item in response.Items) { Console.WriteLine("\nScanThreadTableUsePaging printing....."); PrintItem(item); } lastKeyEvaluated = response.LastEvaluatedKey; } while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void PrintItem( API Version 2012-08-10 321 Amazon DynamoDB 開発者ガイド スキャニング Dictionary<string, AttributeValue> attributeList) { foreach (KeyValuePair<string, AttributeValue> kvp in attributeList) { string attributeName = kvp.Key; AttributeValue value = kvp.Value; Console.WriteLine( attributeName + " " + (value.S == null ? "" : "S=[" + (value.N == null ? "" : "N=[" + (value.SS == null ? "" : "SS=[" value.SS.ToArray()) + "]") + (value.NS == null ? "" : "NS=[" value.NS.ToArray()) + "]") ); } value.S + "]") + value.N + "]") + + string.Join(",", + string.Join(",", Console.WriteLine("************************************************"); } } } 例 – .NET を使用したパラレルスキャン 以下の C# コード例は、パラレルスキャンの例です。このプログラムにより、ProductCatalog テーブ ルが削除後に再作成され、このテーブルにデータがロードされます。データのロードが終了すると、 複数のスレッドが生成され、並列の Scan リクエストが発行されます。最後に、ランタイム統計の要 約が印刷されます。 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照し てください。 using using using using using using using System; System.Collections.Generic; System.Threading; System.Threading.Tasks; Amazon.DynamoDBv2; Amazon.DynamoDBv2.Model; Amazon.Runtime; namespace com.amazonaws.codesamples { class LowLevelParallelScan { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); private static string tableName = "ProductCatalog"; private static int exampleItemCount = 100; private static int scanItemLimit = 10; private static int totalSegments = 5; static void Main(string[] args) { try { API Version 2012-08-10 322 Amazon DynamoDB 開発者ガイド スキャニング DeleteExampleTable(); CreateExampleTable(); UploadExampleData(); ParallelScanExampleTable(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void ParallelScanExampleTable() { Console.WriteLine("\n*** Creating {0} Parallel Scan Tasks to scan {1}", totalSegments, tableName); Task[] tasks = new Task[totalSegments]; for (int segment = 0; segment < totalSegments; segment++) { int tmpSegment = segment; Task task = Task.Factory.StartNew(() => { ScanSegment(totalSegments, tmpSegment); }); tasks[segment] = task; } Console.WriteLine("All scan tasks are created, waiting for them to complete."); Task.WaitAll(tasks); Console.WriteLine("All scan tasks are completed."); } private static void ScanSegment(int totalSegments, int segment) { Console.WriteLine("*** Starting to Scan Segment {0} of {1} out of {2} total segments ***", segment, tableName, totalSegments); Dictionary<string, AttributeValue> lastEvaluatedKey = null; int totalScannedItemCount = 0; int totalScanRequestCount = 0; do { var request = new ScanRequest { TableName = tableName, Limit = scanItemLimit, ExclusiveStartKey = lastEvaluatedKey, Segment = segment, TotalSegments = totalSegments }; var response = client.Scan(request); lastEvaluatedKey = response.LastEvaluatedKey; totalScanRequestCount++; API Version 2012-08-10 323 Amazon DynamoDB 開発者ガイド スキャニング totalScannedItemCount += response.ScannedCount; foreach (var item in response.Items) { Console.WriteLine("Segment: {0}, Scanned Item with Title: {1}", segment, item["Title"].S); } } while (lastEvaluatedKey.Count != 0); Console.WriteLine("*** Completed Scan Segment {0} of {1}. TotalScanRequestCount: {2}, TotalScannedItemCount: {3} ***", segment, tableName, totalScanRequestCount, totalScannedItemCount); } private static void UploadExampleData() { Console.WriteLine("\n*** Uploading {0} Example Items to {1} Table***", exampleItemCount, tableName); Console.Write("Uploading Items: "); for (int itemIndex = 0; itemIndex < exampleItemCount; itemIndex+ +) { Console.Write("{0}, ", itemIndex); CreateItem(itemIndex.ToString()); } Console.WriteLine(); } private static void CreateItem(string itemIndex) { var request = new PutItemRequest { TableName = tableName, Item = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = itemIndex }}, { "Title", new AttributeValue { S = "Book " + itemIndex + " Title" }}, { "ISBN", new AttributeValue { S = "11-11-11-11" }}, { "Authors", new AttributeValue { SS = new List<string>{"Author1", "Author2" }}}, { "Price", new AttributeValue { N = "20.00" }}, { "Dimensions", new AttributeValue { S = "8.5x11.0x.75" }}, { "InPublication", new AttributeValue { BOOL = false } } } }; client.PutItem(request); } private static void CreateExampleTable() { Console.WriteLine("\n*** Creating {0} Table ***", tableName); var request = new CreateTableRequest { AttributeDefinitions = new List<AttributeDefinition>() { new AttributeDefinition { AttributeName = "Id", AttributeType = "N" API Version 2012-08-10 324 Amazon DynamoDB 開発者ガイド スキャニング } }, KeySchema = new List<KeySchemaElement> { new KeySchemaElement { AttributeName = "Id", KeyType = "HASH" //Partition key } }, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 5, WriteCapacityUnits = 6 }, TableName = tableName }; var response = client.CreateTable(request); var result = response; var tableDescription = result.TableDescription; Console.WriteLine("{1}: {0} \t ReadsPerSec: {2} \t WritesPerSec: {3}", tableDescription.TableStatus, tableDescription.TableName, tableDescription.ProvisionedThroughput.ReadCapacityUnits, tableDescription.ProvisionedThroughput.WriteCapacityUnits); string status = tableDescription.TableStatus; Console.WriteLine(tableName + " - " + status); WaitUntilTableReady(tableName); } private static void DeleteExampleTable() { try { Console.WriteLine("\n*** Deleting {0} Table ***", tableName); var request = new DeleteTableRequest { TableName = tableName }; var response = client.DeleteTable(request); var result = response; Console.WriteLine("{0} is being deleted...", tableName); WaitUntilTableDeleted(tableName); } catch (ResourceNotFoundException) { Console.WriteLine("{0} Table delete failed: Table does not exist", tableName); } } API Version 2012-08-10 325 Amazon DynamoDB 開発者ガイド スキャニング private static void WaitUntilTableReady(string tableName) { string status = null; // Let us wait until table is created. Call DescribeTable. do { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); status = res.Table.TableStatus; } catch (ResourceNotFoundException) { // DescribeTable is eventually consistent. So you might // get resource not found. So we handle the potential exception. } } while (status != "ACTIVE"); } private static void WaitUntilTableDeleted(string tableName) { string status = null; // Let us wait until table is deleted. Call DescribeTable. do { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); status = res.Table.TableStatus; } catch (ResourceNotFoundException) { Console.WriteLine("Table name: {0} is not found. It is deleted", tableName); return; } } while (status == "DELETING"); } } } API Version 2012-08-10 326 Amazon DynamoDB 開発者ガイド スキャニング スキャンテーブルとインデックス : PHP Scan オペレーションは、テーブルまたはインデックスの全項目を読み込みます。 スキャンおよび クエリオペレーションに関するパフォーマンスの詳細については、「クエリおよびスキャンの使 用 (p. 287)」を参照してください。 以下に、AWS SDK for PHP を使用した一般的な手順を示します。 1. DynamoDB クライアントのインスタンスを作成します。 2. オプションのパラメーターを含む DynamoDB オペレーションのパラメーターを指定します。 3. DynamoDB からの応答をアプリケーションのローカル変数にロードします。 さまざまなフォーラムスレッドに対する応答を格納する、以下の Reply テーブルを考慮します。 Reply ( Id, ReplyDateTime, Message, PostedBy ) このテーブルには、さまざまなフォーラムスレッドに対するすべての応答が保持されています。した がってプライマリキーは、Id (パーティションキー) と ReplyDateTime (ソートキー) の両方で構成され ます。以下の PHP コードスニペットは、テーブルをスキャンする例を示しています。 Note このサンプルコードでは、「テーブルの作成とサンプルデータのロード (p. 166)」のセクショ ンに記載されている手順に従ってユーザーのアカウントで DynamoDB にデータがロード済み であることを前提としています。あるいは、「AWS SDK for PHP を使用した、サンプルテー ブルの作成とデータのアップロード (p. 617)」のトピックに記載されている手順に従って データをロードすることもできます。 以下の例を実行するための詳しい手順については、「PHP コードサンプル (p. 175)」を参照 してください。 require 'vendor/autoload.php'; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $response = $dynamodb->scan([ 'TableName' => 'Reply' ]); foreach ($response['Items'] as $key => $value) { echo 'Id: ' . $value['Id']['S'] . "\n"; echo 'ReplyDateTime: ' . $value['ReplyDateTime']['S'] . "\n"; echo 'Message: ' . $value['Message']['S'] . "\n"; echo 'PostedBy: ' . $value['PostedBy']['S'] . "\n"; echo "\n"; } API Version 2012-08-10 327 Amazon DynamoDB 開発者ガイド スキャニング オプションパラメータの指定 scan 関数では、複数のオプションパラメータがサポートされています。たとえば、オプションとし て、フィルタ式を使用してスキャン結果をフィルタリングすることができます。フィルタ式では、条 件、およびその条件を評価するための属性名を指定します。詳細については、Scan を参照してくださ い。 以下の PHP コードでは、ProductCatalog テーブルをスキャンし、(誤って) ゼロ以下の価格になって いる項目を見つけます。このサンプルでは、次のオプションパラメータが指定されています。 • ゼロ以下の価格となっている項目のみを取得する FilterExpression。 • クエリ結果内の項目について取り出す属性を指定する ProjectionExpression パラメータ。 $response = $dynamodb->scan([ 'TableName' => 'ProductCatalog', 'ProjectionExpression' => 'Id, Price', 'ExpressionAttributeValues' => [ ':val1' => ['N' => '0']] , 'FilterExpression' => 'Price <= :val1', ]); foreach ($response['Items'] as $key => $value) { echo 'Id: ' . $value['Id']['N'] . ' Price: ' . $value['Price']['N'] . "\n"; echo "\n"; } オプションの Limit パラメータを追加し、ページサイズまたはページごとの項目数を必要に応じて 制限することもできます。scan 関数を実行するたびに、指定した数の項目が付属する 1 ページの結 果が得られます。次のページを取り出すには、前のページで最終項目のプライマリキーの値を指定し て、scan 関数を再度実行します。これにより、scan 関数で、次の項目のセットを返すことができま す。この情報は、ExclusiveStartKey プロパティを設定することでリクエストに含めます。このプ ロパティは最初は null である場合があります。以降のページを取り出すには、このプロパティ値を更 新して、前ページの最後の項目のプライマリキーにする必要があります。 以下の PHP コードスニペットは、ProductCatalog テーブルをスキャンする例を示しています。リク エストでは、オプションの Limit および ExclusiveStartKey パラメータを指定しています。 $tableName = 'ProductCatalog'; # The Scan operation is paginated. Issue the Scan request multiple times. do { echo "Scanning table $tableName\n"; $request = [ 'TableName' => $tableName, 'ExpressionAttributeValues' => [ ':val1' => ['N' => '201'] ], 'FilterExpression' => 'Price < :val1', 'Limit' => 2 ]; # Add the ExclusiveStartKey if we got one back in the previous response if(isset($response) && isset($response['LastEvaluatedKey'])) { API Version 2012-08-10 328 Amazon DynamoDB 開発者ガイド スキャニング $request['ExclusiveStartKey'] = $response['LastEvaluatedKey']; } $response = $dynamodb->scan($request); foreach ($response['Items'] as $key => $value) { echo 'Id: ' . $value['Id']['N'] . "\n"; echo 'Title: ' . $value['Title']['S'] . "\n"; echo 'Price: ' . $value['Price']['N'] . "\n"; echo "\n"; } } # If there is no LastEvaluatedKey in the response, there are no more items matching this Scan while(isset($response['LastEvaluatedKey'])); 例 – PHP を使用したデータのロード 以下の PHP コード例では、以降の例で使用するサンプルデータを作成します。このプログラムによ り、ProductCatalog テーブルが削除後に再作成され、このテーブルにデータがロードされます。 Note これらのコード例を実行するための詳しい手順については、「PHP コードサンプ ル (p. 175)」を参照してください。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'ProductCatalog'; // Delete an old DynamoDB table echo "Deleting the table...\n"; try { $response = $dynamodb->deleteTable([ 'TableName' => $tableName ]); $dynamodb->waitUntil('TableNotExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] API Version 2012-08-10 329 Amazon DynamoDB 開発者ガイド スキャニング ]); echo "The table has been deleted.\n"; echo "The table {$tableName} has been deleted.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to delete table $tableName\n"); } // Create a new DynamoDB table echo "# Creating table $tableName...\n"; try { $response = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'Id', 'AttributeType' => 'N' ] ], 'KeySchema' => [ [ 'AttributeName' => 'Id', 'KeyType' => 'HASH' ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 5, 'WriteCapacityUnits' => 6 ] ]); //Partition key $dynamodb->waitUntil('TableExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] ]); echo "Table {$tableName} has been created.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to create table $tableName\n"); } // Populate DynamoDB table echo "# Populating Items to $tableName...\n"; for ($i = 1; $i <= 100; $i++) { $response = $dynamodb->putItem([ 'TableName' => $tableName, 'Item' => [ 'Id' => [ 'N' => "$i" ], // Primary Key 'Title' => [ 'S' => "Book {$i} Title" ], API Version 2012-08-10 330 Amazon DynamoDB 開発者ガイド スキャニング 'ISBN' => [ 'S' => '111-1111111111' ], 'Price' => [ 'N' => "25" ], 'Authors' => [ 'SS' => ['Author1', 'Author2']] ] ]); $response = $dynamodb->getItem([ 'TableName' => 'ProductCatalog', 'Key' => [ 'Id' => [ 'N' => "$i" ] ] ]); echo "Item populated: {$response['Item']['Title']['S']}\n"; sleep(1); } echo "{$tableName} is populated with items.\n"; ?> 例 – PHP を使用したスキャン 以下の PHP コード例は、ProductCatalog テーブル上でシリアルスキャンを実行する例を示していま す。 Note このプログラムを実行する前に、ProductTable にデータを設定する必要があります。詳細に ついては、「例 – PHP を使用したデータのロード (p. 329)」を参照してください。 これらのコード例を実行するための詳しい手順については、「PHP コードサンプ ル (p. 175)」を参照してください。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'ProductCatalog'; $params = [ 'TableName' => $tableName, 'ExpressionAttributeValues' => [ ':val1' => ['S' => 'Book'] ], 'FilterExpression' => 'contains (Title, :val1)', API Version 2012-08-10 331 Amazon DynamoDB 開発者ガイド スキャニング 'Limit' => 10 ]; // Execute scan operations until the entire table is scanned $count = 0; do { $response = $dynamodb->scan ( $params ); $items = $response->get ( 'Items' ); $count = $count + count ( $items ); // Do something with the $items foreach ( $items as $item ) { echo "Scanned item with Title \"{$item['Title']['S']}\".\n"; } // Set parameters for next scan $params ['ExclusiveStartKey'] = $response ['LastEvaluatedKey']; } while ( $params ['ExclusiveStartKey'] ); echo "{$tableName} table scanned completely. {$count} items found.\n"; ?> 例 – PHP を使用したパラレルスキャン 以下の PHP コード例は、パラレルスキャンの例です。複数の Scan リクエストが同時に実行されま す。最後に、ランタイム統計の要約が印刷されます。 Note このプログラムを実行する前に、ProductTable にデータを設定する必要があります。詳細に ついては、「例 – PHP を使用したデータのロード (p. 329)」を参照してください。 これらのコード例を実行するための詳しい手順については、「PHP コードサンプ ル (p. 175)」を参照してください。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; use Aws\CommandPool; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'ProductCatalog'; $totalSegments = 5; $params = array( 'TableName' => $tableName, API Version 2012-08-10 332 Amazon DynamoDB 開発者ガイド インデックスの使用 'ExpressionAttributeValues' => array ( ':val1' => array('S' => 'Book') ) , 'FilterExpression' => 'contains (Title, :val1)', 'Limit' => 10, 'TotalSegments' => $totalSegments ); // Build an array of Scan commands - one for each segment $commands = []; for ($segment = 0; $segment < $totalSegments; $segment++) { $params['Segment'] = $segment; $commands[] = $dynamodb->getCommand('Scan',$params); } // Setup a command pool to run the Scan commands concurrently // The 'fulfilled' callback will process the results from each command // The 'rejected' callback will tell why the command failed $pool = new CommandPool($dynamodb,$commands,[ 'fulfilled' => function($result, $iterKey, $aggregatePromise) { echo "\nResults from segment $iterKey\n"; // Do something with the items foreach ($result['Items'] as $item) { echo "Scanned item with Title \"" . $item['Title']['S'] . "\"\n"; } }, 'rejected' => function ($reason, $iterKey, $aggregatePromise) { echo "Failed {$iterKey}: {$reason}\n"; } ]); $promise = $pool->promise(); $promise->wait(); ?> セカンダリインデックスを使用したデータアクセ ス性の向上 トピック • グローバルセカンダリインデックス (p. 336) • ローカルセカンダリインデックス (p. 383) Amazon DynamoDB は、プライマリキーの値を指定して、テーブルの項目への高速なアクセスを可能 にします。しかし多くのアプリケーションでは、プライマリキー以外の属性を使って、データに効率 的にアクセスできるようにセカンダリ(または代替)キーを 1 つ以上設定することで、メリットが得 られることがあります。これに対応するために、1 つのテーブルで 1 つ以上のセカンダリインデック スを作成して、それらのインデックスに対して Query または Scan リクエストを実行することができ ます。 セカンダリインデックス は、テーブルからの属性のサブセットと、Query オペレーションをサポート する代替キーで構成されるデータ構造です。Query をテーブルで使用する場合と同じように、Query を使用してインデックスからデータを取得できます。テーブルには、複数の セカンダリインデック API Version 2012-08-10 333 Amazon DynamoDB 開発者ガイド インデックスの使用 ス を作成できます。これにより、アプリケーションは複数の異なるクエリパターンにアクセスできま す。 Note また、テーブルを Scan するのと同じように、インデックスも Scan できます。 すべてのセカンダリインデックスは完全に 1 つのテーブルに関連付けられ、そこからデータを取得 します。これはインデックスのベーステーブルと呼ばれます。インデックスを作成する場合は、イン デックスの代替キー (パーティションキーおよびソートキー) を定義します。また、ベーステーブルか らインデックスに射影 (コピー) する属性も定義します。DynamoDB は、これらの属性とベーステーブ ルからのプライマリキー属性をインデックスにコピーします。次に、テーブルに対してクエリまたは スキャンを実行する場合と同様に、インデックスに対してクエリまたはスキャンを実行します。 すべての セカンダリインデックス は、DynamoDB によって自動的に維持されます。ベーステーブル の項目を追加、変更、または削除すると、そのテーブルのインデックスも更新され、この変更が反映 されます。 DynamoDB では、次の 2 種類の セカンダリインデックス をサポートしています。 • Global secondary index — ベーステーブルと異なるパーティションキーとソートキーを持つイン デックス。グローバルセカンダリインデックスは、そのインデックスのクエリは、すべてのパー ティションにわたって、ベーステーブルのすべてのデータを対象に実行できるので、「グローバ ル」と見なされます。 • ローカルセカンダリインデックス — ベーステーブルと同じパーティションキーと、異なるソート キーを持つインデックス。local secondary indexは、local secondary indexのすべてのパーティショ ンの範囲が、同じパーティションキーの値を持つベーステーブルパーティションに限定されるとい う意味で「ローカル」です。 使用するインデックスの種類を決定するときは、アプリケーションの要件を考慮する必要がありま す。次の表は、グローバルセカンダリインデックスとlocal secondary indexの主な違いを示していま す。 特徴 グローバルセカンダリインデッ クス ローカルセカンダリインデック ス キースキーマ グローバルセカンダリインデッ クスのプライマリキーはシンプ ル (パーティションキー) また は複合 (パーティションキーと ソートキー) のいずれかとする ことができます。 local secondary indexのプライ マリキーは複合 (パーティショ ンキーとソートキー) である必 要があります。 キーの属性 インデックスパーティション キーとソートキー (存在する場 合) は、文字列、数値、または バイナリ型の任意のベーステー ブル属性とすることができま す。 インデックスのパーティション キーは、ベーステーブルのパー ティションキーと同じ属性で す。ソートキーは、文字列、数 値、またはバイナリ型の任意の ベーステーブル属性とすること ができます。 パーティションキー値ごとのサ イズ制限 グローバルセカンダリインデッ クス にサイズ制限はありませ ん。 パーティションキーの値ごと に、すべてのインデックス付き 項目の合計サイズが、10 GB 以 下である必要があります。 オンラインインデックスオペ レーション Global secondary indexは、 テーブルの作成と同時に作成 ローカルセカンダリインデック スは、テーブルの作成と同時 API Version 2012-08-10 334 Amazon DynamoDB 開発者ガイド インデックスの使用 特徴 グローバルセカンダリインデッ クス ローカルセカンダリインデック ス できます。また、既存のテーブ ルに新しいグローバルセカンダ リインデックスを追加したり、 既存のグローバルセカンダリイ ンデックスを削除したりできま す。詳細については、「グロー バルセカンダリインデックスの 管理 (p. 344)」を参照してく ださい。 に作成されます。既存のテーブ ルにlocal secondary indexを追 加したり、現在存在するlocal secondary indexを削除したりす ることはできません。 クエリとパーティション グローバルセカンダリインデッ クス では、すべてのパーティ ションでテーブル全体に対して クエリを実行できます。 local secondary indexでは、ク エリのパーティションキー値で 指定された 1 つのパーティショ ンに対してクエリを実行できま す。 読み込み整合性 グローバルセカンダリインデッ クス のクエリでは、結果整合 性のみがサポートされます。 local secondary index のクエリ を実行するとき、結果整合性ま たは強い整合性のどちらかを選 択できます。 プロビジョニングされたスルー プットの消費 各 グローバルセカンダリイン デックス には、読み込みおよ び書き込みアクティビティに対 する独自のプロビジョニングさ れたスループット設定がありま す。グローバルセカンダリイン デックスのクエリまたはスキャ ンでは、ベーステーブルからで はなく、インデックスからキャ パシティーユニットを消費しま す。同じことが、テーブルへの 書き込みによる グローバルセ カンダリインデックス の更新 にも当てはまります。 local secondary indexのクエリ またはスキャンでは、ベース テーブルから読み込みキャパシ ティーユニットを消費します。 テーブルに書き込むと、その local secondary indexも更新さ れます。この更新では、ベース テーブルから書き込みキャパシ ティーユニットを消費します。 射影される属性 グローバルセカンダリインデッ クスのクエリまたはスキャンで は、インデックスに射影された 属性だけをリクエストできま す。DynamoDB は、テーブル から属性をフェッチしません。 local secondary indexのクエリ またはスキャンを実行する場 合、インデックスに射影されて いない属性をリクエストできま す。DynamoDB は、その属性を テーブルから自動的にフェッチ します。 セカンダリインデックス を持つテーブルを複数作成する場合は、連続的に作成する必要があります。 たとえば、最初のテーブルを作成し、そのテーブルが ACTIVE になるまで待ちます。次のテーブルを 作成し、そのテーブルが ACTIVE になるまで待ちます。セカンダリインデックス を持つ複数のテーブ ルを同時に作成しようとすると、DynamoDB は LimitExceededException を返します。 各 セカンダリインデックス には、以下を指定する必要があります。 • 作成するインデックスの種類 – グローバルセカンダリインデックスまたはlocal secondary index。 • インデックスの名前。インデックスの名前付けルールは、「DynamoDB での制限 (p. 558)」に示 すようにテーブルの場合と同じです。名前は関連付けられているベーステーブルに対して一意であ API Version 2012-08-10 335 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス る必要がありますが、別のベーステーブルに関連付けられているインデックスでも同じ名前を使用 できます。 • インデックスのキースキーマ。インデックスキースキーマの各属性は、型が String、Number、また は Binary の最上位属性である必要があります。ドキュメントとセットを含むその他のデータ型は使 用できません。キースキーマのその他の要件は、インデックスの種類によって異なります。 • グローバルセカンダリインデックスの場合、パーティションキーはベーステーブルの任意のスカ ラー属性にすることができます。ソートキーはオプションです。このキーもベーステーブルの任 意のスカラー属性にすることができます。 • local secondary indexの場合、パーティションキーは、ベーステーブルのパーティションキーと同 じである必要があります。ソートキーは、非キーベーステーブル属性である必要があります。 • ベーステーブルからインデックスに射影する追加の属性 (ある場合)。この属性は、すべてのイン デックスに自動的に射影されるテーブルのキー属性とは別の属性です。スカラー、ドキュメント、 およびセットを含む任意のデータ型の属性を射影できます。 • インデックスのプロビジョニングされたスループット設定(必要な場合): • グローバルセカンダリインデックス の場合、読み込みおよび書き込みキャパシティーユニット設 定を指定する必要があります。このプロビジョニングされたスループット設定は、ベーステーブ ルの設定から独立しています。 • local secondary index の場合、読み込みおよび書き込みキャパシティーユニット設定を指定する 必要はありません。local secondary indexに対する読み込みおよび書き込みオペレーションは、そ のベーステーブルのプロビジョニングされたスループット設定から消費します。 クエリで最大の柔軟性を得るには、1 テーブルあたり最大 5 個のグローバルセカンダリインデックス および最大 5 個のlocal secondary indexを作成できます。 テーブルの セカンダリインデックスes の詳細なリストを取得するには、DescribeTable オペレー ションを使用します。DescribeTable によって、テーブルのすべての セカンダリインデックス につ いて、名前、ストレージサイズ、および項目数が返されます。これらの値はリアルタイムでは更新さ れませんが、約 6 時間ごとに更新されます。 セカンダリインデックスのデータには、Query または Scan オペレーションを使用してアクセスでき ます。使用するベーステーブル名とインデックス名、結果で返される属性、および適用する条件式ま たはフィルタを指定する必要があります。DynamoDB で返される結果は、昇順にも降順にもすること ができます。 テーブルを削除すると、そのテーブルに関連付けられているすべてのインデックスも削除されます。 ベストプラクティスについては、ローカルセカンダリインデックス のガイドライン (p. 584) と グ ローバルセカンダリインデックス のガイドライン (p. 586) をそれぞれ参照してください。 グローバルセカンダリインデックス トピック • 属性の射影 (p. 339) • グローバルセカンダリインデックス のクエリ (p. 340) • グローバルセカンダリインデックスのスキャン (p. 341) • テーブルと グローバルセカンダリインデックス 間のデータ同期 (p. 341) • プロビジョニングされたスループットに関する考慮事項(グローバルセカンダリインデック ス) (p. 342) • グローバルセカンダリインデックス のストレージに関する考慮事項 (p. 343) • グローバルセカンダリインデックスの管理 (p. 344) • グローバルセカンダリインデックス の使用 : Java (p. 356) • グローバルセカンダリインデックスes: .NET の使用 (p. 364) • グローバルセカンダリインデックス の操作 : PHP (p. 375) API Version 2012-08-10 336 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス アプリケーションによっては、さまざまな属性をクエリ基準に使用して、いろいろな種類のクエリ を実行する必要があります。このような要件に対応するために、1 つ以上の グローバルセカンダリ インデックス を作成して、そのインデックスに対して Query リクエストを発行できます。たとえ ば、GameScores という名前のテーブルがあり、モバイルゲームアプリケーションのユーザーとスコ アを記録しているとします。GameScores の各項目は、パーティションキー (UserId) とソートキー (GameTitle) で識別します。次の図は、テーブル内の項目の構成を示しています。一部表示されていな い属性もあります。 ここで、各ゲームの最高スコアを表示する順位表アプリケーションを作成すると仮定します。キー 属性(UserId と GameTitle)を指定したクエリは非常に効率的ですが、GameTitle だけに基づいて GameScores からデータを取り出す必要があるアプリケーションでは、Scan オペレーションを使用 する必要があります。テーブルに追加される項目が増えるにつれ、すべてのデータのスキャンは低速 で非効率的になり、次のような質問に答えることが難しくなります。 • ゲーム Meteor Blasters で記録された最高スコアはいくつですか? • Galaxy Invaders で最高スコアを獲得したユーザーは誰ですか? • 勝敗の最も高い比率は何ですか? 非キー属性に対するクエリの速度を上げるために、グローバルセカンダリインデックス を作成できま す。グローバルセカンダリインデックスには、ベーステーブルからの属性の一部が格納されますが、 テーブルのプライマリキーとは異なるプライマリキーによって構成されます。インデックスキーは、 テーブルからのキー属性を持つ必要がありません。また、テーブルと同じキースキーマを使用する必 要もありません。 たとえば、パーティションキーに GameTitle を使用し、ソートキーに TopScore を使用し て、GameTitleIndex という名前のグローバルセカンダリインデックスを作成できます。ベーステー ブルのプライマリキー属性は必ずインデックスに射影されるので、UserId 属性も存在します。次の図 は、GameTitleIndex インデックスを示しています。 API Version 2012-08-10 337 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス これで、GameTitleIndex に対してクエリを実行し、Meteor Blasters のスコアを簡単に入手できるよう になります。結果は、ソートキーの値 TopScore 別に並べられます。ScanIndexForward パラメータ を false に設定した場合、結果は降順で返されます。つまり、最高スコアが最初に返されます。 すべてのグローバルセカンダリインデックスには、パーティションキーが必要で、オプションのソー トキーを指定できます。インデックスキースキーマは、ベーステーブルスキーマとは異なるものにす ることができます。シンプルなプライマリキー (パーティションキー) のあるテーブルを作成したり、 複合プライマリキー (パーティションキーおよびソートキー) のあるグローバルセカンダリインデッ クスを作成でき、その逆も可能です。インデックスキー属性は、ベーステーブルの任意の最上位文字 列、数値、またはバイナリ属性で構成できます。他のスカラー型、ドキュメント型、およびセット型 は使用できません。 必要な場合、他のベーステーブル属性をインデックスに射影できます。インデックスに対してクエリ を実行すると、DynamoDB は、この射影された属性を効率的に取り出すことができますが、グローバ ルセカンダリインデックスのクエリでは、ベーステーブルから属性をフェッチできません。上記の図 に示すように、GameTitleIndex にクエリを実行した場合、クエリは TopScore 以外の非キー属性にア クセスすることはできません (キー属性 GameTitle と UserId は自動的に射影されます)。 DynamoDB テーブルでは、各キー値は一意である必要があります。ただし、グローバルセカンダリイ ンデックス のキー値は一意である必要がありません。たとえば、Comet Quest という名前のゲームが 特に難しく、多くの新しいユーザーが試しても、ゼロを上回るスコアを獲得することができないとし ます。ここに、それを表すのに使用できるいくつかのデータがあります。 UserId GameTitle TopScore 123 Comet Quest 0 201 Comet Quest 0 301 Comet Quest 0 このデータを GameScores テーブルに追加すると、DynamoDB はそのデータを GameTitleIndex に伝 達します。GameTitle として Comet Quest を、TopScore として 0 を指定してインデックスに対する クエリを実行すると、次のデータが返されます。 API Version 2012-08-10 338 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス 指定したキー値を持つ項目だけがレスポンスに表示されます。その一連のデータ内では、項目は特定 の順に並んでいません。 グローバルセカンダリインデックス は、キー属性が実際に存在するデータ項目のみを記録します。た とえば、別の新しい項目を GameScores テーブルに追加し、必須のプライマリキー属性だけを指定し たとします。 UserId GameTitle 400 Comet Quest TopScore 属性を指定していないので、DynamoDB は、この項目を GameTitleIndex に反映しません。 このため、すべての Comet Quest 項目を対象に、GameScores に対してクエリを実行した場合、次の 4 つの項目が返されます。 GameTitleIndex に対して同様のクエリを実行すると、4 つではなく 3 つの項目が返されます。これ は、TopScore が存在しない項目はインデックスに反映されないためです。 属性の射影 射影は、テーブルからセカンダリインデックスにコピーされる属性セットです。テーブルのパーティ ションキーとソートキーは必ずインデックスに射影されます。アプリケーションのクエリ要件をサ ポートするために、他の属性を射影することができます。インデックスのクエリを行うと、Amazon DynamoDB は射影内の属性に、それらの属性が独立したテーブル内にあるかのようにアクセスできま す。 セカンダリインデックス を作成する場合は、インデックスに射影される属性を指定する必要がありま す。DynamoDB にはこのための 3 つのオプションが用意されています。 • KEYS_ONLY – インデックスの各項目は、テーブルのパーティションキーとソートキー値、および インデックスキー値のみで構成されます。KEYS_ONLY オプションを使用すると、セカンダリイン デックス は最小になります。 • INCLUDE – KEYS_ONLY の属性に加えて、セカンダリインデックス にその他の非キー属性が含まれ るように指定できます。 API Version 2012-08-10 339 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス • ALL – セカンダリインデックス にソーステーブルのすべての属性が含まれます。テーブルの全デー タがインデックスで複製されるため、ALL の射影により、セカンダリインデックス は最大になりま す。 前の図の GameTitleIndex には、追加の射影された属性がありません。アプリケーションは、クエリ で GameTitle と TopScore を使用できます。ただし、特定のゲームで最高スコアを獲得したユーザー や、勝率が最も高いユーザーを効率的に特定することはできません。このデータに対するクエリをサ ポートする最も効率的な方法は、次の図に示すように、これらの属性をベーステーブルからグローバ ルセカンダリインデックスに射影する方法です。 非キー属性 Wins と Losses がインデックスに射影されるので、アプリケーションは、任意のゲーム、 またはゲームとユーザー ID の任意の組み合わせに対して、勝敗の比率を特定できます。 グローバルセカンダリインデックス に射影する属性を選択する場合には、プロビジョニングされるス ループットコストとストレージコストのトレードオフを考慮する必要があります。 • ごく一部の属性だけに最小のレイテンシーでアクセスする必要がある場合は、それらの属性だけを グローバルセカンダリインデックス に射影することを検討してください。インデックスが小さいほ ど少ないコストで格納でき、書き込みコストも低くなります。 • アプリケーションが非キー属性に頻繁にアクセスする場合には、それらの属性を グローバルセカン ダリインデックス に射影することを検討してください。グローバルセカンダリインデックス の追加 のストレージコストは、頻繁なテーブルスキャンを実行するコストを相殺します。 • ほとんどの非キー属性に頻繁にアクセスする場合は、それらの属性、さらにはベーステーブル全体 をグローバルセカンダリインデックスに射影することができます。これにより、最大限の柔軟性が 得られますが、ストレージコストは増加するか、倍になります。 • アプリケーションでテーブルのクエリを頻繁に行う必要がなく、テーブル内のデータに対する書き 込みや更新が多数になる場合は、KEYS_ONLY を射影することを検討してください。グローバルセ カンダリインデックス のサイズは最小になりますが、クエリに必要なサイズは確保されます。 グローバルセカンダリインデックス のクエリ Query オペレーションを使用して、グローバルセカンダリインデックスの 1 つ以上の項目にアクセス することができます。クエリでは、使用するベーステーブル名とインデックス名、クエリ結果で返さ API Version 2012-08-10 340 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス れる属性、および適用するクエリ条件を指定する必要があります。DynamoDB で返される結果は、昇 順にも降順にもすることができます。 順位表アプリケーションのゲームデータをリクエストする Query から返される次のデータについて考 えます。 { "TableName": "GameScores", "IndexName": "GameTitleIndex", "KeyConditionExpression": "GameTitle = :v_title", "ExpressionAttributeValues": { ":v_title": {"S": "Meteor Blasters"} }, "ProjectionExpression": "UserId, TopScore", "ScanIndexForward": false } このクエリでは次のようになっています。 • DynamoDB が GameTitle パーティションキーを使用して GameTitleIndex にアクセスし、Meteor Blasters のインデックス項目を特定します。このキーを持つすべてのインデックス項目が、すばや く取り出せるように隣り合わせに格納されます。 • このゲーム内で、DynamoDB はインデックスを使用して、このゲームのすべてのユーザー ID と最 高スコアにアクセスします。 • ScanIndexForward パラメータが false に設定されているので、結果は降順で返されます。 グローバルセカンダリインデックスのスキャン Scan オペレーションを使用して、グローバルセカンダリインデックス からすべてのデータを取得 できます。 リクエストにはベーステーブル名とインデックス名を指定する必要があります。Scan で は、DynamoDB はインデックスのすべてのデータを読み取り、それをアプリケーションに返します。 また、データの一部のみを返し、残りのデータを破棄するようにリクエストすることもできます。こ れを行うには、Scan オペレーションの FilterExpression パラメーターを使用します。 詳細につ いては、「クエリまたはスキャンからの結果のフィルタリング (p. 289)」を参照してください。 テーブルと グローバルセカンダリインデックス 間のデータ同 期 DynamoDB は、各グローバルセカンダリインデックスをそのベーステーブルと自動的に同期します。 アプリケーションがテーブルに項目を書き込むか、削除すると、そのテーブルのすべての グローバル セカンダリインデックス は、結果整合性のあるモデルを使用して、非同期で更新されます。アプリ ケーションがインデックスに直接書き込むことはありません。ただし、DynamoDB でこれらのイン デックスがどのように維持されるかを理解することは重要です。 グローバルセカンダリインデックスを作成するときは、1 つ以上のインデックスキー属性およびそ れらのデータ型を指定します。つまり、ベーステーブルに項目を書き込むとき、それらの属性の データ型が、インデックスキースキーマのデータ型に一致する必要があります。GameTitleIndex の 場合、インデックスの GameTitle パーティションキーは文字列データ型として定義され、インデッ クス内の TopScore ソートキーは数値型になります。GameScores テーブルに項目を追加すると きに、GameTitle または TopScore に対して別のデータ型を指定すると、データ型の不一致により DynamoDB によって ValidationException が返されます。 テーブルに項目を入力するか、削除すると、そのテーブルの グローバルセカンダリインデックス は、 結果整合性のある方法で更新されます。テーブルデータへの変更は、通常は、瞬時に グローバルセカ ンダリインデックス に伝達されます。ただし、万が一障害が発生した場合は、長い伝達遅延が発生す API Version 2012-08-10 341 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス ることがあります。このため、アプリケーションでは、グローバルセカンダリインデックス に対する クエリによって、最新でない結果が返される状況を予期し、それに対応する必要があります。 テーブルに項目を書き込む場合には、グローバルセカンダリインデックスソートキーに対して属性を 指定する必要はありません。GameTitleIndex を例にとると、GameScores テーブルに新しい項目を書 き込むために、TopScore 属性に値を指定する必要はありません。この場合、Amazon DynamoDB は この特定の項目のインデックスにデータを書き込むことはありません。 多数の グローバルセカンダリインデックス があるテーブルは、インデックス数が少ないテーブルに比 べて書き込みアクティビティに多くのコストを要します。詳細については、「プロビジョニングされ たスループットに関する考慮事項(グローバルセカンダリインデックス) (p. 342)」を参照してくだ さい。 プロビジョニングされたスループットに関する考慮事項(グ ローバルセカンダリインデックス) グローバルセカンダリインデックス を作成するときには、そのインデックスに対して予想されるワー クロードに応じた読み込みおよび書き込みキャパシティーユニットを指定する必要があります。グ ローバルセカンダリインデックスのプロビジョニングされたスループット設定は、そのベーステーブ ルの設定から独立しています。グローバルセカンダリインデックスに対する Query オペレーション では、ベーステーブルではなく、インデックスから読み込みキャパシティーユニットを消費します。 テーブルで項目を入力、更新、または削除すると、そのテーブルのグローバルセカンダリインデック スも更新されます。このインデックスの更新では、ベーステーブルからではなく、インデックスから 書き込みキャパシティーユニットを消費します。 たとえば、グローバルセカンダリインデックス に対して Query を実行し、そのプロビジョニングさ れた読み込みキャパシティーを超えた場合、リクエストは調整されます。多量の書き込みアクティビ ティをテーブルに対して実行するときに、そのテーブルの グローバルセカンダリインデックス に十分 な書き込みキャパシティーがない場合、そのテーブルに対する書き込みアクティビティは調整されま す。 グローバルセカンダリインデックス のプロビジョニングされたスループット設定を表示するに は、DescribeTable オペレーションを使用します。テーブルのすべての グローバルセカンダリイン デックス に関する詳細が返されます。 読み込みキャパシティーユニット Global secondary index では、結果整合性のある読み込みをサポートしており、各読み込みで、1 読み 込みキャパシティーユニットの半分を消費します。つまり、1 回の グローバルセカンダリインデック ス のクエリでは、1 読み込みキャパシティーユニットあたり最大 2 × 4 KB = 8 KB を取り出すことが できます。 グローバルセカンダリインデックス のクエリの場合、DynamoDB は、プロビジョニングされた読み 込みアクティビティを、テーブルに対するクエリと同じ方法で計算します。唯一の違いは、ベース テーブル内の項目のサイズではなくインデックスエントリのサイズに基づいて計算が行われることで す。読み込みキャパシティーユニットの数は、返されたすべての項目について射影されたすべての属 性のサイズの合計です。結果は、次の 4 KB 境界まで切り上げられます。DynamoDB がプロビジョ ニング済みスループットの利用率を計算する方法の詳細については、「テーブルの読み書き要件の指 定 (p. 179)」を参照してください。 Query オペレーションによって返される結果の最大サイズは、1 MB です。これには、返されるすべ ての項目にわたる、すべての属性の名前と値のサイズが含まれます。 たとえば、各項目に 2000 バイトのデータが格納されている グローバルセカンダリインデックス があ るとします。このインデックスに対して Query を実行し、そのクエリによって 8 項目返されるとし ます。一致する項目の合計サイズは、2000 バイト × 8 項目 = 16,000 バイトです。これは、最も近い 4 KB 境界に切り上げられます。グローバルセカンダリインデックス のクエリは結果整合性があるの で、合計コストは、0.5 ×(16 KB/4 KB)、つまり、2 読み込みキャパシティーユニットです。 API Version 2012-08-10 342 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス 書き込みキャパシティーユニット テーブルの項目が追加、更新、または削除されたときに、グローバルセカンダリインデックス がこの 影響を受ける場合、グローバルセカンダリインデックス は、そのオペレーションに対してプロビジョ ニングされた書き込みキャパシティーユニットを消費します。書き込み用にプロビジョニングされた スループットの合計コストは、ベーステーブルに対する書き込みと、グローバルセカンダリインデッ クスの更新で消費された書き込みキャパシティーユニットの合計になります。テーブルへの書き込み には、グローバルセカンダリインデックス の更新は必要ないので、インデックスから消費される書き 込みキャパシティーはありません。 テーブルへの書き込みを正常に実行するために、テーブルとそのすべての グローバルセカンダリイン デックス に対するプロビジョニングされたスループット設定は、書き込みに対応できるだけの十分な 書き込みキャパシティーを備えている必要があります。十分でない場合、書き込みは調整されます。 グローバルセカンダリインデックス に項目を書き込むコストは、いくつかの要因に左右されます。 • インデックス付き属性が定義されたテーブルに新しい項目を書き込む場合、または既存の項目を更 新して未定義のインデックス付き属性を定義する場合には、インデックスへの項目の挿入に 1 回の 書き込みオペレーションが必要です。 • テーブルに対する更新によってインデックス付きキー属性の値が(A から B に)変更された場合に は、インデックスから既存の項目を削除し、インデックスに新しい項目を挿入するために、2 回の 書き込みが必要です。 • インデックス内に既存の項目があって、テーブルに対する書き込みによってインデックス付き属性 が削除された場合は、インデックスから古い項目の射影を削除するために、1 回の書き込みが必要 です。 • 項目の更新の前後にインデックス内に項目が存在しない場合は、インデックスで追加の書き込みコ ストは発生しません。 • テーブルに対する更新によってインデックスキースキーマの射影された属性の値のみが変更され、 インデックス付きキー属性の値は変更されない場合は、インデックスに射影された属性の値を更新 するために、1 回の書き込みが必要です。 これらすべての要因は、インデックス内の各項目のサイズが 1 KB 以下であるという前提で書き込み キャパシティーユニット数を算出します。インデックスエントリがそれよりも大きい場合は、書き込 みキャパシティーユニットを追加する必要があります。クエリが返す必要がある属性を特定し、それ らの属性だけをインデックスに射影することで、書き込みコストは最小になります。 グローバルセカンダリインデックス のストレージに関する考 慮事項 アプリケーションがテーブルに項目を書き込むと、DynamoDB では正しい属性のサブセットが、それ らの属性が現れる必要がある グローバルセカンダリインデックス に自動的にコピーされます。AWS アカウントでは、テーブル内の項目のストレージと、そのベーステーブルのグローバルセカンダリイ ンデックスにある属性のストレージに対して課金されます。 インデックス項目が使用するスペースの量は、次の量の合計になります。 • ベーステーブルのプライマリキー (パーティションキーとソートキー) のサイズのバイト数 • インデックスキー属性のサイズのバイト数 • 射影された属性(存在する場合)のサイズのバイト数 • インデックス項目あたり 100 bytes のオーバーヘッド グローバルセカンダリインデックスのストレージ要件の見積もりは、インデックス内の 1 項目の平均 サイズの見積もり値に、ベーステーブル内のグローバルセカンダリインデックスキー属性を持つ項目 の数を掛けて算出します。 API Version 2012-08-10 343 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス 特定の属性が定義されていない項目がテーブルに含まれていて、その属性がインデックスパーティ ションキーまたはソートキーとして定義されている場合、DynamoDB はその項目のデータをインデッ クスに書き込みません。 グローバルセカンダリインデックスの管理 このセクションでは、グローバルセカンダリインデックスを作成、変更、および削除する方法につい て説明します。 トピック • テーブルとグローバルセカンダリインデックスの作成 (p. 344) • テーブルでのグローバルセカンダリインデックスの説明 (p. 344) • 既存のテーブルへのグローバルセカンダリインデックスの追加 (p. 345) • インデックス作成の変更 (p. 347) • テーブルからのグローバルセカンダリインデックスの削除 (p. 348) • インデックスキー違反の検出と修正 (p. 348) テーブルとグローバルセカンダリインデックスの作成 1 つ以上のグローバルセカンダリインデックスがあるテーブルを作成するに は、GlobalSecondaryIndexes オペレーションを CreateTable パラメータと共に使用します。最 大限のクエリの柔軟性を得るために、テーブルごとに最大 5 個のグローバルセカンダリインデックス を作成できます。 インデックスパーティションキーとなる 1 つの属性を指定する必要があります。必要に応じて、イ ンデックスソートキーに別の属性を指定できます。これらのキー属性は、テーブルのキー属性と同 じである必要はありません。たとえば、GameScores テーブル (「グローバルセカンダリインデック ス (p. 336)」を参照) で、TopScore も TopScoreDateTime もキー属性ではありませんが、パーティ ションキーに TopScore を使用し、ソートキーに TopScoreDateTime を使用して、グローバルセカン ダリインデックスを作成できます。このようなインデックスを使用して、高いスコアとゲームをプレ イする時間帯の間に相関関係があるかどうかを判断できます。 各インデックスキー属性は、文字列型、数値型、またはバイナリ型である必要があります (ドキュメン トまたはセットにすることはできません)。任意のデータ型の属性をグローバルセカンダリインデック スに射影できます。これには、スカラー、ドキュメント、およびセットが含まれます。データ型の詳 細なリストについては、「データ型 (p. 12)」を参照してください。 ReadCapacityUnits および ProvisionedThroughput で構成される、インデックス用の WriteCapacityUnits 設定を指定する必要があります。このプロビジョニングされたスループット 設定は、テーブルに対するその設定から独立していますが、同じように動作します。詳細について は、「プロビジョニングされたスループットに関する考慮事項(グローバルセカンダリインデック ス) (p. 342)」を参照してください。 テーブルでのグローバルセカンダリインデックスの説明 テーブルのすべての グローバルセカンダリインデックスes のステータスを表示するに は、DescribeTable オペレーションを使用します。応答の GlobalSecondaryIndexes 部分は、そ れぞれの現在のステータス(IndexStatus)と共に、テーブルのすべてのインデックスを示します。 グローバルセカンダリインデックスの IndexStatus は次のいずれかになります。 • CREATING - インデックスは現在作成中で、まだ使用することはできません。 • ACTIVE - インデックスは使用する準備が整っていて、アプリケーションはインデックスで Query オペレーションを実行できます。 • UPDATING - インデックスのプロビジョニングされたスループット設定を変更中です。 • DELETING - インデックスは現在削除中で、使用できなくなりました。 API Version 2012-08-10 344 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス DynamoDB がグローバルセカンダリインデックスの作成を終了すると、インデックスのステータスは CREATING から ACTIVE に変わります。 既存のテーブルへのグローバルセカンダリインデックスの追加 既存のテーブルにグローバルセカンダリインデックスを追加するには、UpdateTable オペレーショ ンを GlobalSecondaryIndexUpdates パラメータと共に使用します。以下を指定する必要がありま す。 • インデックス名。名前は、テーブルのすべてのインデックス間で一意である必要があります。 • インデックスのキースキーマ。インデックスパーティションキー用の 1 つの属性を指定する必要 があります。必要に応じて、インデックスソートキーに別の属性を指定できます。これらのキー属 性は、テーブルのキー属性と同じである必要はありません。各スキーマ属性のデータ型はスカラー (文字列、数値、またはバイナリ)である必要があります。 • テーブルからインデックスに射影する属性: • KEYS_ONLY – インデックスの各項目は、テーブルのパーティションキーとソートキー値、および インデックスキー値のみで構成されます。 • INCLUDE - KEYS_ONLY の属性に加えて、セカンダリインデックスにその他の非キー属性が含まれ るように指定できます。 • ALL - インデックスにソーステーブルのすべての属性が含まれます。 • ReadCapacityUnits および WriteCapacityUnits で構成される、インデックスのプロビジョニ ングされたスループット設定。これらのプロビジョニングされたスループット設定は、テーブルの 設定から独立しています。 UpdateTable オペレーションごとに、1 つのグローバルセカンダリインデックスを作成または削除で きます。ただし、複数の UpdateTable オペレーションを同時に実行すれば、複数のインデックスを 同時に作成できます。テーブルでこれらの UpdateTable オペレーションを一度に 5 つまで実行でき ます。各オペレーションは厳密に 1 つのインデックスを作成できます。 Note 処理中のグローバルセカンダリインデックスの作成をキャンセルすることはできません。 インデックス作成のフェーズ 既存のテーブルに新しいグローバルセカンダリインデックスを追加すると、テーブルはインデックス の作成中も引き続き使用可能になります。ただし、Query オペレーションの新しいインデックスは、 そのステータスが CREATING から ACTIVE に変わるまで使用できません。 バックグラウンドでは、DynamoDB が次の 2 つの段階でインデックスを作成します。 リソースの割り当て DynamoDB はインデックスの作成に必要なコンピューティングリソースおよびストレージリソー スを割り当てます。 リソースの割り当てフェーズ中は、IndexStatus 属性は CREATING になり、Backfilling 属 性は false になります。テーブルのステータスとそのすべてのセカンダリインデックスを取得する には、DescribeTable オペレーションを使用します。 インデックスがリソースの割り当てフェーズにあるときは、その親テーブルを削除したり、イン デックスまたはテーブルのプロビジョニングされたスループットを変更したりすることはできま せん。テーブルの他のインデックスを追加または削除することはできませんが、これらの他のイ ンデックスのプロビジョニングされたスループットを変更することができます。 バックフィリング DynamoDB は、テーブルの各項目については、射影(KEYS_ONLY、INCLUDE、または ALL)に 基づいて、インデックスに書き込む一連の属性を決定します。次に、これらの属性をインデック スに書き込みます。DynamoDB はバックフィルフェーズ中に、テーブルで追加、削除、または更 API Version 2012-08-10 345 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス 新中の項目を追跡します。また、これらの項目の属性は、必要に応じてインデックスで追加、削 除、または更新されます。 バックフィリングフェーズ中に、IndexStatus 属性は CREATING になり、Backfilling 属性 は true になります。テーブルのステータスとそのすべてのセカンダリインデックスを取得するに は、DescribeTable オペレーションを使用します。 インデックスのバックフィリング中に親テーブルを削除することはできません。ただし、テーブ ルと任意のグローバルセカンダリインデックスのプロビジョニングされたスループットを変更す ることはできます。 Note バックフィリングフェーズ中に、違反のある項目の書き込みは、成功するものと、拒否 されるものがあります。バックフィリング後に、新しいインデックスのキースキーマに 違反する、項目へのすべての書き込みは拒否されます。バックフィリングフェーズが完了 したら、Violation Detector ツールを実行して、発生した可能性のあるキーの違反を検出 し、解決することをお勧めします。詳細については、「インデックスキー違反の検出と修 正 (p. 348)」を参照してください。 リソースの割り当てフェーズとバックフィリングフェーズの進行中は、インデックスは CREATING 状 態になります。この間、DynamoDB はテーブルで読み取りオペレーションを実行します。この読み取 りオペレーションには課金されません。 インデックスの作成が完了すると、そのステータスは ACTIVE に変わります。状態が ACTIVE になる まで、インデックスに対して Query や Scan を実行することはできません。 Note 場合によっては、DynamoDB は、インデックスキーの違反のため、テーブルからインデック スにデータを書き込めない場合があります。これは、属性値のデータ型がインデックスキー スキーマのデータ型と一致しない場合や、属性のサイズがインデックスキー属性の最大長を 超える場合に発生することがあります。インデックスキーの違反によって、グローバルセカ ンダリインデックスの作成に影響はありません。ただし、インデックスが ACTIVE になる と、違反のあるキーはインデックスに存在しません。 DynamoDB には、これらの問題を見つけて解決するためのスタンドアロンツールが用意され ています。詳細については、「インデックスキー違反の検出と修正 (p. 348)」を参照してく ださい。 大きなテーブルへのグローバルセカンダリインデックスの追加 グローバルセカンダリインデックスの作成に必要な時間は、次のようないくつかの要因によって異な ります。 • テーブルのサイズ • インデックスへの組み込みの対象になるテーブルの項目数 • インデックスに射影される属性の数 • インデックスのプロビジョニングされた書き込みキャパシティー • インデックス作成中のメインテーブルでの書き込みアクティビティ 非常に大きなテーブルにグローバルセカンダリインデックスを追加する場合、作成プロセスが完了す るまでに長い時間がかかることがあります。進捗状況を監視し、インデックスに十分な書き込みキャ パシティーがあるかどうか判断するには、次の Amazon CloudWatch メトリクスを確認します。 • OnlineIndexPercentageProgress • OnlineIndexConsumedWriteCapacity API Version 2012-08-10 346 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス • OnlineIndexThrottleEvents Note DynamoDB に関連する CloudWatch メトリクスの詳細については、「DynamoDB Metrics (p. 497)」を参照してください。 インデックスでプロビジョニングされた書き込みスループット設定が低すぎる場合、インデックスの 作成にはより多くの時間がかかります。新しいグローバルセカンダリインデックスの作成に要する時 間を短くするため、プロビジョニングされる書き込みキャパシティーを一時的に増やすことができま す。 Note 一般的なルールとして、インデックスのプロビジョニングされる書き込みキャパシティー を、テーブルの書き込みキャパシティーの 1.5 倍に設定することをお勧めします。これは多く のユースケースに適した設定ですが、実際の要件はこれ以上またはこれ以下である可能性が あります。 DynamoDB は、インデックスのバックフィリング中に内部的なシステムキャパシティーを使用して テーブルからの読み取りを行います。これは、インデックス作成の影響を最小化し、テーブルの読み 取りキャパシティーが不足しないようにするためです。 ただし、受信書き込みアクティビティのボリュームが、インデックスのプロビジョニングされた書き 込みキャパシティーを超える可能性があります。これは、インデックスへの書き込みアクティビティ が調整されているため、インデックス作成により多くの時間がかかるボトルネックのシナリオです。 インデックスの作成中に、インデックスの Amazon CloudWatch のメトリクスを監視して、消費され た書き込みキャパシティーが、プロビジョニングされたキャパシティーを超えているかどうか判断す ることをお勧めします。ボトルネックのシナリオでは、インデックスでプロビジョニングされた書き 込みキャパシティーを増やし、バックフィルフェーズ中の書き込み調整を避ける必要があります。 インデックスが作成されたら、アプリケーションの通常の使用を反映するように、プロビジョニング された書き込みキャパシティーを設定します。 インデックス作成の変更 インデックスの作成中に、DescribeTable オペレーションを使用して、そのフェーズを判断できま す。インデックスの説明には、現在、DynamoDB がテーブルから項目と共にインデックスを読み込 んでいるかどうかを示すためのブール属性 Backfilling が含まれます。Backfilling が true の場 合、リソースの割り当てフェーズは完了していて、インデックスはバックフィル中です。 バックフィルの進行中は、インデックス用にプロビジョニングされたスループットパラメータを更新 できます。インデックス作成を高速化するために、これを行うことがあります。作成中にインデック スの書き込みキャパシティーを増やし、その後で減らすことができます。インデックスのプロビジョ ニングされたスループット設定を変更するには、UpdateTable オペレーションを使用します。イン デックスのステータスは UPDATING に変わり、Backfilling はインデックスの使用準備ができるま で true になります。 バックフィリングフェーズ中は、テーブルの他のインデックスを追加または削除することはできませ ん。 Note CreateTable オペレーションの一部として作成されたインデックスについ て、Backfilling 属性は DescribeTable 出力に表示されません。詳細については、「イン デックス作成のフェーズ (p. 345)」を参照してください。 API Version 2012-08-10 347 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス テーブルからのグローバルセカンダリインデックスの削除 グローバルセカンダリインデックスが不要になった場合は、UpdateTable オペレーションを使用し て削除することができます。 UpdateTable オペレーションごとに、1 つのグローバルセカンダリインデックスのみを削除できま す。ただし、複数の UpdateTable オペレーションを同時に実行することにより、一度に複数のイン デックスを削除できます。テーブルでこれらの UpdateTable オペレーションを一度に 5 つまで実行 できます。各オペレーションは厳密に 1 つのインデックスを削除できます。 グローバルセカンダリインデックスの削除中に、親テーブルの読み取りアクティビティまたは書き込 みアクティビティに影響はありません。削除が進行中でも、その他のインデックスでプロビジョニン グされたスループットを変更できます。 Note DeleteTable アクションを使用してテーブルを削除すると、そのテーブルのすべてのグロー バルセカンダリインデックスも削除されます。 インデックスキー違反の検出と修正 グローバルセカンダリインデックス作成のバックフィルフェーズの間、DynamoDB はテーブルの各項 目を調べ、インデックスに含めるかどうかを判断します。一部の項目は、インデックスキーの違反を 引き起こすため、この対象とはならない場合があります。このような場合、項目はテーブルに残りま すが、インデックスにはその項目に対応するエントリは作成されません。 次の場合に、インデックスキーの違反が発生します。 • 属性値とインデックスキースキーマのデータ型の間にデータ型の不一致がある。たとえ ば、GameScores テーブルのいずれかの項目に、文字列型の値 TopScore があるとします。数値型 のパーティションキー TopScore をグローバルセカンダリインデックスに追加すると、テーブルの 項目はインデックスキーに違反します。 • テーブルの属性値が、インデックスキー属性の最大長を超えている。パーティションキーの最大長 は 2048 バイト で、ソートキーの最大長は 1024 バイト です。テーブルに対応する属性値のいずれ かがこれらの制限を超えた場合は、テーブルの項目がインデックスキーに違反します。 インデックスキーの違反が発生した場合、バックフィルフェーズは中断なく続行しますが、違反のあ る項目はインデックスには含まれません。バックフィルフェーズが完了すると、新しいインデックス のキースキーマに違反する項目へのすべての書き込みは拒否されます。 インデックスキーに違反したテーブルの属性値を特定し、修正するには、Violation Detector ツールを 使用します。Violation Detector を実行するには、スキャンするテーブルの名前、グローバルセカン ダリインデックスパーティションキーとソートキーの名前とデータ型、およびインデックスキーの違 反が見つかった場合に実行するアクションを指定する設定ファイルを作成します。Violation Detector は、次の 2 つのモードのどちらかで実行できます。 • 検出モード - インデックスキーの違反を検出します。グローバルセカンダリインデックスでキー違 反を発生させるようなテーブル項目を報告するには、検出モードを使用します(オプションで、こ れらのテーブル項目が見つかったらすぐに削除するようリクエストできます)。検出モードの出力 はファイルに書き込まれ、詳細な分析に使用できます。 • 修正モード - インデックスキーの違反を修正します。修正モードでは、Violation Detector は検出 モードからの出力ファイルと同じ形式の入力ファイルを読み取ります。修正モードでは入力ファイ ルからレコードを読み取り、レコードごとに、テーブルの対応する項目を削除または更新します (項目の更新を選択する場合は、入力ファイルを編集し、更新の適切な値を設定する必要がありま す)。 API Version 2012-08-10 348 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス Violation Detector のダウンロードと実行 Violation Detector は、実行可能 Java アーカイブ(.jar ファイル)の形で入手で き、Windows、Mac、または Linux コンピュータで動作します。Violation Detector には Java 1.7(ま たはそれ以降)と Maven が必要です。 • https://github.com/awslabs/dynamodb-online-index-violation-detector README.md ファイルの手順に従い、Maven を使用して Violation Detector をダウンロードし、イン ストールします Violation Detector を起動するには、ViolationDetector.java を作成したディレクトリに移動し、 次のコマンドを入力します。 java -jar ViolationDetector.jar [options] Violation Detector コマンドラインでは、次のオプションを使用できます。 • -h | --help – Violation Detector の使用方法の概要とオプションを出力します。 • -p | --configFilePath value - Violation Detector の設定ファイルの完全修飾名。詳細について は、「Violation Detector の設定ファイル (p. 349)」を参照してください。 • -t | --detect value - テーブルのインデックスキー違反を検出し、Violation Detector の出力 ファイルに書き込みます。このパラメータ値を keep に設定すると、キーの違反がある項目は変更 されません。値を delete に設定すると、キーの違反がある項目はテーブルから削除されます。 • -c | --correct value - 入力ファイルからインデックスキーの違反を読み取り、テーブルの項目 で修正アクションを実行します。このパラメータの値を update に設定すると、キーの違反がある 項目は、違反がない新しい値で更新されます。値を delete に設定すると、キーの違反がある項目 はテーブルから削除されます。 Violation Detector の設定ファイル 実行時に、Violation Detector ツールには設定ファイルが必要です。このファイルのパラメータによ り、Violation Detector がアクセスできる DynamoDB リソースと、消費できるプロビジョニングされ たスループットが決まります。次の表は、これらのパラメータを示しています。 パラメータ名 説明 必須? awsCredentialsFile AWS 認証情報を含むファイル の完全修飾名。認証情報ファイ ルは次の形式である必要があり ます。 はい accessKey = access_key_id_goes_here secretKey = secret_key_goes_here dynamoDBRegion テーブルが存在する AWS リー ジョン。例: us-west-2。 はい tableName スキャンする DynamoDB テー ブルの名前。 はい gsiHashKeyName インデックスパーティション キーの名前。 はい API Version 2012-08-10 349 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス パラメータ名 説明 必須? gsiHashKeyType インデックスパーティション キーのデータ型 (文字列、数 値、またはバイナリ): はい S | N | B gsiRangeKeyName インデックスソートキーの名 前。インデックスにシンプルな プライマリキー (パーティショ ンキー) のみがある場合は、こ のパラメーターを指定しないで ください。 いいえ gsiRangeKeyType インデックスソートキーのデー タ型 (文字列、数値、またはバ イナリ): いいえ S | N | B インデックスにシンプルなプ ライマリキー (パーティション キー) のみがある場合は、この パラメーターを指定しないでく ださい。 出力ファイルにインデックス キーの違反の完全な詳細を書き 込むかどうか。true(デフォ ルト)に設定した場合、違反の ある項目に関する完全な情報が 報告されます。false に設定 した場合、違反数のみが報告さ れます。 いいえ recordGsiValueInViolationRecord 違反のあるインデックスキーの 値を出力ファイルに書き込むか どうか。true(デフォルト) に設定した場合、キーの値が報 告されます。false に設定し た場合、キーの値は報告されま せん。 いいえ recordDetails API Version 2012-08-10 350 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス パラメータ名 説明 必須? detectionOutputPath Violation Detector 出力ファ イルの完全なパス。このパラ メータは、ローカルディレクト リや Amazon Simple Storage Service (Amazon S3) への書き 込みをサポートします。次に例 を示します。 いいえ detectionOutputPath = //local/path/ filename.csv detectionOutputPath = s3://bucket/filename.csv 出力ファイルの情報 が、CSV 形式(カンマ 区切り値)で表示されま す。detectionOutputPath を設定しない場合、 出力ファイルは violation_detection.csv という名前になり、現在の作 業ディレクトリに書き込まれま す。 numOfSegments Violation Detector がテーブル をスキャンするときに使用する 並列スキャンセグメントの数。 デフォルト値は 1 です。この 場合、テーブルはシーケンシャ ルにスキャンされます。値が 2 以上の場合、Violation Detector はテーブルを多数の論理セグメ ントと同数のスキャンスレッド に分割します。 numOfSegments の最大設定は 4096 です。 通常、大きなテーブルの場合、 並列スキャンはシーケンシャル スキャンより高速です。また、 テーブルが複数のパーティショ ンにまたがるほど大きい場合、 並列スキャンでは複数のパー ティションにわたって均等に読 み取りアクティビティが分散さ れます。 DynamoDB での並列スキャン の詳細については、「並列ス キャン (p. 292)」を参照して ください。 API Version 2012-08-10 351 いいえ Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス パラメータ名 説明 必須? numOfViolations 出力ファイルに書き込むイ ンデックスキーの違反の上 限。-1(デフォルト)に設定 された場合、テーブル全体が スキャンされます。正の整数に 設定されている場合、Violation Detector はその数の違反が発生 すると停止します。 いいえ numOfRecords スキャンするテーブルの項目 数。-1(デフォルト)に設定さ れた場合、テーブル全体がス キャンされます。正の整数に 設定されている場合、Violation Detector はテーブルでその数の 項目をスキャンした後に停止し ます。 いいえ readWriteIOPSPercent テーブルのスキャン中に消費さ れた、プロビジョニングされた 読み込みキャパシティーユニッ トの割合を管理します。有効 な値の範囲は 1~100 です。デ フォルト値(25)は、Violation Detector が、プロビジョニング された読み取りスループットの 25% 以上を消費しないことを 意味します。 いいえ correctionInputPath Violation Detector の修正 入力ファイルの完全なパ ス。Violation Detector を修正 モードで実行すると、このファ イルのコンテンツは、テーブ ルでグローバルセカンダリイン デックスに違反するデータ項目 を変更または削除するために使 用されます。 いいえ correctionInputPath ファイルの形式 は、detectionOutputPath ファイルの形式と同じです。こ れにより、検出モードからの出 力を修正モードで入力として処 理することができます。 API Version 2012-08-10 352 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス パラメータ名 説明 必須? correctionOutputPath Violation Detector の修正出力 ファイルの完全なパス。この ファイルは、更新エラーがある 場合にのみ作成されます。 いいえ このパラメータは、ローカ ルディレクトリや Amazon Simple Storage Service (Amazon S3) への書き込みをサ ポートします。次に例を示しま す。 correctionOutputPath = //local/path/ filename.csv correctionOutputPath = s3://bucket/filename.csv 出力ファイルの情報 が、CSV 形式(カンマ 区切り値)で表示されま す。correctionOutputPath を設定しない場合、 出力ファイルは violation_update_errors.csv という名前になり、現在の作業 ディレクトリに書き込まれま す。 検出 インデックスキーの違反を検出するには、Violation Detector を --detect コマンドラインオプショ ンと共に使用します。このオプションの動作を確認するには、「テーブルの作成とサンプルデータの ロード (p. 166)」の ProductCatalog の表を検討してください。次に示すのは、テーブル項目のリス トです。プライマリキー(Id)および Price 属性のみが表示されています。 Id(プライマリキー) 価格 101 -2 102 20 103 200 201 100 202 200 203 300 204 400 205 500 API Version 2012-08-10 353 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス Price のすべての値は数値型です。ただし、DynamoDB はスキーマレスであるため、数値以外の Price を持つ項目を追加することができます。たとえば、別の項目を ProductCatalog テーブルに 追加するとします。 Id(プライマリキー) 価格 999 "Hello" テーブルには、これで合計 9 個の項目があります。 ここで、テーブルに新しいグローバルセカンダリインデックス PriceIndex を追加します。このイン デックスのプライマリキーは、数値型のパーティションキー Price です。インデックスの作成後、8 個の項目が含まれますが、ProductCatalog テーブルには 9 個の項目があります。この不一致の理由 は、値 "Hello" は文字列型ですが、PriceIndex には数値型のプライマリキーがあることです。文 字列値はグローバルセカンダリインデックスキーに違反するので、インデックスには存在しません。 このシナリオで Violation Detector を使用するには、まず次のような設定ファイルを作成します。 # Properties file for violation detection tool configuration. # Parameters that are not specified will use default values. awsCredentialsFile = /home/alice/credentials.txt dynamoDBRegion = us-west-2 tableName = ProductCatalog gsiHashKeyName = Price gsiHashKeyType = N recordDetails = true recordGsiValueInViolationRecord = true detectionOutputPath = ./gsi_violation_check.csv correctionInputPath = ./gsi_violation_check.csv numOfSegments = 1 readWriteIOPSPercent = 40 次に、この例のように Violation Detector を実行します。 $ java -jar ViolationDetector.jar --configFilePath config.txt --detect keep Violation detection started: sequential scan, Table name: ProductCatalog, GSI name: PriceIndex Progress: Items scanned in total: 9, Items scanned by this thread: 9, Violations found by this thread: 1, Violations deleted by this thread: 0 Violation detection finished: Records scanned: 9, Violations found: 1, Violations deleted: 0, see results at: ./gsi_violation_check.csv recordDetails 設定パラメータが true に設定されている場合、Violation Detector は次の例のよう に、出力ファイルにそれぞれの違反の詳細を書き込みます。 Table Hash Key,GSI Hash Key Value,GSI Hash Key Violation Type,GSI Hash Key Violation Description,GSI Hash Key Update Value(FOR USER),Delete Blank Attributes When Updating?(Y/N) 999,"{""S"":""Hello""}",Type Violation,Expected: N Found: S,, 出力ファイルはカンマ区切り値(CSV)形式です。ファイルの最初の行はヘッダーで、インデックス キーに違反する項目ごとに、1 つのレコードが続きます。これら違反レコードのフィールドは次のと おりです。 API Version 2012-08-10 354 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス • Table Hash Key - テーブルの項目のパーティションキー値。 • Table Range Key - テーブルの項目のソートキーの値。 • GSI Hash Key Value - グローバルセカンダリインデックスのパーティションキー値。 • GSI Hash Key Violation Type - Type Violation または Size Violation。 • GSI Hash Key Violation Description - 違反の原因。 • GSI Hash Key Update Value(FOR USER) - 修正モードで、属性に対してユーザーが指定した新しい 値。 • GSI Range Key Value - グローバルセカンダリインデックスのソートキーの値 • GSI Range Key Violation Type - Type Violation または Size Violation。 • GSI Range Key Violation Description - 違反の原因。 • GSI Range Key Update Value(FOR USER) - 修正モードで、属性に対してユーザーが指定した新し い値。 • Delete Blank Attribute When Updating(Y/N) - 修正モードで、テーブルの違反項目を削除する(Y) か維持する(N)かを決定します。ただし、次のフィールドのどちらが空白である場合のみです。 • GSI Hash Key Update Value(FOR USER) • GSI Range Key Update Value(FOR USER) これらのうち、いずれかのフィールドが空でない場合、Delete Blank Attribute When Updating(Y/N) の効果はありません。 Note 出力形式は、設定ファイルおよびコマンドラインツールオプションによって異なることがあ ります。たとえば、テーブルにシンプルなプライマリキー (ソートキーなし) がある場合、出 力にソートキーフィールドは含まれません。 ファイルの違反レコードは、ソート順にならない可能性があります。 修正 インデックスキーの違反を修正するには、Violation Detector を --correct コマンドラインオプショ ンと共に使用します。修正モードでは、Violation Detector は correctionInputPath パラメータで 指定された入力ファイルを読み取ります。このファイルは、detectionOutputPath ファイルと同じ 形式であるため、検出からの出力は修正用の入力として使用できます。 Violation Detector には、インデックスキーの違反を修正するために 2 つの異なる方法が用意されてい ます。 • 違反の削除 - 違反のある属性値を持つテーブル項目を削除します。 • 違反の更新 - テーブル項目を更新し、違反のある属性を違反のない値で置き換えます。 どちらの場合も、修正モードの入力として検出モードの出力ファイルを使用できます。 ProductCatalog の例を引き続き使用し、違反のある項目をテーブルから削除するとします。これを 行うには、次のコマンドラインを使用します。 $ java -jar ViolationDetector.jar --configFilePath config.txt --correct delete この時点で、違反のある項目を削除するかどうか確認が求められます。 API Version 2012-08-10 355 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス Are you sure to delete all violations on the table?y/n y Confirmed, will delete violations on the table... Violation correction from file started: Reading records from file: ./ gsi_violation_check.csv, will delete these records from table. Violation correction from file finished: Violations delete: 1, Violations Update: 0 これで、ProductCatalog と PriceIndex の両方に同じ数の項目の数が含まれました。 グローバルセカンダリインデックス の使用 : Java AWS SDK for Java ドキュメント API を使用して、1 つ以上の グローバルセカンダリインデックス を 持つテーブルを作成し、テーブルのインデックスについて説明し、インデックスを使用してクエリを 実行することができます。 以下に、テーブルオペレーションの一般的な手順を示します。 1. DynamoDB クラスのインスタンスを作成します。 2. 対応するリクエストオブジェクトを作成して、オペレーションについて必要なパラメータとオプ ションパラメータを入力します。 3. 前述のステップで作成したクライアントから提供された適切なメソッドを呼び出します。 グローバルセカンダリインデックス を使用したテーブルの作成 グローバルセカンダリインデックス は、テーブルの作成と同時に作成できます。そのために は、CreateTable を使用して、1 つ以上の グローバルセカンダリインデックス の仕様を指定しま す。次の Java コードスニペットでは、気象データに関する情報を格納するテーブルを作成します。 パーティションキーは Location で、ソートキーは Date です。PrecipIndex という名前の グローバル セカンダリインデックス は、さまざまな場所の降水量データに高速アクセスできます。 次に、DynamoDB ドキュメント API を使用して、グローバルセカンダリインデックス があるテーブ ルを作成するステップを示します。 1. DynamoDB クラスのインスタンスを作成します。 2. リクエスト情報を指定する CreateTableRequest クラスのインスタンスを作成します。 テーブル名、プライマリキー、プロビジョニング済みスループットの値を指定する必要がありま す。グローバルセカンダリインデックスについては、インデックス名、そのプロビジョニングされ たスループット設定、インデックスソートキーの属性定義、インデックスのキースキーマ、属性射 影を指定する必要があります。 3. リクエストオブジェクトをパラメータとして指定して、createTable メソッドを呼び出します。 次の Java コードスニペットは、前述のステップを示しています。このスニペットでは、グローバル セカンダリインデックス(PrecipIndex)を持つテーブル(WeatherData)を作成します。インデック スパーティションキーは Date で、そのソートキーは Precipitation です。すべてのテーブル属性がイ ンデックスに射影されます。ユーザーは、このインデックスに対してクエリを実行して、特定の日付 の気象データを取得でき、必要に応じて、降水量別にデータを並べ替えることができます。 Precipitation はテーブルのキー属性ではないので、必須ではありません。ただし、Precipitation のない WeatherData 項目は PrecipIndex に現れません。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); API Version 2012-08-10 356 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス // Attribute definitions ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("Location") .withAttributeType("S")); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("Date") .withAttributeType("S")); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("Precipitation") .withAttributeType("N")); // Table key schema ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>(); tableKeySchema.add(new KeySchemaElement() .withAttributeName("Location") .withKeyType(KeyType.HASH)); //Partition key tableKeySchema.add(new KeySchemaElement() .withAttributeName("Date") .withKeyType(KeyType.RANGE)); //Sort key // PrecipIndex GlobalSecondaryIndex precipIndex = new GlobalSecondaryIndex() .withIndexName("PrecipIndex") .withProvisionedThroughput(new ProvisionedThroughput() .withReadCapacityUnits((long) 10) .withWriteCapacityUnits((long) 1)) .withProjection(new Projection().withProjectionType(ProjectionType.ALL)); ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>(); indexKeySchema.add(new KeySchemaElement() .withAttributeName("Date") .withKeyType(KeyType.HASH)); //Partition key indexKeySchema.add(new KeySchemaElement() .withAttributeName("Precipitation") .withKeyType(KeyType.RANGE)); //Sort key precipIndex.setKeySchema(indexKeySchema); CreateTableRequest createTableRequest = new CreateTableRequest() .withTableName("WeatherData") .withProvisionedThroughput(new ProvisionedThroughput() .withReadCapacityUnits((long) 5) .withWriteCapacityUnits((long) 1)) .withAttributeDefinitions(attributeDefinitions) .withKeySchema(tableKeySchema) .withGlobalSecondaryIndexes(precipIndex); Table table = dynamoDB.createTable(createTableRequest); System.out.println(table.getDescription()); DynamoDB がテーブルを作成し、テーブルのステータスを ACTIVE に設定するまで待機する必要があ ります。その後は、データ項目をテーブルに書き込むことが可能になります。 API Version 2012-08-10 357 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス グローバルセカンダリインデックス のあるテーブルの説明 テーブルの グローバルセカンダリインデックス に関する情報を取得するには、DescribeTable を使 用します。各インデックスについて、名前、キースキーマ、射影された属性にアクセスできます。 次に、テーブルの グローバルセカンダリインデックス 情報にアクセスするステップを示します。 1. DynamoDB クラスのインスタンスを作成します。 2. 操作対象のインデックスを表すために、Table クラスのインスタンスを作成します。 3. Table オブジェクトで describe メソッドを呼び出します。 次の Java コードスニペットは、前述のステップを示しています。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); Table table = dynamoDB.getTable("WeatherData"); TableDescription tableDesc = table.describe(); Iterator<GlobalSecondaryIndexDescription> gsiIter = tableDesc.getGlobalSecondaryIndexes().iterator(); while (gsiIter.hasNext()) { GlobalSecondaryIndexDescription gsiDesc = gsiIter.next(); System.out.println("Info for index " + gsiDesc.getIndexName() + ":"); Iterator<KeySchemaElement> kseIter = gsiDesc.getKeySchema().iterator(); while (kseIter.hasNext()) { KeySchemaElement kse = kseIter.next(); System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType()); } Projection projection = gsiDesc.getProjection(); System.out.println("\tThe projection type is: " + projection.getProjectionType()); if (projection.getProjectionType().toString().equals("INCLUDE")) { System.out.println("\t\tThe non-key projected attributes are: " + projection.getNonKeyAttributes()); } } グローバルセカンダリインデックス のクエリ グローバルセカンダリインデックス では、テーブルの Query を実行するのと同様の方法で、Query を使用できます。インデックス名、インデックスパーティションキーとソートキー (存在する場合) の クエリ基準、および返されるようにする属性を指定する必要があります。この例では、インデックス は PrecipIndex で、そのパーティションキーは Date で、ソートキーは Precipitation です。インデック スクエリは、特定の日付を対象に、降水量がゼロよりも大きい気象データをすべて返します。 以下に、AWS SDK for Java ドキュメント API を使用して グローバルセカンダリインデックス のクエ リを行う手順を示します。 1. 2. 3. 4. DynamoDB クラスのインスタンスを作成します。 操作対象のインデックスを表すために、Table クラスのインスタンスを作成します。 クエリを実行するインデックスの Index クラスのインスタンスを作成します。 Index オブジェクトで query メソッドを呼び出します。 API Version 2012-08-10 358 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス 属性名 Date は、DynamoDB の予約語です。したがって、式の属性名を KeyConditionExpression のプレースホルダーとして使用する必要があります。 次の Java コードスニペットは、前述のステップを示しています。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); Table table = dynamoDB.getTable("WeatherData"); Index index = table.getIndex("PrecipIndex"); QuerySpec spec = new QuerySpec() .withKeyConditionExpression("#d = :v_date and Precipitation = :v_precip") .withNameMap(new NameMap() .with("#d", "Date")) .withValueMap(new ValueMap() .withString(":v_date","2013-08-10") .withNumber(":v_precip",0)); ItemCollection<QueryOutcome> items = index.query(spec); Iterator<Item> iter = items.iterator(); while (iter.hasNext()) { System.out.println(iter.next().toJSONPretty()); } 例: AWS SDK for Java ドキュメント API を使用した グローバルセカンダリイ ンデックス 次の Java コード例では、グローバルセカンダリインデックス の操作方法を示します。この例で は、Issues という名前のテーブルを作成します。このテーブルは、ソフトウェア開発の単純なバグ 追跡システムで使用される可能性があります。パーティションキーは IssueId で、ソートキーは Title です。このテーブルには 3 つの グローバルセカンダリインデックス があります。 • CreateDateIndex — パーティションキーは CreateDate で、ソートキーは IssueId です。テーブ ルキーに加えて、属性 Description と Status がインデックスに射影されます。 • TitleIndex — パーティションキーは IssueId で、ソートキーは Title です。テーブルキー以外の 属性は、インデックスに射影されません。 • DueDateIndex — パーティションキーは DueDate で、ソートキーはありません。すべてのテーブル 属性がインデックスに射影されます。 Issues テーブルを作成した後、プログラムによって、ソフトウェアバグレポートを表すデータがテー ブルにロードされ、グローバルセカンダリインデックス を使用してそのデータに対してクエリが実行 されます。最後に、プログラムによって Issues テーブルが削除されます。 次のサンプルをテストするための詳しい手順については、「Java コードサンプル (p. 171)」を参照し てください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import java.util.ArrayList; import java.util.Iterator; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; API Version 2012-08-10 359 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス import import import import import import import import import import import import import import import com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Index; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.ItemCollection; com.amazonaws.services.dynamodbv2.document.QueryOutcome; com.amazonaws.services.dynamodbv2.document.Table; com.amazonaws.services.dynamodbv2.document.spec.QuerySpec; com.amazonaws.services.dynamodbv2.document.utils.ValueMap; com.amazonaws.services.dynamodbv2.model.AttributeDefinition; com.amazonaws.services.dynamodbv2.model.CreateTableRequest; com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex; com.amazonaws.services.dynamodbv2.model.KeySchemaElement; com.amazonaws.services.dynamodbv2.model.KeyType; com.amazonaws.services.dynamodbv2.model.Projection; com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; public class DocumentAPIGlobalSecondaryIndexExample { static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); public static String tableName = "Issues"; public static void main(String[] args) throws Exception { createTable(); loadData(); queryIndex("CreateDateIndex"); queryIndex("TitleIndex"); queryIndex("DueDateIndex"); deleteTable(tableName); } public static void createTable() { // Attribute definitions ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("IssueId") .withAttributeType("S")); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("Title") .withAttributeType("S")); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("CreateDate") .withAttributeType("S")); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("DueDate") .withAttributeType("S")); // Key schema for table API Version 2012-08-10 360 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>(); tableKeySchema.add(new KeySchemaElement() .withAttributeName("IssueId") .withKeyType(KeyType.HASH)); //Partition key tableKeySchema.add(new KeySchemaElement() .withAttributeName("Title") .withKeyType(KeyType.RANGE)); //Sort key // Initial provisioned throughput settings for the indexes ProvisionedThroughput ptIndex = new ProvisionedThroughput() .withReadCapacityUnits(1L) .withWriteCapacityUnits(1L); // CreateDateIndex GlobalSecondaryIndex createDateIndex = new GlobalSecondaryIndex() .withIndexName("CreateDateIndex") .withProvisionedThroughput(ptIndex) .withKeySchema( new KeySchemaElement() .withAttributeName("CreateDate") .withKeyType( KeyType.HASH), //Partition key new KeySchemaElement() .withAttributeName("IssueId") .withKeyType(KeyType.RANGE)) //Sort key .withProjection(new Projection() .withProjectionType("INCLUDE") .withNonKeyAttributes("Description", "Status")); // TitleIndex GlobalSecondaryIndex titleIndex = new GlobalSecondaryIndex() .withIndexName("TitleIndex") .withProvisionedThroughput(ptIndex) .withKeySchema(new KeySchemaElement() .withAttributeName("Title") .withKeyType(KeyType.HASH), //Partition key new KeySchemaElement() .withAttributeName("IssueId") .withKeyType(KeyType.RANGE)) //Sort key .withProjection(new Projection() .withProjectionType("KEYS_ONLY")); // DueDateIndex GlobalSecondaryIndex dueDateIndex = new GlobalSecondaryIndex() .withIndexName("DueDateIndex") .withProvisionedThroughput(ptIndex) .withKeySchema( new KeySchemaElement() .withAttributeName("DueDate") .withKeyType(KeyType.HASH)) //Partition key .withProjection(new Projection() .withProjectionType("ALL")); CreateTableRequest createTableRequest = new CreateTableRequest() .withTableName(tableName) .withProvisionedThroughput( new ProvisionedThroughput() .withReadCapacityUnits( (long) 1) .withWriteCapacityUnits( (long) 1)) .withAttributeDefinitions(attributeDefinitions) .withKeySchema(tableKeySchema) API Version 2012-08-10 361 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス .withGlobalSecondaryIndexes(createDateIndex, titleIndex, dueDateIndex); System.out.println("Creating table " + tableName + "..."); dynamoDB.createTable(createTableRequest); // Wait for table to become active System.out.println("Waiting for " + tableName + " to become ACTIVE..."); try { Table table = dynamoDB.getTable(tableName); table.waitForActive(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void queryIndex(String indexName) { Table table = dynamoDB.getTable(tableName); System.out.println ("\n***********************************************************\n"); System.out.print("Querying index " + indexName + "..."); Index index = table.getIndex(indexName); ItemCollection<QueryOutcome> items = null; QuerySpec querySpec = new QuerySpec(); if (indexName == "CreateDateIndex") { System.out.println("Issues filed on 2013-11-01"); querySpec.withKeyConditionExpression("CreateDate = :v_date and begins_with(IssueId, :v_issue)") .withValueMap(new ValueMap() .withString(":v_date","2013-11-01") .withString(":v_issue","A-")); items = index.query(querySpec); } else if (indexName == "TitleIndex") { System.out.println("Compilation errors"); querySpec.withKeyConditionExpression("Title = :v_title and begins_with(IssueId, :v_issue)") .withValueMap(new ValueMap() .withString(":v_title","Compilation error") .withString(":v_issue","A-")); items = index.query(querySpec); } else if (indexName == "DueDateIndex") { System.out.println("Items that are due on 2013-11-30"); querySpec.withKeyConditionExpression("DueDate = :v_date") .withValueMap(new ValueMap() .withString(":v_date","2013-11-30")); items = index.query(querySpec); } else { System.out.println("\nNo valid index name provided"); return; } Iterator<Item> iterator = items.iterator(); API Version 2012-08-10 362 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス System.out.println("Query: printing results..."); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } } public static void deleteTable(String tableName) { System.out.println("Deleting table " + tableName + "..."); Table table = dynamoDB.getTable(tableName); table.delete(); // Wait for table to be deleted System.out.println("Waiting for " + tableName + " to be deleted..."); try { table.waitForDelete(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void loadData() { System.out.println("Loading data into table " + tableName + "..."); // // // // IssueId, Title, Description, CreateDate, LastUpdateDate, DueDate, Priority, Status putItem("A-101","Compilation error", "Can't compile Project X - bad version number. What does this mean?", "2013-11-01", "2013-11-02", "2013-11-10", 1, "Assigned"); putItem("A-102","Can't read data file", "The main data file is missing, or the permissions are incorrect", "2013-11-01", "2013-11-04", "2013-11-30", 2, "In progress"); putItem("A-103", "Test failure", "Functional test of Project X produces errors", "2013-11-01", "2013-11-02", "2013-11-10", 1, "In progress"); putItem("A-104", "Compilation error", "Variable 'messageCount' was not initialized.", "2013-11-15", "2013-11-16", "2013-11-30", 3, "Assigned"); putItem("A-105", "Network issue", "Can't ping IP address 127.0.0.1. Please fix this.", API Version 2012-08-10 363 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス "2013-11-15", "2013-11-16", "2013-11-19", 5, "Assigned"); } public static void putItem( String issueId, String title, String description, String createDate, String lastUpdateDate, String dueDate, Integer priority, String status) { Table table = dynamoDB.getTable(tableName); Item item = new Item() .withPrimaryKey("IssueId", issueId) .withString("Title", title) .withString("Description", description) .withString("CreateDate", createDate) .withString("LastUpdateDate", lastUpdateDate) .withString("DueDate", dueDate) .withNumber("Priority", priority) .withString("Status", status); table.putItem(item); } } グローバルセカンダリインデックスes: .NET の使用 トピック • グローバルセカンダリインデックス を使用したテーブルの作成 (p. 364) • グローバルセカンダリインデックス のあるテーブルの説明 (p. 366) • グローバルセカンダリインデックス のクエリ (p. 367) • 例: AWS SDK for .NET 低レベル API を使用した グローバルセカンダリインデックス (p. 368) AWS SDK for .NET 低レベル API を使用して、1 つ以上の グローバルセカンダリインデックス を持つ テーブルを作成し、テーブルのインデックスについて説明し、インデックスを使用してクエリを実行 することができます。これらのオペレーションは、対応する DynamoDB オペレーションにマッピン グされます。詳細については、『Amazon DynamoDB API Reference』を参照してください。 次に、.NET 低レベル API を使用したテーブルオペレーションの一般的なステップを示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. 対応するリクエストオブジェクトを作成して、オペレーションについて必要なパラメータとオプ ションパラメータを入力します。 たとえば、CreateTableRequest オブジェクトを作成してテーブルと QueryRequest オブジェク トを作成し、テーブルまたはインデックスのクエリを行います。 3. 前述のステップで作成したクライアントから提供された適切なメソッドを実行します。 グローバルセカンダリインデックス を使用したテーブルの作成 グローバルセカンダリインデックス は、テーブルの作成と同時に作成できます。そのために は、CreateTable を使用して、1 つ以上の グローバルセカンダリインデックス の仕様を指定しま API Version 2012-08-10 364 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス す。次の C# コードスニペットでは、気象データに関する情報を格納するテーブルを作成します。 パーティションキーは Location で、ソートキーは Date です。PrecipIndex という名前の グローバル セカンダリインデックス は、さまざまな場所の降水量データに高速アクセスできます。 次に、.NET 低レベル API を使用して、グローバルセカンダリインデックス があるテーブルを作成す るステップを示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. リクエスト情報を指定する CreateTableRequest クラスのインスタンスを作成します。 テーブル名、プライマリキー、プロビジョニング済みスループットの値を指定する必要がありま す。グローバルセカンダリインデックスについては、インデックス名、そのプロビジョニングされ たスループット設定、インデックスソートキーの属性定義、インデックスのキースキーマ、属性射 影を指定する必要があります。 3. リクエストオブジェクトをパラメータとして指定して、CreateTable メソッドを実行します。 次の C# コードスニペットは、前述のステップを示しています。このスニペットでは、グローバルセ カンダリインデックス(PrecipIndex)を持つテーブル(WeatherData)を作成します。インデックス パーティションキーは Date で、そのソートキーは Precipitation です。すべてのテーブル属性がイン デックスに射影されます。ユーザーは、このインデックスに対してクエリを実行して、特定の日付の 気象データを取得でき、必要に応じて、降水量別にデータを並べ替えることができます。 Precipitation はテーブルのキー属性ではないので、必須ではありません。ただし、Precipitation のない WeatherData 項目は PrecipIndex に現れません。 client = new AmazonDynamoDBClient(); string tableName = "WeatherData"; // Attribute definitions var attributeDefinitions = new List<AttributeDefinition>() { {new AttributeDefinition{ AttributeName = "Location", AttributeType = "S"}}, {new AttributeDefinition{ AttributeName = "Date", AttributeType = "S"}}, {new AttributeDefinition(){ AttributeName = "Precipitation", AttributeType = "N"} } }; // Table key schema var tableKeySchema = new List<KeySchemaElement>() { {new KeySchemaElement { AttributeName = "Location", KeyType = "HASH"}}, //Partition key {new KeySchemaElement { AttributeName = "Date", KeyType = "RANGE"} //Sort key } }; // PrecipIndex var precipIndex = new GlobalSecondaryIndex { API Version 2012-08-10 365 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス IndexName = "PrecipIndex", ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = (long)10, WriteCapacityUnits = (long)1 }, Projection = new Projection { ProjectionType = "ALL" } }; var indexKeySchema = new List<KeySchemaElement> { {new KeySchemaElement { AttributeName = "Date", KeyType = "HASH"}}, // Partition key {new KeySchemaElement{AttributeName = "Precipitation",KeyType = "RANGE"}} //Sort key }; precipIndex.KeySchema = indexKeySchema; CreateTableRequest createTableRequest = new CreateTableRequest { TableName = tableName, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = (long)5, WriteCapacityUnits = (long)1 }, AttributeDefinitions = attributeDefinitions, KeySchema = tableKeySchema, GlobalSecondaryIndexes = { precipIndex } }; CreateTableResponse response = client.CreateTable(createTableRequest); Console.WriteLine(response.CreateTableResult.TableDescription.TableName); Console.WriteLine(response.CreateTableResult.TableDescription.TableStatus); DynamoDB がテーブルを作成し、テーブルのステータスを ACTIVE に設定するまで待機する必要があ ります。その後は、データ項目をテーブルに書き込むことが可能になります。 グローバルセカンダリインデックス のあるテーブルの説明 テーブルの グローバルセカンダリインデックス に関する情報を取得するには、DescribeTable を使 用します。各インデックスについて、名前、キースキーマ、射影された属性にアクセスできます。 次に、.NET 低レベル API を使用して、テーブルの グローバルセカンダリインデックス 情報にアクセ スするステップを示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. リクエスト情報を指定する DescribeTableRequest クラスのインスタンスを作成します。テーブ ル名を入力する必要があります。 3. リクエストオブジェクトをパラメータとして指定して、describeTable メソッドを実行します。 次の C# コードスニペットは、前述のステップを示しています。 client = new AmazonDynamoDBClient(); string tableName = "WeatherData"; DescribeTableResponse response = client.DescribeTable(new DescribeTableRequest { TableName = tableName}); API Version 2012-08-10 366 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス List<GlobalSecondaryIndexDescription> globalSecondaryIndexes = response.DescribeTableResult.Table.GlobalSecondaryIndexes; // This code snippet will work for multiple indexes, even though // there is only one index in this example. foreach (GlobalSecondaryIndexDescription gsiDescription in globalSecondaryIndexes) { Console.WriteLine("Info for index " + gsiDescription.IndexName + ":"); foreach (KeySchemaElement kse in gsiDescription.KeySchema) { Console.WriteLine("\t" + kse.AttributeName + ": key type is " + kse.KeyType); } Projection projection = gsiDescription.Projection; Console.WriteLine("\tThe projection type is: " + projection.ProjectionType); if (projection.ProjectionType.ToString().Equals("INCLUDE")) { Console.WriteLine("\t\tThe non-key projected attributes are: " + projection.NonKeyAttributes); } } グローバルセカンダリインデックス のクエリ グローバルセカンダリインデックス では、テーブルの Query を実行するのと同様の方法で、Query を使用できます。インデックス名、インデックスパーティションキーとソートキー (存在する場合) の クエリ基準、および返されるようにする属性を指定する必要があります。この例では、インデックス は PrecipIndex で、そのパーティションキーは Date で、ソートキーは Precipitation です。インデック スクエリは、特定の日付を対象に、降水量がゼロよりも大きい気象データをすべて返します。 次に、.NET 低レベル API を使用して グローバルセカンダリインデックス のクエリを行うステップを 示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. リクエスト情報を指定する QueryRequest クラスのインスタンスを作成します。 3. リクエストオブジェクトをパラメータとして指定して、query メソッドを実行します。 属性名 Date は、DynamoDB の予約語です。したがって、式の属性名を KeyConditionExpression のプレースホルダーとして使用する必要があります。 次の C# コードスニペットは、前述のステップを示しています。 client = new AmazonDynamoDBClient(); QueryRequest queryRequest = new QueryRequest { TableName = "WeatherData", IndexName = "PrecipIndex", KeyConditionExpression = "#dt = :v_date and Precipitation > :v_precip", ExpressionAttributeNames = new Dictionary<String, String> { {"#dt", "Date"} }, ExpressionAttributeValues = new Dictionary<string, AttributeValue> { API Version 2012-08-10 367 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス {":v_date", new AttributeValue { S = "2013-08-01" }}, {":v_precip", new AttributeValue { N = "0" }} }, ScanIndexForward = true }; var result = client.Query(queryRequest); var items = result.Items; foreach (var currentItem in items) { foreach (string attr in currentItem.Keys) { Console.Write(attr + "---> "); if (attr == "Precipitation") { Console.WriteLine(currentItem[attr].N); } else { Console.WriteLine(currentItem[attr].S); } } Console.WriteLine(); } 例: AWS SDK for .NET 低レベル API を使用した グローバルセカンダリイン デックス 次の C# コード例では、グローバルセカンダリインデックス の操作方法を示します。この例で は、Issues という名前のテーブルを作成します。このテーブルは、ソフトウェア開発の単純なバグ追 跡システムで使用される可能性があります。パーティションキーは IssueId で、ソートキーは Title で す。このテーブルには 3 つの グローバルセカンダリインデックス があります。 • CreateDateIndex – パーティションキーは CreateDate で、ソートキーは IssueId です。テーブル キーに加えて、属性 Description と Status がインデックスに射影されます。 • TitleIndex – パーティションキーは IssueId で、ソートキーは Title です。テーブルキー以外の属性 は、インデックスに射影されません。 • DueDateIndex – パーティションキーは DueDate で、ソートキーはありません。すべてのテーブル 属性がインデックスに射影されます。 Issues テーブルを作成した後、プログラムによって、ソフトウェアバグレポートを表すデータがテー ブルにロードされ、グローバルセカンダリインデックス を使用してそのデータに対してクエリが実行 されます。最後に、プログラムによって Issues テーブルが削除されます。 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照し てください。 using using using using using using using using System; System.Collections.Generic; System.Linq; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DataModel; Amazon.DynamoDBv2.DocumentModel; Amazon.DynamoDBv2.Model; Amazon.Runtime; API Version 2012-08-10 368 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス using Amazon.SecurityToken; namespace com.amazonaws.codesamples { class LowLevelGlobalSecondaryIndexExample { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); public static String tableName = "Issues"; public static void Main(string[] args) { CreateTable(); LoadData(); QueryIndex("CreateDateIndex"); QueryIndex("TitleIndex"); QueryIndex("DueDateIndex"); DeleteTable(tableName); Console.WriteLine("To continue, press enter"); Console.Read(); } private static void CreateTable() { // Attribute definitions var attributeDefinitions = new List<AttributeDefinition>() { {new AttributeDefinition {AttributeName = "IssueId", AttributeType = "S"}}, {new AttributeDefinition {AttributeName = "Title", AttributeType = "S"}}, {new AttributeDefinition {AttributeName = "CreateDate", AttributeType = "S"}}, {new AttributeDefinition {AttributeName = "DueDate", AttributeType = "S"}} }; // Key schema for table var tableKeySchema = new List<KeySchemaElement>() { { new KeySchemaElement { AttributeName= "IssueId", KeyType = "HASH" //Partition key } }, { new KeySchemaElement { AttributeName = "Title", KeyType = "RANGE" //Sort key } } }; API Version 2012-08-10 369 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス // Initial provisioned throughput settings for the indexes var ptIndex = new ProvisionedThroughput { ReadCapacityUnits = 1L, WriteCapacityUnits = 1L }; // CreateDateIndex var createDateIndex = new GlobalSecondaryIndex() { IndexName = "CreateDateIndex", ProvisionedThroughput = ptIndex, KeySchema = { new KeySchemaElement { AttributeName = "CreateDate", KeyType = "HASH" // Partition key }, new KeySchemaElement { AttributeName = "IssueId", KeyType = "RANGE" //Sort key } }, Projection = new Projection { ProjectionType = "INCLUDE", NonKeyAttributes = { "Description", "Status" } } }; // TitleIndex var titleIndex = new GlobalSecondaryIndex() { IndexName = "TitleIndex", ProvisionedThroughput = ptIndex, KeySchema = { new KeySchemaElement { AttributeName = "Title", KeyType = "HASH" // Partition key }, new KeySchemaElement { AttributeName = "IssueId", KeyType = "RANGE" //Sort key } }, Projection = new Projection { ProjectionType = "KEYS_ONLY" } }; // DueDateIndex var dueDateIndex = new GlobalSecondaryIndex() { IndexName = "DueDateIndex", ProvisionedThroughput = ptIndex, KeySchema = { new KeySchemaElement { AttributeName = "DueDate", KeyType = "HASH" //Partition key API Version 2012-08-10 370 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス } }, Projection = new Projection { ProjectionType = "ALL" } }; var createTableRequest = new CreateTableRequest { TableName = tableName, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = (long)1, WriteCapacityUnits = (long)1 }, AttributeDefinitions = attributeDefinitions, KeySchema = tableKeySchema, GlobalSecondaryIndexes = { createDateIndex, titleIndex, dueDateIndex } }; Console.WriteLine("Creating table " + tableName + "..."); client.CreateTable(createTableRequest); WaitUntilTableReady(tableName); } private static void LoadData() { Console.WriteLine("Loading data into table " + tableName + "..."); // // // // IssueId, Title, Description, CreateDate, LastUpdateDate, DueDate, Priority, Status putItem("A-101", "Compilation error", "Can't compile Project X - bad version number. What does this mean?", "2013-11-01", "2013-11-02", "2013-11-10", 1, "Assigned"); putItem("A-102", "Can't read data file", "The main data file is missing, or the permissions are incorrect", "2013-11-01", "2013-11-04", "2013-11-30", 2, "In progress"); putItem("A-103", "Test failure", "Functional test of Project X produces errors", "2013-11-01", "2013-11-02", "2013-11-10", 1, "In progress"); API Version 2012-08-10 371 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス putItem("A-104", "Compilation error", "Variable 'messageCount' was not initialized.", "2013-11-15", "2013-11-16", "2013-11-30", 3, "Assigned"); putItem("A-105", "Network issue", "Can't ping IP address 127.0.0.1. Please fix this.", "2013-11-15", "2013-11-16", "2013-11-19", 5, "Assigned"); } private static void putItem( String issueId, String title, String description, String createDate, String lastUpdateDate, String dueDate, Int32 priority, String status) { Dictionary<String, AttributeValue> item = new Dictionary<string, AttributeValue>(); item.Add("IssueId", new AttributeValue { S = issueId }); item.Add("Title", new AttributeValue { S = title }); item.Add("Description", new AttributeValue { S = description }); item.Add("CreateDate", new AttributeValue { S = createDate }); item.Add("LastUpdateDate", new AttributeValue { S = lastUpdateDate }); item.Add("DueDate", new AttributeValue { S = dueDate }); item.Add("Priority", new AttributeValue { N = priority.ToString() }); item.Add("Status", new AttributeValue { S = status }); try { client.PutItem(new PutItemRequest { TableName = tableName, Item = item }); } catch (Exception e) { Console.WriteLine(e.ToString()); } } private static void QueryIndex(string indexName) { Console.WriteLine ("\n***********************************************************\n"); Console.WriteLine("Querying index " + indexName + "..."); QueryRequest queryRequest = new QueryRequest { TableName = tableName, IndexName = indexName, API Version 2012-08-10 372 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス ScanIndexForward = true }; String keyConditionExpression; Dictionary<string, AttributeValue> expressionAttributeValues = new Dictionary<string, AttributeValue>(); if (indexName == "CreateDateIndex") { Console.WriteLine("Issues filed on 2013-11-01\n"); keyConditionExpression = "CreateDate = :v_date and begins_with(IssueId, :v_issue)"; expressionAttributeValues.Add(":v_date", new AttributeValue { S = "2013-11-01" }); expressionAttributeValues.Add(":v_issue", new AttributeValue { S = "A-" }); } else if (indexName == "TitleIndex") { Console.WriteLine("Compilation errors\n"); keyConditionExpression = "Title = :v_title and begins_with(IssueId, :v_issue)"; expressionAttributeValues.Add(":v_title", new AttributeValue { S = "Compilation error" }); expressionAttributeValues.Add(":v_issue", new AttributeValue { S = "A-" }); // Select queryRequest.Select = "ALL_PROJECTED_ATTRIBUTES"; } else if (indexName == "DueDateIndex") { Console.WriteLine("Items that are due on 2013-11-30\n"); keyConditionExpression = "DueDate = :v_date"; expressionAttributeValues.Add(":v_date", new AttributeValue { S = "2013-11-30" }); // Select queryRequest.Select = "ALL_PROJECTED_ATTRIBUTES"; } else { Console.WriteLine("\nNo valid index name provided"); return; } queryRequest.KeyConditionExpression = keyConditionExpression; queryRequest.ExpressionAttributeValues = expressionAttributeValues; var result = client.Query(queryRequest); var items = result.Items; API Version 2012-08-10 373 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス foreach (var currentItem in items) { foreach (string attr in currentItem.Keys) { if (attr == "Priority") { Console.WriteLine(attr + "---> " + currentItem[attr].N); } else { Console.WriteLine(attr + "---> " + currentItem[attr].S); } } Console.WriteLine(); } } private static void DeleteTable(string tableName) { Console.WriteLine("Deleting table " + tableName + "..."); client.DeleteTable(new DeleteTableRequest { TableName = tableName }); WaitForTableToBeDeleted(tableName); } private static void WaitUntilTableReady(string tableName) { string status = null; // Let us wait until table is created. Call DescribeTable. do { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); status = res.Table.TableStatus; } catch (ResourceNotFoundException) { // DescribeTable is eventually consistent. So you might // get resource not found. So we handle the potential exception. } } while (status != "ACTIVE"); } private static void WaitForTableToBeDeleted(string tableName) API Version 2012-08-10 374 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス { bool tablePresent = true; while (tablePresent) { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); } catch (ResourceNotFoundException) { tablePresent = false; } } } } } グローバルセカンダリインデックス の操作 : PHP トピック • グローバルセカンダリインデックス を使用したテーブルの作成 (p. 375) • グローバルセカンダリインデックス のあるテーブルの説明 (p. 377) • グローバルセカンダリインデックス のクエリ (p. 377) • 例: AWS SDK for PHP 低レベル API を使用した グローバルセカンダリインデックス (p. 378) AWS SDK for PHP 低レベル API を使用して、1 つ以上の グローバルセカンダリインデックス を持つ テーブルを作成し、テーブルのインデックスについて説明し、インデックスを使用してクエリを実行 することができます。これらのオペレーションは、対応する DynamoDB アクションにマッピングさ れます。 詳細については、「PHP コードサンプル (p. 175)」を参照してください。 以下に、AWS SDK for PHP を使用したテーブルオペレーションの一般的な手順を示します。 1. DynamoDB クライアントのインスタンスを作成します。 2. オプションのパラメーターを含む DynamoDB オペレーションのパラメーターを指定します。 3. DynamoDB からの応答をアプリケーションのローカル変数にロードします。 グローバルセカンダリインデックス を使用したテーブルの作成 グローバルセカンダリインデックス は、テーブルの作成と同時に作成できます。そのために は、CreateTable を使用して、1 つ以上の グローバルセカンダリインデックス の仕様を指定しま す。次の PHP コードスニペットでは、気象データに関する情報を格納するテーブルを作成します。 パーティションキーは Location で、ソートキーは Date です。PrecipIndex という名前の グローバル セカンダリインデックス は、さまざまな場所の降水量データに高速アクセスできます。 API Version 2012-08-10 375 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス 次のコードスニペットでは、グローバルセカンダリインデックス (PrecipIndex) を持つテーブル (WeatherData) を作成します。インデックスパーティションキーは Date で、そのソートキーは Precipitation です。すべてのテーブル属性がインデックスに射影されます。ユーザーは、このイン デックスに対してクエリを実行して、特定の日付の気象データを取得でき、必要に応じて、降水量別 にデータを並べ替えることができます。 Precipitation はテーブルのキー属性ではないので、必須ではありません。ただし、Precipitation のない WeatherData 項目は PrecipIndex に現れません。 require 'vendor/autoload.php'; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'WeatherData'; $result = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'Location', 'AttributeType' => 'S' ], [ 'AttributeName' => 'Date', 'AttributeType' => 'S' ], [ 'AttributeName' => 'Precipitation', 'AttributeType' => 'N' ] ], 'KeySchema' => [ [ 'AttributeName' => 'Location', 'KeyType' => 'HASH' ], //Partition key [ 'AttributeName' => 'Date', 'KeyType' => 'RANGE' ] //Sort key ], 'GlobalSecondaryIndexes' => [ [ 'IndexName' => 'PrecipIndex', 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 5, 'WriteCapacityUnits' => 5 ], 'KeySchema' => [ [ 'AttributeName' => 'Date', 'KeyType' => 'HASH' ], // Partition key [ 'AttributeName' => 'Precipitation', 'KeyType' => 'RANGE' ] //Sort key ], 'Projection' => [ 'ProjectionType' => 'ALL' ] ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 5, 'WriteCapacityUnits' => 5 ] ]); DynamoDB がテーブルを作成し、テーブルのステータスを ACTIVE に設定するまで待機する必要があ ります。その後は、データ項目をテーブルに書き込むことが可能になります。 API Version 2012-08-10 376 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス グローバルセカンダリインデックス のあるテーブルの説明 テーブルの グローバルセカンダリインデックス に関する情報を取得するには、DescribeTable を使 用します。各インデックスについて、名前、キースキーマ、射影された属性にアクセスできます。 $tableName = 'WeatherData'; $result = $dynamodb->describeTable([ 'TableName' => $tableName ]); foreach ($result['Table']['GlobalSecondaryIndexes'] as $key => $value) { echo "Info for index " . $value['IndexName'] . ":\n"; foreach ($value['KeySchema'] as $attribute => $keyschema) { echo "\t" . $value['KeySchema'][$attribute]['AttributeName'] . ': ' . $value['KeySchema'][$attribute]['KeyType'] . "\n"; } echo "\tThe projection type is: " . $value['Projection'] ['ProjectionType'] . "\n"; } グローバルセカンダリインデックス のクエリ グローバルセカンダリインデックス では、テーブルの Query を実行するのと同様の方法で、Query を使用できます。インデックス名、インデックスパーティションキーとソートキー (存在する場合) の クエリ基準、および返されるようにする属性を指定する必要があります。この例では、インデックス は PrecipIndex で、そのパーティションキーは Date で、ソートキーは Precipitation です。インデック スクエリは、特定の日付を対象に、降水量がゼロよりも大きい気象データをすべて返します。 属性名 Date は、DynamoDB の予約語です。したがって、式の属性名を KeyConditionExpression のプレースホルダーとして使用する必要があります。 $tableName = 'WeatherData'; $response = $dynamodb->query([ 'TableName' => $tableName, 'IndexName' => 'PrecipIndex', 'KeyConditionExpression' => '#dt = :v_dt and Precipitation > :v_precip', 'ExpressionAttributeNames' => ['#dt' => 'Date'], 'ExpressionAttributeValues' => [ ':v_dt' => ['S' => '2014-08-01'], ':v_precip' => ['N' => '0'] ], 'Select' => 'ALL_ATTRIBUTES', 'ScanIndexForward' => true, ]); foreach ($response['Items'] as $item) { echo "Date ---> " . $item['Date']['S'] . "\n"; echo "Location ---> " . $item['Location']['S'] . "\n"; echo "Precipitation ---> " . $item['Precipitation']['N'] . "\n"; echo "\n"; } API Version 2012-08-10 377 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス 例: AWS SDK for PHP 低レベル API を使用した グローバルセカンダリイン デックス 次の PHP コード例では、グローバルセカンダリインデックス の操作方法を示します。この例で は、Issues という名前のテーブルを作成します。このテーブルは、ソフトウェア開発の単純なバグ追 跡システムで使用される可能性があります。パーティションキーは IssueId で、ソートキーは Title で す。このテーブルには 3 つの グローバルセカンダリインデックス があります。 • CreateDateIndex – パーティションキーは CreateDate で、ソートキーは IssueId です。テーブル キーに加えて、属性 Description と Status がインデックスに射影されます。 • TitleIndex – パーティションキーは IssueId で、ソートキーは Title です。テーブルキー以外の属性 は、インデックスに射影されません。 • DueDateIndex – パーティションキーは DueDate で、ソートキーはありません。すべてのテーブル 属性がインデックスに射影されます。 Issues テーブルを作成した後、プログラムによって、ソフトウェアバグレポートを表すデータがテー ブルにロードされ、グローバルセカンダリインデックス を使用してそのデータに対してクエリが実行 されます。最後に、プログラムによって Issues テーブルが削除されます。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'Issues'; echo "# Creating table $tableName...\n"; try { $response = $dynamodb->createTable ( [ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'IssueId', 'AttributeType' => 'S' ], [ 'AttributeName' => 'Title', 'AttributeType' => 'S' ], [ 'AttributeName' => 'CreateDate', 'AttributeType' => 'S' ], [ 'AttributeName' => 'DueDate', 'AttributeType' => 'S' ] ], 'KeySchema' => [ [ 'AttributeName' => 'IssueId', 'KeyType' => 'HASH' ], // Partition key [ 'AttributeName' => 'Title', 'KeyType' => 'RANGE' ] //Sort key ], 'GlobalSecondaryIndexes' => [ [ 'IndexName' => 'CreateDateIndex', 'KeySchema' => [ [ 'AttributeName' => 'CreateDate', 'KeyType' => 'HASH' ], //Partition key API Version 2012-08-10 378 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス [ 'AttributeName' => 'IssueId', 'KeyType' => 'RANGE' ] //Sort key ], 'Projection' => [ 'ProjectionType' => 'INCLUDE', 'NonKeyAttributes' => [ 'Description', 'Status' ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 1, 'WriteCapacityUnits' => 1 ] ], [ 'IndexName' => 'TitleIndex', 'KeySchema' => [ [ 'AttributeName' => 'Title', 'KeyType' => 'HASH' ], // Partition key [ 'AttributeName' => 'IssueId', 'KeyType' => 'RANGE' ] //Sort key ], 'Projection' => [ 'ProjectionType' => 'KEYS_ONLY' ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 1, 'WriteCapacityUnits' => 1 ] ], [ 'IndexName' => 'DueDateIndex', 'KeySchema' => [ [ 'AttributeName' => 'DueDate', 'KeyType' => 'HASH' ] Partition key ], 'Projection' => [ 'ProjectionType' => 'ALL' ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 1, 'WriteCapacityUnits' => 1 ] ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 1, 'WriteCapacityUnits' => 1 ] ]); echo " Waiting for table $tableName to be created.\n"; $dynamodb->waitUntil('TableExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] ]); echo " Table $tableName has been created.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to create table $tableName\n"); } // ######################################## // Add items to the table API Version 2012-08-10 379 // Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス echo "# Loading data into $tableName...\n"; $response = $dynamodb->putItem ([ 'TableName' => $tableName, 'Item' => [ 'IssueId' => [ 'S' => 'A-101' ], 'Title' => [ 'S' => 'Compilation error' ], 'Description' => [ 'S' => 'Can\'t compile Project X - bad version number. What does this mean?' ], 'CreateDate' => [ 'S' => '2014-11-01' ], 'LastUpdateDate' => [ 'S' => '2014-11-02' ], 'DueDate' => [ 'S' => '2014-11-10' ], 'Priority' => [ 'N' => '1' ], 'Status' => [ 'S' => 'Assigned' ] ] ]); $response = $dynamodb->putItem ([ 'TableName' => $tableName, 'Item' => [ 'IssueId' => [ 'S' => 'A-102' ], 'Title' => [ 'S' => 'Can\'t read data file' ], 'Description' => [ 'S' => 'The main data file is missing, or the permissions are incorrect' ], 'CreateDate' => [ 'S' => '2014-11-01' ], 'LastUpdateDate' => [ 'S' => '2014-11-04' ], 'DueDate' => [ 'S' => '2014-11-30' ], 'Priority' => [ 'N' => '2' ], 'Status' => [ 'S' => 'In progress' ] ] ]); $response = $dynamodb->putItem ([ 'TableName' => $tableName, 'Item' => [ 'IssueId' => [ 'S' => 'A-103' ], 'Title' => [ 'S' => 'Test failure' ], 'Description' => [ 'S' => 'Functional test of Project X produces errors.' ], 'CreateDate' => [ 'S' => '2014-11-01' ], 'LastUpdateDate' => [ 'S' => '2014-11-02' ], 'DueDate' => [ 'S' => '2014-11-10' ], 'Priority' => [ 'N' => '1' ], 'Status' => [ 'S' => 'In progress' ] ] ]); $response = $dynamodb->putItem ([ 'TableName' => $tableName, 'Item' => [ 'IssueId' => [ 'S' => 'A-104' ], 'Title' => [ 'S' => 'Compilation error' ], 'Description' => [ 'S' => 'Variable "messageCount" was not initialized.' ], 'CreateDate' => [ 'S' => '2014-11-15' ], 'LastUpdateDate' => [ 'S' => '2014-11-16' ], 'DueDate' => [ 'S' => '2014-11-30' ], API Version 2012-08-10 380 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス 'Priority' => [ 'N' => '3' ], 'Status' => [ 'S' => 'Assigned' ] ] ]); $response = $dynamodb->putItem ([ 'TableName' => $tableName, 'Item' => [ 'IssueId' => [ 'S' => 'A-105' ], 'Title' => [ 'S' => 'Network issue' ], 'Description' => [ 'S' => 'Can\'t ping IP address 127.0.0.1. Please fix this.' ], 'CreateDate' => [ 'S' => '2014-11-15' ], 'LastUpdateDate' => [ 'S' => '2014-11-16' ], 'DueDate' => [ 'S' => '2014-11-19' ], 'Priority' => [ 'N' => '5' ], 'Status' => [ 'S' => 'Assigned' ] ] ]); // ######################################## // Query for issues filed on 2014-11-01 $response = $dynamodb->query ( [ 'TableName' => $tableName, 'IndexName' => 'CreateDateIndex', 'KeyConditionExpression' => 'CreateDate = :v_dt and begins_with(IssueId, :v_issue)', 'ExpressionAttributeValues' => [ ':v_dt' => ['S' => '2014-11-01'], ':v_issue' => ['S' => 'A-'] ] ]); echo '# Query for issues filed on 2014-11-01:' . "\n"; foreach ( $response ['Items'] as $item ) { echo ' - ' . $item ['CreateDate'] ['S'] . ' ' . $item ['IssueId'] ['S'] . ' ' . $item ['Description'] ['S'] . ' ' . $item ['Status'] ['S'] . "\n"; } echo "\n"; // ######################################## // Query for issues that are 'Compilation errors' $response = $dynamodb->query ( [ 'TableName' => $tableName, 'IndexName' => 'TitleIndex', 'KeyConditionExpression' => 'Title = :v_title and IssueId >= :v_issue', 'ExpressionAttributeValues' => [ ':v_title' => ['S' => 'Compilation error'], ':v_issue' => ['S' => 'A-'] ] ]); API Version 2012-08-10 381 Amazon DynamoDB 開発者ガイド グローバルセカンダリインデックス echo '# Query for issues that are compilation errors: ' . "\n"; foreach ( $response ['Items'] as $item ) { echo ' - ' . $item ['Title'] ['S'] . ' ' . $item ['IssueId'] ['S'] . "\n"; } echo "\n"; // ######################################## // Query for items that are due on 2014-11-30 $response = $dynamodb->query ( [ 'TableName' => $tableName, 'IndexName' => 'DueDateIndex', 'KeyConditionExpression' => 'DueDate = :v_dt', 'ExpressionAttributeValues' => [ ':v_dt' => ['S' => '2014-11-30'] ] ]); echo "# Querying for items that are due on 2014-11-30:\n"; foreach ( $response ['Items'] as $item ) { echo ' - ' . $item ['DueDate'] ['S'] . ' ' . $item ['IssueId'] ['S'] . ' ' . $item ['Title'] ['S'] . ' ' . $item ['Description'] ['S'] . ' ' . $item ['CreateDate'] ['S'] . ' ' . $item ['LastUpdateDate'] ['S'] . ' ' . $item ['Priority'] ['N'] . ' ' . $item ['Status'] ['S'] . "\n"; } echo "\n"; // ######################################## // Delete the table try { echo "# Deleting table $tableName...\n"; $dynamodb->deleteTable(['TableName' => $tableName]); echo " Waiting for table $tableName to be deleted.\n"; $dynamodb->waitUntil('TableNotExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] ]); echo " Table $tableName has been deleted.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to delete table $tableName\n"); } API Version 2012-08-10 382 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス ?> ローカルセカンダリインデックス トピック • 属性の射影 (p. 385) • ローカルセカンダリインデックス の作成 (p. 387) • ローカルセカンダリインデックス のクエリ (p. 387) • ローカルセカンダリインデックスの実行 (p. 388) • 項目の書き込みと ローカルセカンダリインデックス (p. 389) • プロビジョニングされたスループットに関する考慮事項(ローカルセカンダリインデック ス) (p. 389) • ローカルセカンダリインデックス のストレージに関する考慮事項 (p. 391) • 項目コレクション (p. 391) • ローカルセカンダリインデックス の使用 : Java (p. 394) • ローカルセカンダリインデックスes: .NET の使用 (p. 405) • ローカルセカンダリインデックス の操作 : PHP (p. 418) ベーステーブルのプライマリキーを使用してデータのクエリを実行する必要があるのは、一部のアプ リケーションだけですが、代替のソートキーが役に立つ場合があります。アプリケーションにソート キーという選択肢を提供するために、テーブルに 1 つ以上のlocal secondary indexを作成して、それ らのインデックスに対して Query または Scan リクエストを実行できます。 たとえば、テーブルの作成とサンプルデータのロード (p. 166) で定義した Thread テーブルがありま す。このテーブルは、AWS フォーラムのようなアプリケーションで役立ちます。次の図は、テーブル 内の項目の構成を示しています。一部表示されていない属性もあります。 DynamoDB には、同じパーティションキー値を持つすべての項目が隣接して保存されます。この 例では、特定の ForumName を指定すると、Query オペレーションはそのフォーラムのすべての スレッドをすばやく見つけることができます。同じパーティションキー値を持つ項目のグループで は、項目がソートキーの値によって並べ替えられます。クエリにソートキー (Subject) も指定した場 API Version 2012-08-10 383 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 合、DynamoDB では、返された結果をすばやく絞り込むことができます。たとえば、"S3" フォーラム の中から、Subject の先頭が文字 "a" であるすべてのスレッドを返すことができます。 リクエストによっては、より複雑なデータアクセスパターンが要求される場合があります。以下に例 を示します。 • ビューと返信の数が最も多いのはどのフォーラムか? • 特定のフォーラムでメッセージ数が最も多いのはどのスレッドか? • 特定の期間中に特定のフォーラムに投稿されたスレッド数は? これらの質問に答えるには、Query アクションでは十分ではありません。代わりに、テーブル全体の Scan を実行する必要があります。膨大な数の項目があるテーブルでは、これにより、プロビジョニン グされた読み込みスループットが大量に消費されることになり、完了するまでに長時間かかります。 ただし、Replies や LastPostDateTime などの非キー属性に 1 つ以上のlocal secondary indexを指定す ることができます。 local secondary index は特定のパーティションキー値の代替ソートキーを維持します。またlocal secondary indexでは、そのベーステーブルの一部またはすべての属性のコピーが保持されます。テー ブルを作成する際に、local secondary indexに射影する属性を指定します。local secondary indexの データは、ベーステーブルと同じパーティションキーと、異なるソートキーで構成されます。これに より、この異なるディメンションにわたってデータ項目に効率的にアクセスできます。クエリまたは スキャンの柔軟性を向上するために、テーブルごとに最大 5 つのlocal secondary indexを作成できま す。 たとえば、あるアプリケーションで過去 3 か月以内に投稿されたすべてのスレッドを検索する必要 があるとします。local secondary index がない場合は、アプリケーションでは Thread テーブル全体 の Scan を実行して、指定された時間枠から外れた投稿を破棄する必要があります。local secondary indexがあれば、Query オペレーションでは LastPostDateTime をソートキーとして使用して、データ をすばやく特定することができます。 次の図は、LastPostIndex という名前の local secondary index を示しています。パーティションキー は Thread テーブルのパーティションキーと同じですが、ソートキーは LastPostDateTime です。 local secondary index は、すべて次の条件を満たす必要があります。 • パーティションキーはそのベーステーブルのパーティションキーと同じである。 API Version 2012-08-10 384 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス • ソートキーは完全に 1 つのスカラー属性で構成されている。 • ベーステーブルのソートキーがインデックスに射影され、非キー属性として機能する。 この例では、パーティションキーは ForumName で、local secondary indexのソートキーは LastPostDateTime です。さらに、ベーステーブルのソートキーの値 (この例では Subject) がイン デックスに射影されますが、その値はインデックスキーの一部ではありません。アプリケーション が ForumName と LastPostDateTime に基づくリストを必要とする場合は、LastPostIndex に対して Query リクエストを実行できます。クエリ結果は LastPostDateTime によって並べ替えられ、昇順ま たは降順で返すことができます。このクエリは、特定の時間枠内に LastPostDateTime がある項目だ けを返すなどのキー条件を適用することもできます。 すべてのlocal secondary indexには、そのベーステーブルからのパーティションキーとソートキーが 自動的に格納されます。必要に応じて、非キー属性をインデックスに射影できます。インデックスの クエリを行うと、DynamoDB ではこれらの射影された属性を効率的に取り出すことができます。local secondary index のクエリを行うと、クエリでは、インデックスに射影されていない属性も取り出すこ とができます。DynamoDB では、これらの属性をベーステーブルから自動的にフェッチしますが、レ イテンシーが大きくなり、プロビジョニングされたスループットコストが高くなります。 任意のlocal secondary indexについて、異なるパーティションキーの値ごとに最大 10 GB のデータを 保存できます。この数字には、ベーステーブル内のすべての項目に加えて、同じパーティションキー の値を持つインデックス内のすべての項目も含まれています。詳細については、「項目コレクショ ン (p. 391)」を参照してください。 属性の射影 LastPostIndex があるので、アプリケーションは、ForumName と LastPostDateTime をクエリ基準と して使用できますが、追加の属性を取り出すには、DynamoDB は、Thread テーブルに対して追加の 読み込みオペレーションを実行する必要があります。このような追加の読み込みをフェッチと言い、 それによってクエリにプロビジョニングするスループットの合計量が増加することがあります。 ウェブページに "S3" 内のすべてのスレッドと各スレッドの返信のリストを表示し、最新の返信の最後 の返信日時で並べ替えるとします。このリストに入力するには、次の属性が必要になります。 • 件名 • Replies • LastPostDateTime このデータのクエリを最も効率的に行い、フェッチオペレーションを回避するには、次の図に示すよ うに、local secondary indexにテーブルからの Replies 属性を射影します。 API Version 2012-08-10 385 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 射影は、テーブルからセカンダリインデックスにコピーされる属性セットです。テーブルのパーティ ションキーとソートキーは必ずインデックスに射影されます。アプリケーションのクエリ要件をサ ポートするために、他の属性を射影することができます。インデックスのクエリを行うと、Amazon DynamoDB は射影内の属性に、それらの属性が独立したテーブル内にあるかのようにアクセスできま す。 セカンダリインデックス を作成する場合は、インデックスに射影される属性を指定する必要がありま す。DynamoDB にはこのための 3 つのオプションが用意されています。 • KEYS_ONLY – インデックスの各項目は、テーブルのパーティションキーとソートキー値、および インデックスキー値のみで構成されます。KEYS_ONLY オプションを使用すると、セカンダリイン デックス は最小になります。 • INCLUDE – KEYS_ONLY の属性に加えて、セカンダリインデックス にその他の非キー属性が含まれ るように指定できます。 • ALL – セカンダリインデックス にソーステーブルのすべての属性が含まれます。テーブルの全デー タがインデックスで複製されるため、ALL の射影により、セカンダリインデックス は最大になりま す。 前の図では、非キー属性の Replies が LastPostIndex に射影されています。アプリケーション では Thread テーブル全体ではなく LastPostIndex に対するクエリを実行し、ウェブページに Subject、Replies、LastPostDateTime を表示することができます。他の非キー属性がリクエストされ た場合には、DynamoDB はそれらの属性を Thread テーブルからフェッチする必要があります。 アプリケーションの観点から見ると、ベーステーブルから追加の属性をフェッチする処理は、自動 的で透過的なので、アプリケーションロジックを書き直す必要はありません。ただし、このような フェッチによって、local secondary index を使用することで得られるパフォーマンスの利点が大幅に 小さくなる可能性があります。 local secondary index に射影する属性を選択する場合には、プロビジョニングされるスループットコ ストとストレージコストのトレードオフを考慮する必要があります。 • ごく一部の属性だけに最小のレイテンシーでアクセスする必要がある場合は、それらの属性だけ を local secondary index に射影することを検討してください。インデックスが小さいほど少ないコ ストで格納でき、書き込みコストも低くなります。まれにしかフェッチされない属性がある場合に は、それらの属性を格納するコストよりも、プロビジョニングされるスループットのコストのほう が長期的に大きくなる可能性があります。 API Version 2012-08-10 386 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス • アプリケーションが非キー属性に頻繁にアクセスする場合には、それらの属性を local secondary index に射影すると効果的です。local secondary index の追加のストレージコストは、頻繁なテーブ ルスキャンを実行するコストを相殺します。 • ほとんどの非キー属性に頻繁にアクセスする場合は、それらの属性、さらにはベーステーブル全体 をlocal secondary indexに射影することができます。それによってフェッチが不要になるため、柔軟 性が最大になり、プロビジョニングされるスループットが最小限になります。ただしストレージコ ストが増加し、すべての属性を射影する場合には 2 倍にまで増大します。 • アプリケーションでテーブルのクエリを頻繁に行う必要がなく、テーブル内のデータに対する 書き込みや更新が多数になる場合は、KEYS_ONLY を射影することを検討してください。local secondary index のサイズは最小になりますが、クエリに必要なサイズは確保されます。 ローカルセカンダリインデックス の作成 テーブルで 1 つ以上の local secondary index を作成するには、CreateTable オペレーションの LocalSecondaryIndexes パラメータを使用します。テーブルの ローカルセカンダリインデックス は、テーブルが作成された時点で作成されます。テーブルを削除すると、そのテーブルにある local secondary index も削除されます。 local secondary indexのソートキーにとなる 1 つの非キー属性を指定する必要があります。選択し た属性は、スカラー文字列、数値、またはバイナリである必要があります。他のスカラー型、ド キュメント型、およびセット型は使用できません。データ型の詳細なリストについては、「データ 型 (p. 12)」を参照してください。 Important local secondary indexがあるテーブルには、パーティションキーの値ごとに 10 GB のサイズ 制限があります。local secondary indexがあるテーブルには、1 つのパーティションキー値 の合計サイズが 10 GB を超えない限り、任意の数の項目を保存できます。詳細については、 「項目コレクションのサイズ制限 (p. 393)」を参照してください。 local secondary index には、任意のデータ型の属性を射影できます。これには、スカラー、ドキュメ ント、およびセットが含まれます。データ型の詳細なリストについては、「データ型 (p. 12)」を参照 してください。 ローカルセカンダリインデックス のクエリ DynamoDB テーブルでは、各項目のパーティションキーとソートキーを結合した値が一意である必要 があります。ただし、local secondary indexでは、ソートキーの値は、特定のパーティションキーの値 に対して一意である必要がありません。local secondary indexにソートキーの値が同じである複数の項 目がある場合、Query オペレーションは、同じパーティションキーの値を持つすべての項目を返しま す。レスポンスでは、一致する項目は特定の順序で返されません。 結果整合性のある読み込みまたは強力な整合性のある読み込みを使用して、local secondary index のクエリを行うことができます。必要な整合性のタイプを指定するには、Query オペレーションの ConsistentRead パラメータを使用します。local secondary index からの強力な整合性のある読み込み では、常に最新の更新された値が返されます。クエリがベーステーブルからさらに属性をフェッチす る必要がある場合、それらの属性はインデックスについて整合性があることになります。 API Version 2012-08-10 387 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス Example 特定のフォーラムのディスカッションスレッドにあるデータをリクエストする Query から返される次 のデータを考えてみます。 { "TableName": "Thread", "IndexName": "LastPostIndex", "ConsistentRead": false, "ProjectionExpression": "Subject, LastPostDateTime, Replies, Tags", "KeyConditionExpression": "ForumName = :v_forum and LastPostDateTime between :v_start and :v_end", "ExpressionAttributeValues": { ":v_start": {"S": "2015-08-31T00:00:00.000Z"}, ":v_end": {"S": "2015-11-31T00:00:00.000Z"}, ":v_forum": {"S": "EC2"} } } このクエリでは次のようになっています。 • DynamoDB が ForumName パーティションキーを使用して LastPostIndex にアクセスし、「EC2」 のインデックス項目を特定します。このキーを持つすべてのインデックス項目が、すばやく取り出 せるように隣り合わせに格納されます。 • このフォーラム内で、DynamoDB はインデックスを使用して、指定された LastPostDateTime 条件 に一致するキーを検索します。 • Replies 属性はインデックスに射影されているため、DynamoDB は追加でプロビジョニングされた スループットを消費することなく、この属性を取り出すことができます。 • Tags 属性はインデックスに射影されていないため、DynamoDB は Thread テーブルにアクセスして この属性をフェッチする必要があります。 • 結果が、LastPostDateTime によって並べ替えられ、返されます。インデックスのエントリはまず パーティションキーの値によって、次にソートキーの値によって並べ替えられ、保存される順序 で Query から返されます(ScanIndexForward パラメータを使用すると、結果が降順で返されま す)。 local secondary indexには Tags 属性が射影されていないため、DynamoDB は、読み込みキャパシ ティーユニットをさらに消費して、ベーステーブルからこの属性をフェッチする必要があります。こ のクエリを頻繁に実行する必要がある場合は、Tags 属性を LastPostIndex に射影して、ベーステーブ ルからフェッチされないようにする必要があります。ただし、Tags 属性をまれにしか使用しない場合 は、Tags 属性をインデックスに射影するためにストレージを追加することが有効でない可能性があり ます。 ローカルセカンダリインデックスの実行 Scan を使用して、local secondary index からすべてのデータを取得できます。 リクエストにはベー ステーブル名とインデックス名を指定する必要があります。Scan では、DynamoDB はインデック スのすべてのデータを読み取り、それをアプリケーションに返します。また、データの一部のみを返 し、残りのデータを破棄するようにリクエストすることもできます。これを行うには、Scan API の FilterExpression パラメータを使用します。詳細については、「クエリまたはスキャンからの結 果のフィルタリング (p. 289)」を参照してください。 API Version 2012-08-10 388 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 項目の書き込みと ローカルセカンダリインデックス DynamoDB によって、すべてのlocal secondary indexがそれぞれのベーステーブルと自動的に同期さ れます。アプリケーションがインデックスに直接書き込むことはありません。ただし、DynamoDB で これらのインデックスがどのように維持されるかを理解することは重要です。 local secondary indexを作成する場合は、インデックスのソートキーになる属性を指定します。その 属性のデータ型も指定します。つまり、ベーステーブルに項目を書き込むとき、その項目にインデッ クスキー属性が定義されている場合は、その型がインデックスキースキーマのデータ型に一致する 必要があります。LastPostIndex の場合、インデックス内の LastPostDateTime ソートキーは、文字 列データ型として定義されています。Thread テーブルに項目を追加するときに、LastPostDateTime に対して別のデータ型 (数値など) を指定すると、データ型の不一致により DynamoDB によって ValidationException が返されます。 テーブルに項目を書き込む場合には、local secondary indexソートキーに対して属性を指定する 必要はありません。LastPostIndex を例にとると、Thread テーブルに新しい項目を書き込むため に、LastPostDateTime 属性の値を指定する必要はありません。その場合、DynamoDB はこの特定の 項目のインデックスにデータを書き込むことはありません。 ベーステーブル内の項目とlocal secondary index内の項目を 1 対 1 の関係にする必要はありません。 この振る舞いは、多くのアプリケーションにとってメリットになります。詳細については、「スパー スなインデックスの利用 (p. 585)」を参照してください。 多数の local secondary index があるテーブルは、インデックス数が少ないテーブルに比べて書き込み アクティビティに多くのコストを要します。詳細については、「プロビジョニングされたスループッ トに関する考慮事項(ローカルセカンダリインデックス) (p. 389)」を参照してください。 Important local secondary indexがあるテーブルには、パーティションキーの値ごとに 10 GB のサイズ 制限があります。local secondary indexがあるテーブルには、1 つのパーティションキー値 の合計サイズが 10 GB を超えない限り、任意の数の項目を保存できます。詳細については、 「項目コレクションのサイズ制限 (p. 393)」を参照してください。 プロビジョニングされたスループットに関する考慮事項(ロー カルセカンダリインデックス) DynamoDB でテーブルを作成する場合には、テーブルで予想されるワークロードに応じた読み込みお よび書き込みキャパシティーユニットをプロビジョニングします。このワークロードには、テーブル の local secondary index の読み込みおよび書き込みアクティビティが含まれます。 プロビジョンドスループット性能の現在の料金を確認するには、https://aws.amazon.com/dynamodb/ pricing を参照してください。 読み込みキャパシティーユニット local secondary index に対してクエリを実行する場合には、消費される読み込みキャパシティーユ ニットの数は、データのアクセス方法によって異なります。 テーブルに対するクエリと同様に、インデックスクエリでは ConsistentRead の値に応じて、結果整 合性のある読み込みまたは強力な整合性のある読み込みを実行できます。1 回の強力な整合性のある 読み込みでは、1 つの読み込みキャパシティーユニットが消費され、結果整合性のある読み込みでは その半分が消費されます。したがって結果整合性のある読み込みを選択することで、読み込みキャパ シティーユニットのコストを削減できます。 インデックスキーと射影された属性だけをリクエストするインデックスクエリの場合、DynamoDB は テーブルに対するクエリの場合と同じ計算方法で、プロビジョニングされた読み込みアクティビティ API Version 2012-08-10 389 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス を計算します。唯一の違いは、ベーステーブル内の項目のサイズではなくインデックスエントリのサ イズに基づいて計算が行われることです。読み込みキャパシティーユニットの数は、返されたすべて の項目について射影されたすべての属性のサイズの合計です。結果は、次の 4 KB 境界まで切り上げ られます。DynamoDB がプロビジョニング済みスループットの利用率を計算する方法の詳細について は、「テーブルの読み書き要件の指定 (p. 179)」を参照してください。 local secondary indexに射影されていない属性を読み取るインデックスクエリの場合、DynamoDB は射影された属性をインデックスから読み取るのに加えて、それらの属性をベーステーブルから フェッチする必要があります。これらのフェッチは、Query オペレーションの Select または ProjectionExpression パラメータに、射影されていない属性を含めた場合に実行されます。 フェッチによってクエリ応答のレイテンシーが増加し、プロビジョニングされるスループットのコス トも増加します。前述のlocal secondary indexからの読み込みに加えて、フェッチされるベーステーブ ル項目それぞれについて、読み込みキャパシティーユニットの料金がかかります。この料金は、リク エストした属性だけでなく、項目全体をテーブルから読み取るために発生するものです。 Query オペレーションによって返される結果の最大サイズは、1 MB です。これには、返されるすべ ての項目にわたる、すべての属性の名前と値のサイズが含まれます。ただし、local secondary indexに 対するクエリによって、DynamoDB がテーブルから項目の属性をフェッチする場合には、結果で示さ れるデータの最大サイズが小さくなる可能性があります。この場合、結果のサイズは次の合計になり ます。 • インデックス内で一致する項目のサイズ(次の 4 KB に切り上げ) • ベーステーブル内で一致する各項目のサイズ (項目ごとに次の 4 KB に切り上げ) この式を使用すると、クエリオペレーションによって返される結果の最大サイズは依然として 1 MB になります。 たとえば、各項目のサイズが 300 バイトであるテーブルがあるとします。そのテーブルには local secondary index がありますが、各項目のうち 200 バイトだけがインデックスに射影されます。この インデックスに対して Query を行うときに各項目についてテーブルのフェッチが必要で、クエリに よって 4 つの項目が返されるとします。DynamoDB では次のように合計されます。 • インデックス内で一致する項目のサイズは 200 バイト × 4 項目 = 800 バイトになり、それが 4 KB に切り上げられます。 • ベーステーブル内で一致する項目のサイズ: (300 バイト、4 KB に切り上げ) × 4 項目 = 16 KB。 それによって、結果データの合計サイズは 20 KB になります。 書き込みキャパシティーユニット テーブル内の項目が追加、更新、または削除された場合に local secondary index を更新すると、テー ブルにプロビジョニングされた書き込みキャパシティーユニットが消費されます。書き込み用にプ ロビジョニングされたスループットの合計コストは、テーブルに対する書き込みと、local secondary index の更新で消費された書き込みキャパシティーユニットの合計になります。 local secondary index に項目を書き込むコストは、いくつかの要因によって異なります。 • インデックス付き属性が定義されたテーブルに新しい項目を書き込む場合、または既存の項目を更 新して未定義のインデックス付き属性を定義する場合には、インデックスへの項目の挿入に 1 回の 書き込みオペレーションが必要です。 • テーブルに対する更新によってインデックス付きキー属性の値が(A から B に)変更された場合に は、インデックスから既存の項目を削除し、インデックスに新しい項目を挿入するために、2 回の 書き込みが必要です。 • インデックス内に既存の項目があって、テーブルに対する書き込みによってインデックス付き属性 が削除された場合は、インデックスから古い項目の射影を削除するために、1 回の書き込みが必要 です。 API Version 2012-08-10 390 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス • 項目の更新の前後にインデックス内に項目が存在しない場合は、インデックスで追加の書き込みコ ストは発生しません。 これらすべての要因は、インデックス内の各項目のサイズが 1 KB 以下であるという前提で書き込み キャパシティーユニット数を算出します。インデックスエントリがそれよりも大きい場合は、書き込 みキャパシティーユニットを追加する必要があります。クエリが返す必要がある属性を特定し、それ らの属性だけをインデックスに射影することで、書き込みコストは最小になります。 ローカルセカンダリインデックス のストレージに関する考慮 事項 アプリケーションがテーブルに項目を書き込むと、DynamoDB では正しい属性のサブセットが、それ らの属性を表示する必要がある local secondary index に自動的にコピーされます。AWS アカウント では、テーブル内の項目のストレージと、そのベーステーブルのlocal secondary indexにある属性のス トレージに対して課金されます。 インデックス項目が使用するスペースの量は、次の量の合計になります。 • ベーステーブルのプライマリキー (パーティションキーとソートキー) のサイズのバイト数 • インデックスキー属性のサイズのバイト数 • 射影された属性(存在する場合)のサイズのバイト数 • インデックス項目あたり 100 bytes のオーバーヘッド local secondary indexのストレージ要件の見積もりは、インデックス内の 1 項目の平均サイズの見積 もり値にベーステーブルの項目数を掛けて算出します。 特定の属性が定義された項目がテーブルに含まれておらず、その属性がインデックスソートキーとし て定義されている場合、DynamoDB はその項目に関連するデータをインデックスに書き込みません。 この動作の詳細については、「スパースなインデックスの利用 (p. 585)」を参照してください。 項目コレクション Note 次のセクションは、local secondary index があるテーブルだけに関係します。 DynamoDB では、項目コレクションとは、テーブルおよびテーブルのlocal secondary index全体 で同じパーティションキーの値を持つ任意の項目グループです。このセクションで使用する例で は、Thread テーブルのパーティションキーは ForumName で、LastPostIndex のパーティションキー も ForumName です。同じ ForumName を持つテーブルとインデックス項目は、すべて同じ項目コレ クションの一部です。たとえば Thread テーブルと LastPostIndex local secondary index には、フォー ラム EC2 用の項目コレクションと、フォーラム RDS 用の別の項目コレクションがあります。 次の図は、フォーラム S3 の項目コレクションを示しています。 API Version 2012-08-10 391 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス この図では、項目コレクションは、ForumName パーティションキーの値が「S3」である Thread お よび LastPostIndex 内のすべての項目で構成されています。テーブルにその他のlocal secondary index があった場合には、ForumName が「S3」であるそれらのインデックス内の項目も、項目コレクショ ンの一部になります。 DynamoDB では次のオペレーションのいずれかを使用して、項目コレクションに関する情報を得るこ とができます。 • BatchWriteItem • DeleteItem • PutItem • UpdateItem API Version 2012-08-10 392 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス これらのオペレーションでは、それぞれ ReturnItemCollectionMetrics パラメータがサポートさ れています。このパラメータを SIZE に設定すると、インデックス内の各項目コレクションのサイズ に関する情報が表示されます。 Example UpdateItemThread テーブルでの オペレーションの出力に含まれる スニペットを示しま す。ReturnItemCollectionMetrics が SIZE に設定されています。更新された項目には ForumName 値「EC2」があったため、出力にはその項目コレクションに関する情報が含まれていま す。 { ItemCollectionMetrics: { ItemCollectionKey: { ForumName: "EC2" }, SizeEstimateRangeGB: [0.0, 1.0] } } SizeEstimateRangeGB オブジェクトは、項目コレクションのサイズが 0~1 GB の間であることを 示します。DynamoDB ではこのサイズ見積りが定期的に更新されるため、項目を次に変更したときに は数字が異なる場合があります。 項目コレクションのサイズ制限 1 つの項目コレクションのサイズは最大 10 GB までです。この制限は、local secondary index を含ま ないテーブルには適用されません。1 つ以上の local secondary index を含むテーブルのみに影響しま す。 項目コレクションが 10 GB を超えると、DynamoDB は ItemCollectionSizeLimitExceededException を返します。こうなると、その項目コレクショ ンに項目を追加することも、項目サイズを大きくすることもできません。(項目コレクションのサイ ズを小さくする読み込みおよび書き込みオペレーションは、引き続き実行できます)。その他の項目 コレクションには項目を追加することができます。 項目コレクションのサイズを小さくするには、次のいずれかを実行します。 • 問題になっているパーティションキーの値を持つ不要な項目を削除します。ベーステーブルからこ れらの項目を削除すると、DynamoDB では同じパーティションキーの値を持つインデックスエント リも削除されます。 • 属性を削除するか属性のサイズを小さくすることで、項目を更新します。これらの属性が local secondary index に射影されている場合には、DynamoDB では対応するインデックスエントリのサ イズも小さくなります。 • 同じパーティションキーおよびソートキーを使用して新しいテーブルを作成し、古いテーブルから 新しいテーブルに項目を移動します。これは、頻繁にアクセスされない履歴データがテーブルに含 まれている場合に適した方法です。この履歴データを Amazon Simple Storage Service(Amazon S3)にアーカイブすることもできます。 項目コレクションの合計サイズが 10 GB 未満になると、再び同じパーティションキーの値を使用して 項目を追加できるようになります。 項目コレクションのサイズを監視するようにアプリケーションを設定することをお勧めします。1 つ の方法としては、BatchWriteItem、DeleteItem、PutItem、または UpdateItem を使用する場合 に、ReturnItemCollectionMetrics パラメータを SIZE に設定するというものがあります。アプ リケーションで出力内の ReturnItemCollectionMetrics オブジェクトを調査し、項目コレクショ API Version 2012-08-10 393 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス ンがユーザー定義の制限(たとえば 8 GB)を超えた場合にエラーメッセージを記録するようにしま す。制限を 10 GB より低く設定すれば早期警告システムになり、項目コレクションが上限に達する前 に余裕をもって何らかの対処をとることができます。 項目コレクションおよびパーティション 各項目コレクションのテーブルおよびインデックスデータは、単一のパーティションに格納されま す。Thread テーブルの例では、同じ ForumName 属性を持つすべてのベーステーブルとインデックス 項目が、同じパーティション内に格納されます。「S3」項目コレクションが 1 つのパーティションに 格納され、「EC2」が別のパーティションに格納され、「RDS」が 3 つ目のパーティションに格納さ れます。 アプリケーションを設計する場合は、テーブルデータが異なるパーティションキー値に均一に分配さ れるようにする必要があります。local secondary index を持つテーブルについては、単一のパーティ ション内の単一の項目コレクションに読み込みおよび書き込みアクティビティの「ホットスポット」 が作られないように、アプリケーションを設計します。 ローカルセカンダリインデックス の使用 : Java トピック • ローカルセカンダリインデックス を使用したテーブルの作成 (p. 394) • ローカルセカンダリインデックス のあるテーブルの説明 (p. 396) • ローカルセカンダリインデックスのクエリ (p. 397) • 例: Java ドキュメント API を使用した ローカルセカンダリインデックス (p. 398) AWS SDK for Java ドキュメント API を使用して、1 つ以上の local secondary index を持つテーブル を作成し、テーブルのインデックスについて説明し、インデックスを使用してクエリを実行すること ができます。 次に、AWS SDK for Java ドキュメント API を使用したテーブルオペレーションの一般的なステップ を示します。 1. DynamoDB クラスのインスタンスを作成します。 2. 対応するリクエストオブジェクトを作成して、オペレーションについて必要なパラメータとオプ ションパラメータを入力します。 3. 前述のステップで作成したクライアントから提供された適切なメソッドを呼び出します。 ローカルセカンダリインデックス を使用したテーブルの作成 ローカルセカンダリインデックス は、テーブルの作成と同時に作成する必要があります。そのために は、createTable メソッドを使用して、1 つ以上の local secondary index の仕様を指定します。次 の Java コードスニペットでは、音楽コレクション内の曲に関する情報を保存するテーブルを作成し ています。パーティションキーは Artist で、ソートキーは SongTitle です。セカンダリインデックスの AlbumTitleIndex は、アルバムのタイトルによるクエリを容易にします。 次に、DynamoDB ドキュメント API を使用して、local secondary index があるテーブルを作成するス テップを示します。 1. DynamoDB クラスのインスタンスを作成します。 2. リクエスト情報を指定する CreateTableRequest クラスのインスタンスを作成します。 テーブル名、プライマリキー、プロビジョニング済みスループットの値を指定する必要がありま す。local secondary indexについては、インデックス名、インデックスソートキーの名前とデータ 型、インデックスのキースキーマ、属性射影を指定する必要があります。 API Version 2012-08-10 394 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 3. リクエストオブジェクトをパラメータとして指定して、createTable メソッドを呼び出します。 次の Java コードスニペットは、前述のステップを示しています。このスニペットでは、AlbumTitle 属性のセカンダリインデックスによって、テーブル(Music)が作成されています。インデックスに射 影される属性は、テーブルのパーティションキーおよびソートキーと、インデックスのソートキーだ けです。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); String tableName = "Music"; CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(tableName); //ProvisionedThroughput createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits((long)5).withWriteCapacityUnits((long)5)); //AttributeDefinitions ArrayList<AttributeDefinition> attributeDefinitions= new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition().withAttributeName("Artist").withAttributeType("S")); attributeDefinitions.add(new AttributeDefinition().withAttributeName("SongTitle").withAttributeType("S")); attributeDefinitions.add(new AttributeDefinition().withAttributeName("AlbumTitle").withAttributeType("S")); createTableRequest.setAttributeDefinitions(attributeDefinitions); //KeySchema ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>(); tableKeySchema.add(new KeySchemaElement().withAttributeName("Artist").withKeyType(KeyType.HASH)); //Partition key tableKeySchema.add(new KeySchemaElement().withAttributeName("SongTitle").withKeyType(KeyType.RANGE)); //Sort key createTableRequest.setKeySchema(tableKeySchema); ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>(); indexKeySchema.add(new KeySchemaElement().withAttributeName("Artist").withKeyType(KeyType.HASH)); //Partition key indexKeySchema.add(new KeySchemaElement().withAttributeName("AlbumTitle").withKeyType(KeyType.RANGE)); //Sort key Projection projection = new Projection().withProjectionType(ProjectionType.INCLUDE); ArrayList<String> nonKeyAttributes = new ArrayList<String>(); nonKeyAttributes.add("Genre"); nonKeyAttributes.add("Year"); API Version 2012-08-10 395 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス projection.setNonKeyAttributes(nonKeyAttributes); LocalSecondaryIndex localSecondaryIndex = new LocalSecondaryIndex() .withIndexName("AlbumTitleIndex").withKeySchema(indexKeySchema).withProjection(projection); ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new ArrayList<LocalSecondaryIndex>(); localSecondaryIndexes.add(localSecondaryIndex); createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes); Table table = dynamoDB.createTable(createTableRequest); System.out.println(table.getDescription()); DynamoDB がテーブルを作成し、テーブルのステータスを ACTIVE に設定するまで待機する必要があ ります。その後は、データ項目をテーブルに書き込むことが可能になります。 ローカルセカンダリインデックス のあるテーブルの説明 テーブルの local secondary index に関する情報を取得するには、describeTable メソッドを使用し ます。各インデックスについて、名前、キースキーマ、射影された属性にアクセスできます。 次に、AWS SDK for Java ドキュメント API を使用して、テーブルの local secondary index 情報にア クセスするステップを示します。 1. DynamoDB クラスのインスタンスを作成します。 2. Table クラスのインスタンスを作成します。テーブル名を入力する必要があります。 3. Table オブジェクトで describeTable メソッドを呼び出します。 次の Java コードスニペットは、前述のステップを示しています。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); String tableName = "Music"; Table table = dynamoDB.getTable(tableName); TableDescription tableDescription = table.describe(); List<LocalSecondaryIndexDescription> localSecondaryIndexes = tableDescription.getLocalSecondaryIndexes(); // This code snippet will work for multiple indexes, even though // there is only one index in this example. Iterator<LocalSecondaryIndexDescription> lsiIter = localSecondaryIndexes.iterator(); while (lsiIter.hasNext()) { LocalSecondaryIndexDescription lsiDescription = lsiIter.next(); System.out.println("Info for index " + lsiDescription.getIndexName() + ":"); Iterator<KeySchemaElement> kseIter = lsiDescription.getKeySchema().iterator(); while (kseIter.hasNext()) { KeySchemaElement kse = kseIter.next(); API Version 2012-08-10 396 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType()); } Projection projection = lsiDescription.getProjection(); System.out.println("\tThe projection type is: " + projection.getProjectionType()); if (projection.getProjectionType().toString().equals("INCLUDE")) { System.out.println("\t\tThe non-key projected attributes are: " + projection.getNonKeyAttributes()); } } ローカルセカンダリインデックスのクエリ local secondary index では、テーブルの Query を実行するのと同様の方法で、Query オペレーション を使用できます。 インデックス名、インデックスソートキーのクエリ基準、および返されるようにす る属性を指定する必要があります。この例では、インデックスが AlbumTitleIndex で、インデックス ソートキーが AlbumTitle です。 返される属性は、インデックスに射影された属性だけです。このクエリを変更して非キー属性も選択 するように設定することもできますが、その場合は比較的コストがかかるテーブルフェッチアクティ ビティが必要になります。テーブルのフェッチの詳細については、「属性の射影 (p. 385)」を参照し てください。 以下に、AWS SDK for Java ドキュメント API を使用して local secondary index のクエリを行う手順 を示します。 1. DynamoDB クラスのインスタンスを作成します。 2. Table クラスのインスタンスを作成します。テーブル名を入力する必要があります。 3. Index クラスのインスタンスを作成します。インデックス名を提供しなければなりません。 4. Index クラスの query メソッドを呼び出します。 次の Java コードスニペットは、前述のステップを示しています。 DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); String tableName = "Music"; Table table = dynamoDB.getTable(tableName); Index index = table.getIndex("AlbumTitleIndex"); QuerySpec spec = new QuerySpec() .withKeyConditionExpression("Artist = :v_artist and AlbumTitle = :v_title") .withValueMap(new ValueMap() .withString(":v_artist", "Acme Band") .withString(":v_title", "Songs About Life")); ItemCollection<QueryOutcome> items = index.query(spec); Iterator<Item> itemsIter = items.iterator(); while (itemsIter.hasNext()) { Item item = itemsIter.next(); System.out.println(item.toJSONPretty()); API Version 2012-08-10 397 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス } 例: Java ドキュメント API を使用した ローカルセカンダリインデックス 次の Java コード例では、local secondary index の操作方法を示します。この例では、パーティション キーとして CustomerId、ソートキーとして OrderId を使用して、CustomerOrders という名前のテー ブルが作成されます。このテーブルには次の 2 つの local secondary index があります。 • OrderCreationDateIndex — ソートキーは OrderCreationDate で、次の属性がインデックスに射影さ れます。 • ProductCategory • ProductName • OrderStatus • ShipmentTrackingId • IsOpenIndex — ソートキーは IsOpen で、すべてのテーブル属性がインデックスに射影されていま す。 CustomerOrders テーブルを作成すると、プログラムによってカスタマーの注文を表すデータがテー ブルにロードされ、local secondary index を使用してデータのクエリが行われます。最後に、プログ ラムによって CustomerOrders テーブルが削除されます。 次のサンプルをテストするための詳しい手順については、「Java コードサンプル (p. 171)」を参照し てください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.document; import java.util.ArrayList; import java.util.Iterator; import import import import import import import import import import import import import import import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Index; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.ItemCollection; com.amazonaws.services.dynamodbv2.document.PutItemOutcome; com.amazonaws.services.dynamodbv2.document.QueryOutcome; com.amazonaws.services.dynamodbv2.document.Table; com.amazonaws.services.dynamodbv2.document.spec.QuerySpec; com.amazonaws.services.dynamodbv2.document.utils.ValueMap; com.amazonaws.services.dynamodbv2.model.AttributeDefinition; com.amazonaws.services.dynamodbv2.model.CreateTableRequest; com.amazonaws.services.dynamodbv2.model.KeySchemaElement; com.amazonaws.services.dynamodbv2.model.KeyType; com.amazonaws.services.dynamodbv2.model.LocalSecondaryIndex; com.amazonaws.services.dynamodbv2.model.Projection; com.amazonaws.services.dynamodbv2.model.ProjectionType; com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; com.amazonaws.services.dynamodbv2.model.ReturnConsumedCapacity; com.amazonaws.services.dynamodbv2.model.Select; public class DocumentAPILocalSecondaryIndexExample { static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( API Version 2012-08-10 398 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス new ProfileCredentialsProvider())); public static String tableName = "CustomerOrders"; public static void main(String[] args) throws Exception { createTable(); loadData(); query(null); query("IsOpenIndex"); query("OrderCreationDateIndex"); deleteTable(tableName); } public static void createTable() { CreateTableRequest createTableRequest = new CreateTableRequest() .withTableName(tableName) .withProvisionedThroughput(new ProvisionedThroughput() .withReadCapacityUnits((long) 1) .withWriteCapacityUnits((long) 1)); // Attribute definitions for table partition and sort keys ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("CustomerId") .withAttributeType("S")); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("OrderId") .withAttributeType("N")); // Attribute definition for index primary key attributes attributeDefinitions.add(new AttributeDefinition() .withAttributeName("OrderCreationDate") .withAttributeType("N")); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("IsOpen") .withAttributeType("N")); createTableRequest.setAttributeDefinitions(attributeDefinitions); // Key schema for table ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>(); tableKeySchema.add(new KeySchemaElement() .withAttributeName("CustomerId") .withKeyType(KeyType.HASH)); //Partition key tableKeySchema.add(new KeySchemaElement() .withAttributeName("OrderId") .withKeyType(KeyType.RANGE)); //Sort key createTableRequest.setKeySchema(tableKeySchema); ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new ArrayList<LocalSecondaryIndex>(); API Version 2012-08-10 399 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス // OrderCreationDateIndex LocalSecondaryIndex orderCreationDateIndex = new LocalSecondaryIndex() .withIndexName("OrderCreationDateIndex"); // Key schema for OrderCreationDateIndex ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>(); indexKeySchema.add(new KeySchemaElement() .withAttributeName("CustomerId") .withKeyType(KeyType.HASH)); //Partition key indexKeySchema.add(new KeySchemaElement() .withAttributeName("OrderCreationDate") .withKeyType(KeyType.RANGE)); //Sort key orderCreationDateIndex.setKeySchema(indexKeySchema); // Projection (with list of projected attributes) for // OrderCreationDateIndex Projection projection = new Projection() .withProjectionType(ProjectionType.INCLUDE); ArrayList<String> nonKeyAttributes = new ArrayList<String>(); nonKeyAttributes.add("ProductCategory"); nonKeyAttributes.add("ProductName"); projection.setNonKeyAttributes(nonKeyAttributes); orderCreationDateIndex.setProjection(projection); localSecondaryIndexes.add(orderCreationDateIndex); // IsOpenIndex LocalSecondaryIndex isOpenIndex = new LocalSecondaryIndex() .withIndexName("IsOpenIndex"); // Key schema for IsOpenIndex indexKeySchema = new ArrayList<KeySchemaElement>(); indexKeySchema.add(new KeySchemaElement() .withAttributeName("CustomerId") .withKeyType(KeyType.HASH)); //Partition key indexKeySchema.add(new KeySchemaElement() .withAttributeName("IsOpen") .withKeyType(KeyType.RANGE)); //Sort key // Projection (all attributes) for IsOpenIndex projection = new Projection() .withProjectionType(ProjectionType.ALL); isOpenIndex.setKeySchema(indexKeySchema); isOpenIndex.setProjection(projection); localSecondaryIndexes.add(isOpenIndex); // Add index definitions to CreateTable request createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes); System.out.println("Creating table " + tableName + "..."); System.out.println(dynamoDB.createTable(createTableRequest)); API Version 2012-08-10 400 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス // Wait for table to become active System.out.println("Waiting for " + tableName + " to become ACTIVE..."); try { Table table = dynamoDB.getTable(tableName); table.waitForActive(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void query(String indexName) { Table table = dynamoDB.getTable(tableName); System.out .println("\n***********************************************************\n"); System.out.println("Querying table " + tableName + "..."); QuerySpec querySpec = new QuerySpec() .withConsistentRead(true) .withScanIndexForward(true) .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL); if (indexName == "IsOpenIndex") { System.out.println("\nUsing index: '" + indexName + "': Bob's orders that are open."); System.out.println( "Only a user-specified list of attributes are returned\n"); Index index = table.getIndex(indexName); querySpec.withKeyConditionExpression("CustomerId = :v_custid and IsOpen = :v_isopen") .withValueMap(new ValueMap() .withString(":v_custid", "[email protected]") .withNumber(":v_isopen", 1)); querySpec.withProjectionExpression( "OrderCreationDate, ProductCategory, ProductName, OrderStatus"); ItemCollection<QueryOutcome> items = index.query(querySpec); Iterator<Item> iterator = items.iterator(); System.out.println("Query: printing results..."); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } } else if (indexName == "OrderCreationDateIndex") { System.out.println("\nUsing index: '" + indexName + "': Bob's orders that were placed after 01/31/2015."); System.out.println("Only the projected attributes are returned \n"); Index index = table.getIndex(indexName); API Version 2012-08-10 401 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス querySpec.withKeyConditionExpression("CustomerId = :v_custid and OrderCreationDate >= :v_orddate") .withValueMap(new ValueMap() .withString(":v_custid", "[email protected]") .withNumber(":v_orddate", 20150131)); querySpec.withSelect(Select.ALL_PROJECTED_ATTRIBUTES); ItemCollection<QueryOutcome> items = index.query(querySpec); Iterator<Item> iterator = items.iterator(); System.out.println("Query: printing results..."); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } } else { System.out.println("\nNo index: All of Bob's orders, by OrderId: \n"); querySpec.withKeyConditionExpression("CustomerId = :v_custid") .withValueMap(new ValueMap() .withString(":v_custid", "[email protected]")); ItemCollection<QueryOutcome> items = table.query(querySpec); Iterator<Item> iterator = items.iterator(); System.out.println("Query: printing results..."); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } } } public static void deleteTable(String tableName) { Table table = dynamoDB.getTable(tableName); System.out.println("Deleting table " + tableName + "..."); table.delete(); // Wait for table to be deleted System.out.println("Waiting for " + tableName + " to be deleted..."); try { table.waitForDelete(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void loadData() { Table table = dynamoDB.getTable(tableName); System.out.println("Loading data into table " + tableName + "..."); API Version 2012-08-10 402 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス Item item = new Item() .withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 1) .withNumber("IsOpen", 1) .withNumber("OrderCreationDate", 20150101) .withString("ProductCategory", "Book") .withString("ProductName", "The Great Outdoors") .withString("OrderStatus", "PACKING ITEMS"); // no ShipmentTrackingId attribute PutItemOutcome putItemOutcome = table.putItem(item); item = new Item() .withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 2) .withNumber("IsOpen", 1) .withNumber("OrderCreationDate", 20150221) .withString("ProductCategory", "Bike") .withString("ProductName", "Super Mountain") .withString("OrderStatus", "ORDER RECEIVED"); // no ShipmentTrackingId attribute putItemOutcome = table.putItem(item); item = new Item() .withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 3) // no IsOpen attribute .withNumber("OrderCreationDate", 20150304) .withString("ProductCategory", "Music") .withString("ProductName", "A Quiet Interlude") .withString("OrderStatus", "IN TRANSIT") .withString("ShipmentTrackingId", "176493"); putItemOutcome = table.putItem(item); item = new Item() .withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 1) // no IsOpen attribute .withNumber("OrderCreationDate", 20150111) .withString("ProductCategory", "Movie") .withString("ProductName", "Calm Before The Storm") .withString("OrderStatus", "SHIPPING DELAY") .withString("ShipmentTrackingId", "859323"); putItemOutcome = table.putItem(item); item = new Item() .withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 2) // no IsOpen attribute .withNumber("OrderCreationDate", 20150124) .withString("ProductCategory", "Music") .withString("ProductName", "E-Z Listening") .withString("OrderStatus", "DELIVERED") .withString("ShipmentTrackingId", "756943"); putItemOutcome = table.putItem(item); API Version 2012-08-10 403 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス item = new Item() .withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 3) // no IsOpen attribute .withNumber("OrderCreationDate", 20150221) .withString("ProductCategory", "Music") .withString("ProductName", "Symphony 9") .withString("OrderStatus", "DELIVERED") .withString("ShipmentTrackingId", "645193"); putItemOutcome = table.putItem(item); item = new Item().withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 4).withNumber("IsOpen", 1) .withNumber("OrderCreationDate", 20150222) .withString("ProductCategory", "Hardware") .withString("ProductName", "Extra Heavy Hammer") .withString("OrderStatus", "PACKING ITEMS"); // no ShipmentTrackingId attribute putItemOutcome = table.putItem(item); item = new Item().withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 5) /* no IsOpen attribute */ .withNumber("OrderCreationDate", 20150309) .withString("ProductCategory", "Book") .withString("ProductName", "How To Cook") .withString("OrderStatus", "IN TRANSIT") .withString("ShipmentTrackingId", "440185"); putItemOutcome = table.putItem(item); item = new Item() .withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 6) // no IsOpen attribute .withNumber("OrderCreationDate", 20150318) .withString("ProductCategory", "Luggage") .withString("ProductName", "Really Big Suitcase") .withString("OrderStatus", "DELIVERED") .withString("ShipmentTrackingId", "893927"); putItemOutcome = table.putItem(item); item = new Item().withPrimaryKey("CustomerId", "[email protected]") .withNumber("OrderId", 7) /* no IsOpen attribute */ .withNumber("OrderCreationDate", 20150324) .withString("ProductCategory", "Golf") .withString("ProductName", "PGA Pro II") .withString("OrderStatus", "OUT FOR DELIVERY") .withString("ShipmentTrackingId", "383283"); putItemOutcome = table.putItem(item); assert putItemOutcome != null; } API Version 2012-08-10 404 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス } ローカルセカンダリインデックスes: .NET の使用 トピック • ローカルセカンダリインデックス を使用したテーブルの作成 (p. 405) • ローカルセカンダリインデックス のあるテーブルの説明 (p. 407) • ローカルセカンダリインデックス のクエリ (p. 408) • 例: AWS SDK for .NET 低レベル API を使用した ローカルセカンダリインデックス (p. 409) AWS SDK for .NET 低レベル API を使用して、1 つ以上の local secondary index を持つテーブルを作 成し、テーブルのインデックスについて説明し、インデックスを使用してクエリを実行することがで きます。 これらのオペレーションは、対応する低レベル DynamoDB API アクションにマッピングし ます。 詳細については、「.NET コードサンプル (p. 173)」を参照してください。 次に、.NET 低レベル API を使用したテーブルオペレーションの一般的なステップを示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. 対応するリクエストオブジェクトを作成して、オペレーションについて必要なパラメータとオプ ションパラメータを入力します。 たとえば、テーブルを作成するための CreateTableRequest オブジェクトと、テーブルまたはイ ンデックスのクエリを行うための QueryRequest オブジェクトを作成します。 3. 前述のステップで作成したクライアントから提供された適切なメソッドを実行します。 ローカルセカンダリインデックス を使用したテーブルの作成 ローカルセカンダリインデックス は、テーブルの作成と同時に作成する必要があります。そのた めには、CreateTable を使用して、1 つ以上の local secondary index の仕様を指定します。 次の C# コードスニペットでは、音楽コレクション内の曲に関する情報を保存するテーブルを作成してい ます。パーティションキーは Artist で、ソートキーは SongTitle です。セカンダリインデックスの AlbumTitleIndex は、アルバムのタイトルによるクエリを容易にします。 次に、.NET 低レベル API を使用して、local secondary index があるテーブルを作成するステップを示 します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. リクエスト情報を指定する CreateTableRequest クラスのインスタンスを作成します。 テーブル名、プライマリキー、プロビジョニング済みスループットの値を指定する必要がありま す。local secondary indexについては、インデックス名、インデックスソートキーの名前とデータ 型、インデックスのキースキーマ、属性射影を指定する必要があります。 3. リクエストオブジェクトをパラメータとして指定して、CreateTable メソッドを実行します。 次の C# コードスニペットは、前述のステップを示しています。このスニペットでは、AlbumTitle 属 性のセカンダリインデックスによって、テーブル(Music)が作成されています。インデックスに射影 される属性は、テーブルのパーティションキーおよびソートキーと、インデックスのソートキーだけ です。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "Music"; CreateTableRequest createTableRequest = new CreateTableRequest() { API Version 2012-08-10 405 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス TableName = tableName }; //ProvisionedThroughput createTableRequest.ProvisionedThroughput = new ProvisionedThroughput() { ReadCapacityUnits = (long)5, WriteCapacityUnits = (long)5 }; //AttributeDefinitions List<AttributeDefinition> attributeDefinitions = new List<AttributeDefinition>(); attributeDefinitions.Add(new AttributeDefinition() { AttributeName = "Artist", AttributeType = "S" }); attributeDefinitions.Add(new AttributeDefinition() { AttributeName = "SongTitle", AttributeType = "S" }); attributeDefinitions.Add(new AttributeDefinition() { AttributeName = "AlbumTitle", AttributeType = "S" }); createTableRequest.AttributeDefinitions = attributeDefinitions; //KeySchema List<KeySchemaElement> tableKeySchema = new List<KeySchemaElement>(); tableKeySchema.Add(new KeySchemaElement() { AttributeName = "Artist", KeyType = "HASH" }); //Partition key tableKeySchema.Add(new KeySchemaElement() { AttributeName = "SongTitle", KeyType = "RANGE" }); //Sort key createTableRequest.KeySchema = tableKeySchema; List<KeySchemaElement> indexKeySchema = new List<KeySchemaElement>(); indexKeySchema.Add(new KeySchemaElement() { AttributeName = "Artist", KeyType = "HASH" }); //Partition key indexKeySchema.Add(new KeySchemaElement() { AttributeName = "AlbumTitle", KeyType = "RANGE" }); //Sort key Projection projection = new Projection() { ProjectionType = "INCLUDE" }; List<string> nonKeyAttributes = new List<string>(); nonKeyAttributes.Add("Genre"); nonKeyAttributes.Add("Year"); projection.NonKeyAttributes = nonKeyAttributes; LocalSecondaryIndex localSecondaryIndex = new LocalSecondaryIndex() { API Version 2012-08-10 406 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス IndexName = "AlbumTitleIndex", KeySchema = indexKeySchema, Projection = projection }; List<LocalSecondaryIndex> localSecondaryIndexes = new List<LocalSecondaryIndex>(); localSecondaryIndexes.Add(localSecondaryIndex); createTableRequest.LocalSecondaryIndexes = localSecondaryIndexes; CreateTableResponse result = client.CreateTable(createTableRequest); Console.WriteLine(result.CreateTableResult.TableDescription.TableName); Console.WriteLine(result.CreateTableResult.TableDescription.TableStatus); DynamoDB がテーブルを作成し、テーブルのステータスを ACTIVE に設定するまで待機する必要があ ります。その後は、データ項目をテーブルに書き込むことが可能になります。 ローカルセカンダリインデックス のあるテーブルの説明 テーブルの local secondary index に関する情報を取得するには、DescribeTable API を使用しま す。各インデックスについて、名前、キースキーマ、射影された属性にアクセスできます。 次に、.NET 低レベル API を使用して、テーブルの local secondary index 情報にアクセスするステッ プを示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. リクエスト情報を指定する DescribeTableRequest クラスのインスタンスを作成します。テーブ ル名を入力する必要があります。 3. リクエストオブジェクトをパラメータとして指定して、describeTable メソッドを実行します。 次の C# コードスニペットは、前述のステップを示しています。 AmazonDynamoDBClient client = new AmazonDynamoDBClient(); string tableName = "Music"; DescribeTableResponse response = client.DescribeTable(new DescribeTableRequest() { TableName = tableName }); List<LocalSecondaryIndexDescription> localSecondaryIndexes = response.DescribeTableResult.Table.LocalSecondaryIndexes; // This code snippet will work for multiple indexes, even though // there is only one index in this example. foreach (LocalSecondaryIndexDescription lsiDescription in localSecondaryIndexes) { Console.WriteLine("Info for index " + lsiDescription.IndexName + ":"); foreach (KeySchemaElement kse in lsiDescription.KeySchema) { Console.WriteLine("\t" + kse.AttributeName + ": key type is " + kse.KeyType); } Projection projection = lsiDescription.Projection; Console.WriteLine("\tThe projection type is: " + projection.ProjectionType); API Version 2012-08-10 407 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス if (projection.ProjectionType.ToString().Equals("INCLUDE")) { Console.WriteLine("\t\tThe non-key projected attributes are:"); foreach (String s in projection.NonKeyAttributes) { Console.WriteLine("\t\t" + s); } } } ローカルセカンダリインデックス のクエリ local secondary index では、テーブルの Query を実行するのと同様の方法で、Query を使用できま す。 インデックス名、インデックスソートキーのクエリ基準、および返されるようにする属性を指定 する必要があります。この例では、インデックスが AlbumTitleIndex で、インデックスソートキーが AlbumTitle です。 返される属性は、インデックスに射影された属性だけです。このクエリを変更して非キー属性も選択 するように設定することもできますが、その場合は比較的コストがかかるテーブルフェッチアクティ ビティが必要になります。テーブルのフェッチの詳細については、「属性の射影 (p. 385)」を参照し てください。 次に、.NET 低レベル API を使用して local secondary index のクエリを行うステップを示します。 1. AmazonDynamoDBClient クラスのインスタンスを作成します。 2. リクエスト情報を指定する QueryRequest クラスのインスタンスを作成します。 3. リクエストオブジェクトをパラメータとして指定して、query メソッドを実行します。 次の C# コードスニペットは、前述のステップを示しています。 QueryRequest queryRequest = new QueryRequest { TableName = "Music", IndexName = "AlbumTitleIndex", Select = "ALL_ATTRIBUTES", ScanIndexForward = true, KeyConditionExpression = "Artist = :v_artist and AlbumTitle = :v_title", ExpressionAttributeValues = new Dictionary<string, AttributeValue>() { {":v_artist",new AttributeValue {S = "Acme Band"}}, {":v_title",new AttributeValue {S = "Songs About Life"}} }, }; QueryResponse response = client.Query(queryRequest); foreach (var attribs in response.Items) { foreach (var attrib in attribs) { Console.WriteLine(attrib.Key + " ---> " + attrib.Value.S); } Console.WriteLine(); API Version 2012-08-10 408 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス } 例: AWS SDK for .NET 低レベル API を使用した ローカルセカンダリインデッ クス 次の C# コード例では、local secondary index の操作方法を示します。この例では、パーティション キーとして CustomerId、ソートキーとして OrderId を使用して、CustomerOrders という名前のテー ブルが作成されます。このテーブルには次の 2 つの local secondary index があります。 • OrderCreationDateIndex — ソートキーは OrderCreationDate で、次の属性がインデックスに射影さ れます。 • ProductCategory • ProductName • OrderStatus • ShipmentTrackingId • IsOpenIndex — ソートキーは IsOpen で、すべてのテーブル属性がインデックスに射影されていま す。 CustomerOrders テーブルを作成すると、プログラムによってカスタマーの注文を表すデータがテー ブルにロードされ、local secondary index を使用してデータのクエリが行われます。最後に、プログ ラムによって CustomerOrders テーブルが削除されます。 次のサンプルをテストするための詳しい手順については、「.NET コードサンプル (p. 173)」を参照し てください。 using using using using using using using using using System; System.Collections.Generic; System.Linq; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DataModel; Amazon.DynamoDBv2.DocumentModel; Amazon.DynamoDBv2.Model; Amazon.Runtime; Amazon.SecurityToken; namespace com.amazonaws.codesamples { class LowLevelLocalSecondaryIndexExample { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); private static string tableName = "CustomerOrders"; static void Main(string[] args) { try { CreateTable(); LoadData(); Query(null); Query("IsOpenIndex"); Query("OrderCreationDateIndex"); DeleteTable(tableName); API Version 2012-08-10 409 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } private static void CreateTable() { var createTableRequest = new CreateTableRequest() { TableName = tableName, ProvisionedThroughput = new ProvisionedThroughput() { ReadCapacityUnits = (long)1, WriteCapacityUnits = (long)1 } }; var attributeDefinitions = new List<AttributeDefinition>() { // Attribute definitions for table primary key { new AttributeDefinition() {AttributeName = "CustomerId", AttributeType = "S"} }, { new AttributeDefinition() {AttributeName = "OrderId", AttributeType = "N"} }, // Attribute definitions for index primary key { new AttributeDefinition() {AttributeName = "OrderCreationDate", AttributeType = "N"} }, { new AttributeDefinition() {AttributeName = "IsOpen", AttributeType = "N" }} }; createTableRequest.AttributeDefinitions = attributeDefinitions; // Key schema for table var tableKeySchema = new List<KeySchemaElement>() { { new KeySchemaElement() {AttributeName = "CustomerId", KeyType = "HASH"} }, //Partition key { new KeySchemaElement() {AttributeName = "OrderId", KeyType = "RANGE"} } //Sort key }; createTableRequest.KeySchema = tableKeySchema; var localSecondaryIndexes = new List<LocalSecondaryIndex>(); // OrderCreationDateIndex LocalSecondaryIndex orderCreationDateIndex = new LocalSecondaryIndex() { IndexName = "OrderCreationDateIndex" API Version 2012-08-10 410 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス }; // Key schema for OrderCreationDateIndex var indexKeySchema = new List<KeySchemaElement>() { { new KeySchemaElement() {AttributeName = "CustomerId", KeyType = "HASH"} }, //Partition key { new KeySchemaElement() {AttributeName = "OrderCreationDate", KeyType = "RANGE"} } //Sort key }; orderCreationDateIndex.KeySchema = indexKeySchema; // Projection (with list of projected attributes) for // OrderCreationDateIndex var projection = new Projection() { ProjectionType = "INCLUDE" }; var nonKeyAttributes = new List<string>() { "ProductCategory", "ProductName" }; projection.NonKeyAttributes = nonKeyAttributes; orderCreationDateIndex.Projection = projection; localSecondaryIndexes.Add(orderCreationDateIndex); // IsOpenIndex LocalSecondaryIndex isOpenIndex = new LocalSecondaryIndex() { IndexName = "IsOpenIndex" }; // Key schema for IsOpenIndex indexKeySchema = new List<KeySchemaElement>() { { new KeySchemaElement() {AttributeName = "CustomerId", KeyType = "HASH" }}, //Partition key { new KeySchemaElement() {AttributeName = "IsOpen", KeyType = "RANGE" }} //Sort key }; // Projection (all attributes) for IsOpenIndex projection = new Projection() { ProjectionType = "ALL" }; isOpenIndex.KeySchema = indexKeySchema; isOpenIndex.Projection = projection; localSecondaryIndexes.Add(isOpenIndex); // Add index definitions to CreateTable request createTableRequest.LocalSecondaryIndexes = localSecondaryIndexes; Console.WriteLine("Creating table " + tableName + "..."); client.CreateTable(createTableRequest); WaitUntilTableReady(tableName); } public static void Query(string indexName) { API Version 2012-08-10 411 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス Console.WriteLine("\n*********************************************************** \n"); Console.WriteLine("Querying table " + tableName + "..."); QueryRequest queryRequest = new QueryRequest() { TableName = tableName, ConsistentRead = true, ScanIndexForward = true, ReturnConsumedCapacity = "TOTAL" }; String keyConditionExpression = "CustomerId = :v_customerId"; Dictionary<string, AttributeValue> expressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_customerId", new AttributeValue { S = "[email protected]" }} }; if (indexName == "IsOpenIndex") { Console.WriteLine("\nUsing index: '" + indexName + "': Bob's orders that are open."); Console.WriteLine("Only a user-specified list of attributes are returned\n"); queryRequest.IndexName = indexName; keyConditionExpression += " and IsOpen = :v_isOpen"; expressionAttributeValues.Add(":v_isOpen", new AttributeValue { N = "1" }); // ProjectionExpression queryRequest.ProjectionExpression = "OrderCreationDate, ProductCategory, ProductName, OrderStatus"; } else if (indexName == "OrderCreationDateIndex") { Console.WriteLine("\nUsing index: '" + indexName + "': Bob's orders that were placed after 01/31/2013."); Console.WriteLine("Only the projected attributes are returned \n"); queryRequest.IndexName = indexName; keyConditionExpression += " and OrderCreationDate > :v_Date"; expressionAttributeValues.Add(":v_Date", new AttributeValue { N = "20130131" }); // Select queryRequest.Select = "ALL_PROJECTED_ATTRIBUTES"; } else { Console.WriteLine("\nNo index: All of Bob's orders, by OrderId:\n"); } API Version 2012-08-10 412 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス queryRequest.KeyConditionExpression = keyConditionExpression; queryRequest.ExpressionAttributeValues = expressionAttributeValues; var result = client.Query(queryRequest); var items = result.Items; foreach (var currentItem in items) { foreach (string attr in currentItem.Keys) { if (attr == "OrderId" || attr == "IsOpen" || attr == "OrderCreationDate") { Console.WriteLine(attr + "---> " + currentItem[attr].N); } else { Console.WriteLine(attr + "---> " + currentItem[attr].S); } } Console.WriteLine(); } Console.WriteLine("\nConsumed capacity: " + result.ConsumedCapacity.CapacityUnits + "\n"); } private static void DeleteTable(string tableName) { Console.WriteLine("Deleting table " + tableName + "..."); client.DeleteTable(new DeleteTableRequest() { TableName = tableName }); WaitForTableToBeDeleted(tableName); } public static void LoadData() { Console.WriteLine("Loading data into table " + tableName + "..."); Dictionary<string, AttributeValue> item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "1" }; item["IsOpen"] = new AttributeValue { N = "1" }; item["OrderCreationDate"] = new AttributeValue { N = "20130101" }; item["ProductCategory"] = new AttributeValue { S = "Book" }; item["ProductName"] = new AttributeValue { S = "The Great Outdoors" }; item["OrderStatus"] = new AttributeValue { S = "PACKING ITEMS" }; /* no ShipmentTrackingId attribute */ PutItemRequest putItemRequest = new PutItemRequest { TableName = tableName, Item = item, API Version 2012-08-10 413 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "2" }; item["IsOpen"] = new AttributeValue { N = "1" }; item["OrderCreationDate"] = new AttributeValue { N = "20130221" }; item["ProductCategory"] = new AttributeValue { S = "Bike" }; item["ProductName"] = new AttributeValue { S = "Super Mountain" }; item["OrderStatus"] = new AttributeValue { S = "ORDER RECEIVED" }; /* no ShipmentTrackingId attribute */ putItemRequest = new PutItemRequest { TableName = tableName, Item = item, ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "3" }; /* no IsOpen attribute */ item["OrderCreationDate"] = new AttributeValue { N = "20130304" }; item["ProductCategory"] = new AttributeValue { S = "Music" }; item["ProductName"] = new AttributeValue { S = "A Quiet Interlude" }; item["OrderStatus"] = new AttributeValue { S = "IN TRANSIT" }; item["ShipmentTrackingId"] = new AttributeValue { S = "176493" }; putItemRequest = new PutItemRequest { TableName = tableName, Item = item, ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "1" }; /* no IsOpen attribute */ item["OrderCreationDate"] = new AttributeValue { N = "20130111" }; item["ProductCategory"] = new AttributeValue { S = "Movie" }; item["ProductName"] = new AttributeValue { S = "Calm Before The Storm" }; item["OrderStatus"] = new AttributeValue { S = "SHIPPING DELAY" }; item["ShipmentTrackingId"] = new AttributeValue { S = "859323" }; putItemRequest = new PutItemRequest API Version 2012-08-10 414 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス { TableName = tableName, Item = item, ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "2" }; /* no IsOpen attribute */ item["OrderCreationDate"] = new AttributeValue { N = "20130124" }; item["ProductCategory"] = new AttributeValue { S = "Music" }; item["ProductName"] = new AttributeValue { S = "E-Z Listening" }; item["OrderStatus"] = new AttributeValue { S = "DELIVERED" }; item["ShipmentTrackingId"] = new AttributeValue { S = "756943" }; putItemRequest = new PutItemRequest { TableName = tableName, Item = item, ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "3" }; /* no IsOpen attribute */ item["OrderCreationDate"] = new AttributeValue { N = "20130221" }; item["ProductCategory"] = new AttributeValue { S = "Music" }; item["ProductName"] = new AttributeValue { S = "Symphony 9" }; item["OrderStatus"] = new AttributeValue { S = "DELIVERED" }; item["ShipmentTrackingId"] = new AttributeValue { S = "645193" }; putItemRequest = new PutItemRequest { TableName = tableName, Item = item, ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "4" }; item["IsOpen"] = new AttributeValue { N = "1" }; item["OrderCreationDate"] = new AttributeValue { N = "20130222" }; item["ProductCategory"] = new AttributeValue { S = "Hardware" }; item["ProductName"] = new AttributeValue { S = "Extra Heavy Hammer" }; item["OrderStatus"] = new AttributeValue { S = "PACKING ITEMS" }; /* no ShipmentTrackingId attribute */ putItemRequest = new PutItemRequest { API Version 2012-08-10 415 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス TableName = tableName, Item = item, ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "5" }; /* no IsOpen attribute */ item["OrderCreationDate"] = new AttributeValue { N = "20130309" }; item["ProductCategory"] = new AttributeValue { S = "Book" }; item["ProductName"] = new AttributeValue { S = "How To Cook" }; item["OrderStatus"] = new AttributeValue { S = "IN TRANSIT" }; item["ShipmentTrackingId"] = new AttributeValue { S = "440185" }; putItemRequest = new PutItemRequest { TableName = tableName, Item = item, ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "6" }; /* no IsOpen attribute */ item["OrderCreationDate"] = new AttributeValue { N = "20130318" }; item["ProductCategory"] = new AttributeValue { S = "Luggage" }; item["ProductName"] = new AttributeValue { S = "Really Big Suitcase" }; item["OrderStatus"] = new AttributeValue { S = "DELIVERED" }; item["ShipmentTrackingId"] = new AttributeValue { S = "893927" }; putItemRequest = new PutItemRequest { TableName = tableName, Item = item, ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); item = new Dictionary<string, AttributeValue>(); item["CustomerId"] = new AttributeValue { S = "[email protected]" }; item["OrderId"] = new AttributeValue { N = "7" }; /* no IsOpen attribute */ item["OrderCreationDate"] = new AttributeValue { N = "20130324" }; item["ProductCategory"] = new AttributeValue { S = "Golf" }; item["ProductName"] = new AttributeValue { S = "PGA Pro II" }; item["OrderStatus"] = new AttributeValue { S = "OUT FOR DELIVERY" }; item["ShipmentTrackingId"] = new AttributeValue { S = "383283" }; putItemRequest = new PutItemRequest { API Version 2012-08-10 416 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス TableName = tableName, Item = item, ReturnItemCollectionMetrics = "SIZE" }; client.PutItem(putItemRequest); } private static void WaitUntilTableReady(string tableName) { string status = null; // Let us wait until table is created. Call DescribeTable. do { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); status = res.Table.TableStatus; } catch (ResourceNotFoundException) { // DescribeTable is eventually consistent. So you might // get resource not found. So we handle the potential exception. } } while (status != "ACTIVE"); } private static void WaitForTableToBeDeleted(string tableName) { bool tablePresent = true; while (tablePresent) { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); } catch (ResourceNotFoundException) { tablePresent = false; } } } API Version 2012-08-10 417 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス } } ローカルセカンダリインデックス の操作 : PHP トピック • ローカルセカンダリインデックス を使用したテーブルの作成 (p. 418) • ローカルセカンダリインデックス のクエリ (p. 419) • 例: AWS SDK for PHP 低レベル API を使用した ローカルセカンダリインデックス (p. 420) AWS SDK for PHP 低レベル API を使用して、1 つ以上の local secondary index を持つテーブルを作 成し、テーブルのインデックスについて説明し、インデックスを使用してクエリを実行することがで きます。これらのオペレーションは、対応する DynamoDB API にマッピングされます。詳細について は、「PHP コードサンプル (p. 175)」を参照してください。 以下に、AWS SDK for PHP を使用したテーブルオペレーションの一般的な手順を示します。 1. DynamoDB クライアントのインスタンスを作成します。 2. オプションのパラメーターを含む DynamoDB オペレーションのパラメーターを指定します。 3. DynamoDB からの応答をアプリケーションのローカル変数にロードします。 ローカルセカンダリインデックス を使用したテーブルの作成 ローカルセカンダリインデックス は、テーブルの作成と同時に作成する必要があります。そのために は、CreateTable を使用して、1 つ以上の local secondary index の仕様を指定します。 次の PHP コードスニペットでは、音楽コレクション内の曲に関する情報を保存するテーブルを作成し ています。パーティションキーは Artist で、ソートキーは SongTitle です。セカンダリインデックスの AlbumTitleIndex は、アルバムのタイトルによるクエリを容易にします。インデックスに射影される属 性は、テーブルのパーティションキーおよびソートキーと、インデックスのソートキーだけです。 require 'vendor/autoload.php'; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'Music'; $result = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'Artist', 'AttributeType' => 'S' ], [ 'AttributeName' => 'SongTitle', 'AttributeType' => 'S' ], [ 'AttributeName' => 'AlbumTitle', 'AttributeType' => 'S' ] ], 'KeySchema' => [ [ 'AttributeName' => 'Artist', 'KeyType' => 'HASH' ], [ 'AttributeName' => 'SongTitle', 'KeyType' => 'RANGE' ] ], API Version 2012-08-10 418 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 'LocalSecondaryIndexes' => [ [ 'IndexName' => 'AlbumTitleIndex', 'KeySchema' => [ [ 'AttributeName' => 'Artist', 'KeyType' => 'HASH' ], [ 'AttributeName' => 'AlbumTitle', 'KeyType' => 'RANGE' ] ], 'Projection' => [ 'ProjectionType' => 'INCLUDE', 'NonKeyAttributes' => ['Genre', 'Year'] ] ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 5, 'WriteCapacityUnits' => 5 ] ]); DynamoDB がテーブルを作成し、テーブルのステータスを ACTIVE に設定するまで待機する必要があ ります。その後は、データ項目をテーブルに書き込むことが可能になります。 ローカルセカンダリインデックス のクエリ local secondary index では、テーブルの Query を実行するのと同様の方法で、Query オペレーション を使用できます。 インデックス名、インデックスソートキーのクエリ基準、および返されるようにす る属性を指定する必要があります。この例では、インデックスが AlbumTitleIndex で、インデックス ソートキーが AlbumTitle です。 返される属性は、インデックスに射影された属性だけです。このクエリを変更して非キー属性も選択 するように設定することもできますが、その場合は比較的コストがかかるテーブルフェッチアクティ ビティが必要になります。テーブルのフェッチの詳細については、「属性の射影 (p. 385)」を参照し てください。 $tableName='Music'; $response = $dynamodb->query([ 'TableName' => $tableName, 'IndexName' => 'AlbumTitleIndex', 'KeyConditionExpression' => 'Artist = :v_artist and AlbumTitle >= :v_title', 'ExpressionAttributeValues' => [ ':v_artist' => ['S' => 'Acme Band'], ':v_title' => ['S' => 'Songs About Life'] ], 'Select' => 'ALL_ATTRIBUTES' ]); echo "Acme Band's Songs About Life:\n"; foreach($response['Items'] as $item) { echo " - " . $item['SongTitle']['S'] . "\n"; } API Version 2012-08-10 419 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 例: AWS SDK for PHP 低レベル API を使用した ローカルセカンダリインデッ クス 次の PHP コード例では、local secondary index の操作方法を示します。この例では、パーティション キーとして CustomerId、ソートキーとして OrderId を使用して、CustomerOrders という名前のテー ブルが作成されます。このテーブルには次の 2 つの local secondary index があります。 • OrderCreationDateIndex — ソートキーは OrderCreationDate で、次の属性がインデックスに射影さ れます。 • ProductCategory • ProductName • OrderStatus • ShipmentTrackingId • IsOpenIndex — ソートキーは IsOpen で、すべてのテーブル属性がインデックスに射影されていま す。 CustomerOrders テーブルを作成すると、プログラムによってカスタマーの注文を表すデータがテー ブルにロードされ、local secondary index を使用してデータのクエリが行われます。最後に、プログ ラムによって CustomerOrders テーブルが削除されます。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'CustomerOrders'; echo "# Creating table $tableName...\n"; try { $response = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'CustomerId', 'AttributeType' => 'S' ], [ 'AttributeName' => 'OrderId', 'AttributeType' => 'N' ], [ 'AttributeName' => 'OrderCreationDate', 'AttributeType' => 'N' ], [ 'AttributeName' => 'IsOpen', 'AttributeType' => 'N' ] ], 'KeySchema' => [ [ 'AttributeName' => 'CustomerId', 'KeyType' => 'HASH' ], // Partition key [ 'AttributeName' => 'OrderId', 'KeyType' => 'RANGE' ] //Sort key ], 'LocalSecondaryIndexes' => [ [ 'IndexName' => 'OrderCreationDateIndex', API Version 2012-08-10 420 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 'KeySchema' => [ [ 'AttributeName' => 'CustomerId', 'KeyType' => 'HASH' ], //Partition key [ 'AttributeName' => 'OrderCreationDate', 'KeyType' => 'RANGE' ] //Sort key ], 'Projection' => [ 'ProjectionType' => 'INCLUDE', 'NonKeyAttributes' => ['ProductCategory', 'ProductName'] ] ], [ 'IndexName' => 'IsOpenIndex', 'KeySchema' => [ [ 'AttributeName' => 'CustomerId', 'KeyType' => 'HASH' ], //Partition key [ 'AttributeName' => 'IsOpen', 'KeyType' => 'RANGE' ] // Sort key ], 'Projection' => [ 'ProjectionType' => 'ALL' ] ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 5, 'WriteCapacityUnits' => 5 ] ]); echo " Waiting for table $tableName to be created.\n"; $dynamodb->waitUntil('TableExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] ]); echo " Table $tableName has been created.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to create table $tableName\n"); } ######################################### # Add items to the table echo "# Loading data into $tableName...\n"; $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '1'], 'IsOpen' => ['N' => '1'], 'OrderCreationDate' => ['N' => '20140101'], 'ProductCategory' => ['S' => 'Book'], 'ProductName' => ['S' => 'The Great Outdoors'], 'OrderStatus' => ['S' => 'PACKING ITEMS'] ] ]); API Version 2012-08-10 421 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '2'], 'IsOpen' => ['N' => '1'], 'OrderCreationDate' => ['N' => '20140221'], 'ProductCategory' => ['S' => 'Bike'], 'ProductName' => ['S' => 'Super Mountain'], 'OrderStatus' => ['S' => 'ORDER RECEIVED'] ] ]); $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '3'], // no IsOpen attribute 'OrderCreationDate' => ['N' => '20140304'], 'ProductCategory' => ['S' => 'Music'], 'ProductName' => ['S' => 'A Quiet Interlude'], 'OrderStatus' => ['S' => 'IN TRANSIT'], 'ShipmentTrackingId' => ['N' => '176493'] ] ]); $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '1'], // no IsOpen attribute 'OrderCreationDate' => ['N' => '20140111'], 'ProductCategory' => ['S' => 'Movie'], 'ProductName' => ['S' => 'Calm Before The Storm'], 'OrderStatus' => ['S' => 'SHIPPING DELAY'], 'ShipmentTrackingId' => ['N' => '859323'] ] ]); $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '2'], // no IsOpen attribute 'OrderCreationDate' => ['N' => '20140124'], 'ProductCategory' => ['S' => 'Music'], 'ProductName' => ['S' => 'E-Z Listening'], 'OrderStatus' => ['S' => 'DELIVERED'], 'ShipmentTrackingId' => ['N' => '756943'] ] ]); $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ API Version 2012-08-10 422 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '3'], // no IsOpen attribute 'OrderCreationDate' => ['N' => '20140221'], 'ProductCategory' => ['S' => 'Music'], 'ProductName' => ['S' => 'Symphony 9'], 'OrderStatus' => ['S' => 'DELIVERED'], 'ShipmentTrackingId' => ['N' => '645193'] ] ]); $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '4'], 'IsOpen' => ['N' => '1'], 'OrderCreationDate' => ['N' => '20140222'], 'ProductCategory' => ['S' => 'Hardware'], 'ProductName' => ['S' => 'Extra Heavy Hammer'], 'OrderStatus' => ['S' => 'PACKING ITEMS'] ] ]); $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '5'], // no IsOpen attribute 'OrderCreationDate' => ['N' => '20140309'], 'ProductCategory' => ['S' => 'Book'], 'ProductName' => ['S' => 'How To Cook'], 'OrderStatus' => ['S' => 'IN TRANSIT'], 'ShipmentTrackingId' => ['N' => '440185'] ] ]); $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '6'], // no IsOpen attribute 'OrderCreationDate' => ['N' => '20140318'], 'ProductCategory' => ['S' => 'Luggage'], 'ProductName' => ['S' => 'Really Big Suitcase'], 'OrderStatus' => ['S' => 'DELIVERED'], 'ShipmentTrackingId' => ['N' => '893927'] ] ]); $response = $dynamodb->putItem ( [ 'TableName' => $tableName, 'Item' => [ 'CustomerId' => ['S' => '[email protected]'], 'OrderId' => ['N' => '7'], // no IsOpen attribute 'OrderCreationDate' => ['N' => '20140324'], API Version 2012-08-10 423 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 'ProductCategory' => ['S' => 'Golf'], 'ProductName' => ['S' => 'PGA Pro II'], 'OrderStatus' => ['S' => 'OUT FOR DELIVERY'], 'ShipmentTrackingId' => ['N' => '383283'] ] ]); ######################################### # Query for Bob's 5 most recent orders in 2014, retrieving attributes which # are projected into the index $response = $dynamodb->query([ 'TableName' => $tableName, 'IndexName' => 'OrderCreationDateIndex', 'KeyConditionExpression' => 'CustomerId = :v_id and OrderCreationDate >= :v_dt', 'ExpressionAttributeValues' => [ ':v_id' => ['S' => '[email protected]'], ':v_dt' => ['N' => '20140101'] ], 'Select' => 'ALL_PROJECTED_ATTRIBUTES', 'ScanIndexForward' => false, 'ConsistentRead' => true, 'Limit' => 5, 'ReturnConsumedCapacity' => 'TOTAL' ]); echo "# Querying for Bob's 5 most recent orders in 2014:\n"; foreach($response['Items'] as $item) { echo ' - ' . $item['CustomerId']['S'] . ' ' . $item['OrderCreationDate']['N'] . ' ' . $item['ProductName']['S'] . ' ' . $item['ProductCategory']['S'] . "\n"; } echo ' Provisioned Throughput Consumed: ' . $response['ConsumedCapacity']['CapacityUnits'] . "\n"; ######################################### # Query for Bob's 5 most recent orders in 2014, retrieving some attributes # which are not projected into the index $response = $dynamodb->query([ 'TableName' => $tableName, 'IndexName' => 'OrderCreationDateIndex', 'KeyConditionExpression' => 'CustomerId = :v_id and OrderCreationDate >= :v_dt', 'ExpressionAttributeValues' => [ ':v_id' => ['S' => '[email protected]'], ':v_dt' => ['N' => '20140101'] ], 'Select' => 'SPECIFIC_ATTRIBUTES', 'ProjectionExpression' => 'CustomerId, OrderCreationDate, ProductName, ProductCategory, OrderStatus', 'ScanIndexForward' => false, 'ConsistentRead' => true, 'Limit' => 5, API Version 2012-08-10 424 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス 'ReturnConsumedCapacity' => 'TOTAL' ]); echo "# Querying for Bob's 5 most recent orders in 2014:" . "\n"; foreach($response['Items'] as $item) { echo ' - ' . $item['CustomerId']['S'] . ' ' . $item['OrderCreationDate']['N'] . ' ' . $item['ProductName']['S'] . ' ' . $item['ProductCategory']['S'] . ' ' . $item['OrderStatus']['S'] . "\n"; } echo ' Provisioned Throughput Consumed: ' . $response['ConsumedCapacity']['CapacityUnits'] . "\n"; ######################################### # Query for Alice's open orders, fetching all attributes # (which are already projected into the index) $response = $dynamodb->query([ 'TableName' => $tableName, 'IndexName' => 'IsOpenIndex', 'KeyConditionExpression' => 'CustomerId = :v_id', 'ExpressionAttributeValues' => [ ':v_id' => ['S' => '[email protected]'] ], 'Select' => 'ALL_ATTRIBUTES', 'ScanIndexForward' => false, 'ConsistentRead' => true, 'Limit' => 5, 'ReturnConsumedCapacity' => 'TOTAL' ]); echo "# Querying for Alice's open orders:" . "\n"; foreach($response['Items'] as $item) { echo ' - ' . $item['CustomerId']['S']. ' ' . $item['OrderCreationDate']['N'] . ' ' . $item['ProductName']['S'] . ' ' . $item['ProductCategory']['S'] . ' ' . $item['OrderStatus']['S'] . "\n"; } echo ' Provisioned Throughput Consumed: ' . $response['ConsumedCapacity']['CapacityUnits'] . "\n"; ######################################### # Delete the table try { $dynamodb->deleteTable(['TableName' => $tableName]); echo " Waiting for table $tableName to be deleted.\n"; $dynamodb->waitUntil('TableNotExists', [ 'TableName' => $tableName, '@waiter' => [ 'delay' => 5, 'maxAttempts' => 20 ] API Version 2012-08-10 425 Amazon DynamoDB 開発者ガイド ストリームの使用 ]); echo " Table $tableName has been deleted.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to delete table $tableName\n"); } ?> DynamoDB ストリーム を使用したテーブルアク ティビティのキャプチャ 多くのアプリケーションでは、DynamoDB テーブルに保存された項目の変更を、変更の発生時にキャ プチャできると役立ちます。ユースケースは次のとおりです。 • ある AWS リージョンのアプリケーションが、DynamoDB テーブルのデータを変更します。別の AWS リージョンの 2 番目のアプリケーションがそのデータ変更を読み込み、データを別のテーブ ルに書き込みます。このとき、元のテーブルと同期されたレプリカを作成します。 • 人気のモバイルアプリは、1 秒あたり数千件の更新速度で、DynamoDB テーブルのデータを変更し ます。別のアプリケーションは、これらの更新に関するデータをキャプチャして保存し、モバイル アプリの使用状況メトリクスをほぼリアルタイムで提供します。 • グローバルなマルチプレーヤーゲームには、データを複数の AWS リージョンに保存するマルチマ スタートポロジがあります。各マスターは、リモートリージョンで発生した変更を使用および再現 することにより同期されます。 • アプリケーションは、友人の 1 人が新しい画像をアップロードするとすぐに、グループ内のすべて の友人のモバイルデバイスに通知を自動送信します。 • 新しいお客様がデータを DynamoDB テーブルに追加します。このイベントにより、新しいお客様 にようこそメールを送信する別のアプリケーションが起動されます。 DynamoDB ストリーム では、このようなソリューションに加えて、他にも多くのソリューションを 実現できます。DynamoDB ストリーム は、DynamoDB テーブル内の項目レベルの変更の時系列シー ケンスをキャプチャし、この情報を最大 24 時間ログに保存します。アプリケーションは、このログ にアクセスし、データ項目の変更前および変更後の内容をほぼリアルタイムで参照できます。 DynamoDB ストリームは、Amazon DynamoDB テーブル内の項目に加えられた変更に関する情報の 順序付けされた情報です。テーブルでストリームを有効にすると、DynamoDB はテーブル内のデータ 項目に加えられた各変更に関する情報をキャプチャします。 アプリケーションがテーブル内の項目を作成、更新、または削除するたびに、DynamoDB ストリーム は変更された項目のプライマリキー属性を付けてストリームレコードを書き込みます。ストリームレ コードには、DynamoDB テーブル内の単一の項目に加えれたデータ変更についての情報が含まれてい ます。ストリームレコードが追加情報(変更された項目の前後のイメージ)をキャプチャするように ストリームを設定できます。 DynamoDB ストリーム では、以下の点が保証されます。 • 各ストリームレコードは、ストリームに 1 回だけ出現します。 • DynamoDB テーブルで変更された各項目について、ストリームレコードは項目に対する実際の変更 と同じ順序で出現します。 DynamoDB ストリーム は、ストリームレコードをほぼリアルタイムで書き込むため、これらのスト リームを使用し、内容に基づいてアクションを実行するアプリケーションを構築できます。 API Version 2012-08-10 426 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム におけるエンドポイント DynamoDB ストリーム におけるエンドポイント AWS では、DynamoDB と DynamoDB ストリーム に別個のエンドポイントが維持されます。データ ベースのテーブルとインデックスを使用するには、アプリケーションが DynamoDB エンドポイント にアクセスする必要があります。DynamoDB ストリーム レコードを読み込んで処理するには、アプ リケーションが同じリージョンの DynamoDB ストリーム エンドポイントにアクセスする必要があり ます。 DynamoDB ストリーム エンドポイントの命名規則は streams.dynamodb.<region>.amazonaws.com です。たとえば、エンドポイント dynamodb.uswest-2.amazonaws.com を使用して DynamoDB にアクセスする場合、エンドポイント streams.dynamodb.us-west-2.amazonaws.com を使用して DynamoDB ストリーム にアクセス する必要があります。 Note DynamoDB と DynamoDB ストリーム のリージョンおよびエンドポイントの詳細なリストに ついては、『AWS General Reference』の「リージョンとエンドポイント」を参照してくだ さい。 AWS SDK は、さまざまなクライアントに DynamoDB また DynamoDB ストリーム を提供します。要 件によっては、アプリケーションは、DynamoDB エンドポイント、DynamoDB ストリーム エンドポ イント、または両方に同時にアクセスできます。両エンドポイントに接続するには、アプリケーショ ンは、DynamoDB 用と DynamoDB ストリーム 用の 2 つのクライアントをインスタンス化する必要が あります。 API Version 2012-08-10 427 Amazon DynamoDB 開発者ガイド ストリームの有効化 ストリームの有効化 新しいテーブルでは、そのテーブルの作成時にストリームを有効にできます。既存のテーブルでスト リームを有効または無効にしたり、ストリームの設定を変更することもできます。DynamoDB スト リーム は非同期的に動作するため、ストリームを有効にしてもテーブルのパフォーマンスに影響は与 えません。 DynamoDB ストリーム を管理するには、AWS マネジメントコンソール を使用するのが最も簡単な方 法です。 1. 2. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 DynamoDB コンソールのダッシュボードから、[Tables] を選択します。 3. [Overview] タブで、[Manage Stream] を選択します。 4. [Manage Stream] ウィンドウで、テーブルのデータが変更されるたびにストリームに書き込まれ る情報を選択します。 • [Keys only] — 変更された項目のキー属性のみ。 • [New image] — 変更後に表示される項目全体。 • [Old image] — 変更前に表示されていた項目全体。 • [New and old images] — 項目の新しいイメージと古いイメージの両方。 5. すべての設定が正しいことを確認したら、[Enable] を選択します。 (オプション) 既存のストリームを無効にするには、[Manage Stream] を選択し、[Disable] を選択 します。 CreateTable または UpdateTable API を使用して、ストリームを有効にするか、変更することもで きます。ストリームの設定内容は、StreamSpecification パラメータにより決まります。 • StreamEnabled - テーブルでストリームが有効(true)か無効(false)かを指定します。 • StreamViewType - テーブル内のデータが変更されるたびにストリームに書き込まれる情報を指定 します。 • KEYS_ONLY - 変更された項目のキー属性のみ。 • NEW_IMAGE – 変更後に表示される項目全体。 • OLD_IMAGE – 変更前に表示されていた項目全体。 • NEW_AND_OLD_IMAGES - 項目の新しいイメージと古いイメージの両方。 ストリームはいつでも有効または無効にできます。ただし、既にストリームがあるテーブルでスト リームを有効にしようとした場合は ResourceInUseException を受け取り、ストリームのないテーブ ルでストリームを無効にしようとすると ValidationException を受け取る点に注意してください。 StreamEnabled を true に設定すると、一意のストリーム記述子が割り当てられた新しいストリー ムが DynamoDB により作成されます。テーブルでストリームを無効にして再度有効にすると、新し いストリームは異なるストリーム記述子で作成されます。 各ストリームは、Amazon リソースネーム(ARN)により一意に識別されます。TestTable という DynamoDB テーブルにあるストリームのサンプル ARN を次に示します。 arn:aws:dynamodb:us-west-2:111122223333:table/TestTable/ stream/2015-05-11T21:21:33.291 テーブルの最新のストリーム記述子を調べるには、DynamoDB DescribeTable リクエストを発行 し、レスポンスで LatestStreamArn 要素を探します。 API Version 2012-08-10 428 Amazon DynamoDB 開発者ガイド ストリームの読み込みと処理 ストリームの読み込みと処理 ストリームを読み込んで処理するには、アプリケーションが DynamoDB ストリーム エンドポイント に接続して API リクエストを発行する必要があります。 ストリームは、ストリームレコードで構成されています。各ストリームレコードは、ストリームが 属する DynamoDB テーブル内の 1 件のデータ変更を表しています。各ストリームレコードには、レ コードがストリームに発行された順序を反映したシーケンス番号が割り当てられます。 ストリームレコードは、グループ(つまり、シャード)に整理されます。各シャードは、複数のスト リームレコードのコンテナとして機能し、これらのレコードへのアクセスと反復処理に必要な情報が 含まれています。シャード内のストリームレコードは 24 時間後に自動的に削除されます。 シャードはエフェメラルであり、必要に応じて自動的に作成および削除されます。また、任意の シャードは複数の新しいシャードに分割できます。これもまた自動的に行われます (親シャードが 1 つの子シャードのみを持つ場合もあります)。アプリケーションが複数のシャードからレコードを並列 処理できるように、シャードは親テーブルで高レベルな書き込みアクティビティに応じて分割される 場合があります。 ストリームを無効にすると、開かれているシャードは閉じられます。 シャードには系列 (親と子) があるため、アプリケーションは子シャードを処理する前に、必ず親 シャードを処理する必要があります。これにより、ストリームレコードも正しい順序で処理されるよ うになります。DynamoDB ストリーム Kinesis Adapter を使用している場合、これは自動的に処理さ れます。アプリケーションは、シャードとストリームレコードを正しい順序で処理し、新しいシャー ド、期限切れのシャード、およびアプリケーションの実行中に分割されたシャードを自動的に処理し ます。詳細については、「DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの 処理 (p. 430)」を参照してください。 次の図は、ストリーム、ストリーム内のシャード、シャード内のストリームレコードの関係を示して います。 Note 項目内のデータを何も変更しないPutItemまたはUpdateItem オペレーションを実行した場 合、そのオペレーションのストリームレコードは DynamoDB ストリーム によって書き込ま れません。 API Version 2012-08-10 429 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 ストリームにアクセスしてその中のストリームレコードを処理するには、以下の操作を実行する必要 があります。 • アクセスするストリームの一意の Amazon リソースネーム(ARN)を調べます。 • 目的のストリームレコードがストリーム内のどのシャードに含まれているかを調べます。 • シャードにアクセスし、目的のストリームレコードを取得します。 Note 最大でも 2 つを超えるプロセスが、同時に同じストリームシャードから読み取りを行うこと はできません。シャードごとに 2 つを超えるリーダーがあると、スロットリングが発生する 場合があります。 DynamoDB ストリーム API は、アプリケーションプログラムが使用する次のアクションを提供しま す。 • ListStreams - 現在のアカウントおよびエンドポイントのストリーム記述子のリストを返します。 必要に応じて、特定のテーブル名のストリーム記述子だけをリクエストできます。 • DescribeStream - 特定のストリームに関する詳細情報を返します。出力には、ストリームに関連 付けられたシャードのリストが含まれています(シャード ID を含む)。 • GetShardIterator - シャード内の場所を表すシャードイテレーターを返します。イテレータがス トリーム内の最も古いポイント、最も新しいポイント、特定のポイントへのアクセスを提供するこ とをリクエストできます。 • GetRecords - 特定のシャード内からストリームレコードを返します。GetShardIterator リクエ ストから返されたシャードイテレーターを指定する必要があります。 リクエストやレスポンスの例など、これらの API アクションの詳細な説明については、「DynamoDB ストリーム API リファレンス」を参照してください。 DynamoDB ストリーム のデータ保持期限 DynamoDB ストリーム 内のすべてのデータは、24 時間保持されます。特定のテーブルの直近 24 時 間のアクティビティを取得して分析できますが、24 時間を超えたデータはすぐにトリミング(削除) される可能性があります。 テーブルのストリームを無効にした場合、ストリーム内のデータは 24 時間読み込み可能な状態にな ります。この時間が経過すると、データは期限切れになり、ストリームレコードは自動的に削除され ます。既存のストリームを手動で削除するためのメカニズムはないことに注意してください、保持期 限が切れて(24 時間)、すべてのストリームレコードが削除されるまで待つ必要があります。 DynamoDB ストリーム Kinesis Adapter を使用した ストリームレコードの処理 DynamoDB から Streams を消費するには、Kinesis Adapter の使用をお勧めします。 DynamoDB ストリーム API は、Amazon Kinesis Streams (大規模なストリーミングデータをリアル タイムで処理するためのサービス) の API と意図的に似たものになっています。 どちらのサービスで も、データストリームはシャード(ストリームレコードのコンテナ)で構成されています。どちらの サービスの API にも、ListStreams、DescribeStream、GetShards、GetShardIterator の各 アクションが含まれています(DynamoDB ストリーム のアクションは Amazon Kinesis Streams のア クションと似ていますが、100% 同じではありません。) Amazon Kinesis Streams のアプリケーションは、Amazon Kinesis Client Library (KCL) を使用して 記述できます。KCL は、低レベルの Amazon Kinesis Streams API の上で役に立つ抽象化を提供す API Version 2012-08-10 430 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 ることによりコーディングを簡素化します。KCL の詳細については、「Amazon Kinesis Developer Guide」を参照してください。 DynamoDB ストリーム ユーザーは、KCL 内で見つかった設計パターンを活用して、DynamoDB スト リーム のシャードとストリームレコードを活用できます。 これを行うには、DynamoDB ストリーム Kinesis Adapter を使用します。 DynamoDB ストリーム からのレコードの使用と処理に KCL を使用 できるように、Kinesis Adapter には Amazon Kinesis Streams インターフェイスが実装されます。 次の図に、これらのライブラリがどのように相互に作用するかを示します。 DynamoDB ストリーム Kinesis Adapter が用意されたら、DynamoDB ストリーム エンドポイントで シームレスに指示された API 呼び出しを行って、KCL インターフェイスを対象とした開発を開始でき ます。 アプリケーションは起動時に KCL を呼び出してワーカーをインスタンス化します。ワーカーには、 アプリケーションの設定情報(ストリームの記述子や AWS 認証情報など)と、お客様が指定したレ コードプロセッサクラス名を提供する必要があります。ワーカーは、コードをレコードプロセッサで 実行するため、以下のタスクを実行します。 API Version 2012-08-10 431 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 • ストリームに接続する. • ストリーム内のシャードを列挙します。 • シャードと他のワーカー(存在する場合)の関連付けを調整します。 • レコードプロセッサで管理する各シャードのレコードプロセッサをインスタンス化する. • ストリームからレコードを取得します。 • 対応するレコードプロセッサにレコードを送信する. • 処理されたレコードのチェックポイントを作成する. • ワーカーのインスタンス数が変化したときに、シャードとワーカーの関連付けを調整する. • シャードが分割されたときに、シャードとワーカーの関連付けを調整する. Note 上記の KCL の概念の説明については、『Amazon Kinesis Developer Guide』の「Amazon Kinesis クライアントライブラリを使用した Amazon Kinesis コンシューマーの開発」を参照 してください。 チュートリアル : DynamoDB ストリーム Kinesis Adapter このセクションは、Kinesis Client Library と DynamoDB ストリーム Kinesis Adapter を使用する Java アプリケーションのチュートリアルです。 アプリケーションには、データレプリケーションの例が表 示されます。データレプリケーションでは、1 つのテーブルからの書き込みアクティビティが 2 番目 のテーブルに適用され、両方のテーブルの内容が同期されます。ソースコードについては、「完成し たプログラム: DynamoDB ストリーム Kinesis Adapter (p. 435)」を参照してください。 このプログラムでは、次のような処理を実行します。 1. KCL-Demo-src と KCL-Demo-dst という 2 つの DynamoDB テーブルを作成します。これらの各 テーブルでは、ストリームが有効になっています。 2. 項目を追加、更新、削除することで、ソーステーブルで更新アクティビティを生成します。これに より、データがテーブルのストリームに書き込まれます。 3. ストリームからレコードを読み込んで、DynamoDB リクエストとして再構築し、ターゲットテーブ ルにリクエストを適用します。 4. ソーステーブルとターゲットテーブルをスキャンし、内容が同じであることを確認します。 5. テーブルを削除してクリーンアップします。 これらのステップについては次のセクションで説明します。完成したアプリケーションは、チュート リアルの最後に示します。 トピック • ステップ 1: DynamoDB テーブルを作成する (p. 432) • ステップ 2: ソーステーブルに更新アクティビティを生成する (p. 433) • ステップ 3: ストリームを処理する (p. 433) • ステップ 4: 両方のテーブルの内容が同じであることを確認する (p. 434) • ステップ 5: クリーンアップ (p. 435) • 完成したプログラム: DynamoDB ストリーム Kinesis Adapter (p. 435) ステップ 1: DynamoDB テーブルを作成する 最初のステップでは、2 つの DynamoDB テーブル(ソーステーブルとターゲットテーブル)を作成し ます。ソーステーブルのストリームにある StreamViewType は NEW_IMAGE です。これは、このテー API Version 2012-08-10 432 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 ブルで項目が変更されると必ず、イメージの "後の" 項目がストリームに書き込まれることを意味しま す。このようにして、ストリームはテーブル内のすべての書き込みアクティビティを記録します。 次のコードスニペットは、両方のテーブルを作成するためのコードを示しています。 java.util.List<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition().withAttributeName("Id").withAttributeType("N")); java.util.List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>(); keySchema.add(new KeySchemaElement().withAttributeName("Id").withKeyType(KeyType.HASH)); Partition key // ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput() .withReadCapacityUnits(2L).withWriteCapacityUnits(2L); StreamSpecification streamSpecification = new StreamSpecification(); streamSpecification.setStreamEnabled(true); streamSpecification.setStreamViewType(StreamViewType.NEW_IMAGE); CreateTableRequest createTableRequest = new CreateTableRequest() .withTableName(tableName) .withAttributeDefinitions(attributeDefinitions) .withKeySchema(keySchema) .withProvisionedThroughput(provisionedThroughput) .withStreamSpecification(streamSpecification); ステップ 2: ソーステーブルに更新アクティビティを生成する 次のステップでは、ソーステーブルにいくつかの書き込みアクティビティを生成します。このアク ティビティの実行中、ソーステーブルのストリームもほぼリアルタイムで更新されます。 アプリケーションは、データを書き込むための PutItem、UpdateItem、および DeleteItem API ア クションを呼び出すメソッドを持つヘルパークラスを定義します。次のコードスニペットは、これら のメソッドの使用方法を示しています。 StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, "101", "test1"); StreamsAdapterDemoHelper.updateItem(dynamoDBClient, tableName, "101", "test2"); StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, "101"); StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, "102", "demo3"); StreamsAdapterDemoHelper.updateItem(dynamoDBClient, tableName, "102", "demo4"); StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, "102"); ステップ 3: ストリームを処理する ここでは、プログラムがストリームの処理を開始します。DynamoDB ストリーム Kinesis Adapter は、コードが低レベルの DynamoDB ストリーム 呼び出しを行わなくても KCL を十分に活用できるよ うに、KCL と DynamoDB ストリーム エンドポイントの間の透過的なレイヤーとして機能します。 こ のプログラムでは次のタスクを実行しています。 API Version 2012-08-10 433 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 • KCL インターフェイス定義に従ったメソッド(initialize、processRecords、shutdown) を使用して、レコードプロセッサクラス StreamsRecordProcessor を定義しま す。processRecords メソッドには、ソーステーブルのストリームからの読み込みとターゲット テーブルへの書き込みに必要なロジックが含まれています。 • レコードプロセッサクラスのクラスファクトリを定義します (StreamsRecordProcessorFactory)。これは、KCL を使用する Java プログラムに必要で す。 • クラスファクトリに関連付けられた新しい KCL Worker をインスタンス化します。 • レコード処理が完了すると、Worker をシャットダウンします。 KCL インターフェイス定義の詳細については、『Amazon Kinesis Developer Guide』の「Amazon Kinesis クライアントライブラリを使用した Amazon Kinesis コンシューマーの開発」を参照してくだ さい。 次のコードスニペットは、StreamsRecordProcessor におけるメインループを示しています。case ステートメントは、ストリームレコードに出現する OperationType に基づいて、実行するアクショ ンを決定します。 for(Record record : records) { String data = new String(record.getData().array(), Charset.forName("UTF-8")); System.out.println(data); if(record instanceof RecordAdapter) { com.amazonaws.services.dynamodbv2.model.Record streamRecord = ((RecordAdapter) record).getInternalObject(); switch(streamRecord.getEventName()) { case "INSERT" : case "MODIFY" : StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, streamRecord.getDynamodb().getNewImage()); break; case "REMOVE" : StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, streamRecord.getDynamodb().getKeys().get("Id").getN()); } } checkpointCounter += 1; if(checkpointCounter % 10 == 0) { try { checkpointer.checkpoint(); } catch(Exception e) { e.printStackTrace(); } } } } ステップ 4: 両方のテーブルの内容が同じであることを確認する この時点で、ソーステーブルとターゲットテーブルの内容が同期されています。アプリケーション は、両方のテーブルに対して Scan リクエストを発行し、内容が実際に同じであることを確認しま す。 DemoHelper クラスには、低レベルのスキャン API を呼び出す ScanTable メソッドが含まれていま す。次のコードスニペットは、このクラスの使用方法を示しています。 API Version 2012-08-10 434 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 if(StreamsAdapterDemoHelper.scanTable(dynamoDBClient, srcTable).getItems().equals(StreamsAdapterDemoHelper.scanTable(dynamoDBClient, destTable).getItems())) { System.out.println("Scan result is equal."); } else { System.out.println("Tables are different!"); } ステップ 5: クリーンアップ デモは完了したため、アプリケーションによりソーステーブルとターゲットテーブルが削除されま す。次のコードスニペットを参照してください。 テーブルが削除されても、そのストリームは最大 24 時間使用可能です。その後、自動的に削除され ます。 dynamoDBClient.deleteTable(new DeleteTableRequest().withTableName(srcTable)); dynamoDBClient.deleteTable(new DeleteTableRequest().withTableName(destTable)); 完成したプログラム: DynamoDB ストリーム Kinesis Adapter このチュートリアルで説明したタスクを実行する、完成した Java プログラムを次に示します。実行 すると、次のような出力が表示されます。 Creating table KCL-Demo-src Creating table KCL-Demo-dest Table is active. Creating worker for stream: arn:aws:dynamodb:us-west-2:111122223333:table/ KCL-Demo-src/stream/2015-05-19T22:48:56.601 Starting worker... Scan result is equal. Done. Important このプログラムを実行するには、クライアントアプリケーションがポリシーを使用して DynamoDB および CloudWatch にアクセスできることを確認します。詳細については、 「Amazon DynamoDB でアイデンティティベースのポリシー (IAM ポリシー) を使用す る (p. 465)」を参照してください。 ソースコードは、4 つの .java ファイルから構成されています。 StreamsAdapterDemo.java // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.gsg; import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; API Version 2012-08-10 435 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.services.cloudwatch.AmazonCloudWatchClient; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest; import com.amazonaws.services.dynamodbv2.model.DescribeTableResult; import com.amazonaws.services.dynamodbv2.streamsadapter.AmazonDynamoDBStreamsAdapterClient; import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessorFactory; import com.amazonaws.services.kinesis.clientlibrary.lib.worker.InitialPositionInStream; import com.amazonaws.services.kinesis.clientlibrary.lib.worker.KinesisClientLibConfiguration; import com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker; public class StreamsAdapterDemo { private static Worker worker; private static KinesisClientLibConfiguration workerConfig; private static IRecordProcessorFactory recordProcessorFactory; private static AmazonDynamoDBStreamsAdapterClient adapterClient; private static AWSCredentialsProvider streamsCredentials; private static AmazonDynamoDBClient dynamoDBClient; private static AWSCredentialsProvider dynamoDBCredentials; private static AmazonCloudWatchClient cloudWatchClient; private private private private private static static static static static String String String String String serviceName = "dynamodb"; dynamodbEndpoint = "DYNAMODB_ENDPOINT_GOES_HERE"; streamsEndpoint = "STREAMS_ENDPOINT_GOES_HERE"; tablePrefix = "KCL-Demo"; streamArn; /** * @param args */ public static void main(String[] args) throws Exception { System.out.println("Starting demo..."); String srcTable = tablePrefix + "-src"; String destTable = tablePrefix + "-dest"; streamsCredentials = new ProfileCredentialsProvider(); dynamoDBCredentials = new ProfileCredentialsProvider(); recordProcessorFactory = new StreamsRecordProcessorFactory(dynamoDBCredentials, dynamodbEndpoint, serviceName, destTable); /* ===== REQUIRED ===== * Users will have to explicitly instantiate and configure the adapter, then pass it to * the KCL worker. */ adapterClient = new AmazonDynamoDBStreamsAdapterClient(streamsCredentials, new ClientConfiguration()); adapterClient.setEndpoint(streamsEndpoint); API Version 2012-08-10 436 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 dynamoDBClient = new AmazonDynamoDBClient(dynamoDBCredentials, new ClientConfiguration()); dynamoDBClient.setEndpoint(dynamodbEndpoint); cloudWatchClient = new AmazonCloudWatchClient(dynamoDBCredentials, new ClientConfiguration()); setUpTables(); workerConfig = new KinesisClientLibConfiguration("streams-adapterdemo", streamArn, streamsCredentials, "streams-demo-worker") .withMaxRecords(1000) .withIdleTimeBetweenReadsInMillis(500) .withInitialPositionInStream(InitialPositionInStream.TRIM_HORIZON); System.out.println("Creating worker for stream: " + streamArn); worker = new Worker(recordProcessorFactory, workerConfig, adapterClient, dynamoDBClient, cloudWatchClient); System.out.println("Starting worker..."); Thread t = new Thread(worker); t.start(); Thread.sleep(25000); worker.shutdown(); t.join(); if(StreamsAdapterDemoHelper.scanTable(dynamoDBClient, srcTable).getItems().equals(StreamsAdapterDemoHelper.scanTable(dynamoDBClient, destTable).getItems())) { System.out.println("Scan result is equal."); } else { System.out.println("Tables are different!"); } System.out.println("Done."); cleanupAndExit(0); } private static void setUpTables() { String srcTable = tablePrefix + "-src"; String destTable = tablePrefix + "-dest"; streamArn = StreamsAdapterDemoHelper.createTable(dynamoDBClient, srcTable); StreamsAdapterDemoHelper.createTable(dynamoDBClient, destTable); awaitTableCreation(srcTable); performOps(srcTable); } private static void awaitTableCreation(String tableName) { Integer retries = 0; Boolean created = false; while(!created && retries < 100) { DescribeTableResult result = StreamsAdapterDemoHelper.describeTable(dynamoDBClient, tableName); API Version 2012-08-10 437 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 created = result.getTable().getTableStatus().equals("ACTIVE"); if (created) { System.out.println("Table is active."); return; } else { retries++; try { Thread.sleep(1000); } catch(InterruptedException e) { // do nothing } } } System.out.println("Timeout after table creation. Exiting..."); cleanupAndExit(1); } private static void performOps(String tableName) { StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, "101", "test1"); StreamsAdapterDemoHelper.updateItem(dynamoDBClient, tableName, "101", "test2"); StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, "101"); StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, "102", "demo3"); StreamsAdapterDemoHelper.updateItem(dynamoDBClient, tableName, "102", "demo4"); StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, "102"); } private static void cleanupAndExit(Integer returnValue) { String srcTable = tablePrefix + "-src"; String destTable = tablePrefix + "-dest"; dynamoDBClient.deleteTable(new DeleteTableRequest().withTableName(srcTable)); dynamoDBClient.deleteTable(new DeleteTableRequest().withTableName(destTable)); System.exit(returnValue); } } StreamsRecordProcessor.java // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.gsg; import java.nio.charset.Charset; import java.util.List; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import com.amazonaws.services.dynamodbv2.streamsadapter.model.RecordAdapter; import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessor; API Version 2012-08-10 438 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessorCheckpointer; import com.amazonaws.services.kinesis.clientlibrary.types.ShutdownReason; import com.amazonaws.services.kinesis.model.Record; public class StreamsRecordProcessor implements IRecordProcessor { private Integer checkpointCounter; private final AmazonDynamoDBClient dynamoDBClient; private final String tableName; public StreamsRecordProcessor(AmazonDynamoDBClient dynamoDBClient, String tableName) { this.dynamoDBClient = dynamoDBClient; this.tableName = tableName; } @Override public void initialize(String shardId) { checkpointCounter = 0; } @Override public void processRecords(List<Record> records, IRecordProcessorCheckpointer checkpointer) { for(Record record : records) { String data = new String(record.getData().array(), Charset.forName("UTF-8")); System.out.println(data); if(record instanceof RecordAdapter) { com.amazonaws.services.dynamodbv2.model.Record streamRecord = ((RecordAdapter) record).getInternalObject(); switch(streamRecord.getEventName()) { case "INSERT" : case "MODIFY" : StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, streamRecord.getDynamodb().getNewImage()); break; case "REMOVE" : StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, streamRecord.getDynamodb().getKeys().get("Id").getN()); } } checkpointCounter += 1; if(checkpointCounter % 10 == 0) { try { checkpointer.checkpoint(); } catch(Exception e) { e.printStackTrace(); } } } } @Override public void shutdown(IRecordProcessorCheckpointer checkpointer, ShutdownReason reason) { API Version 2012-08-10 439 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 if(reason == ShutdownReason.TERMINATE) { try { checkpointer.checkpoint(); } catch (Exception e) { e.printStackTrace(); } } } } StreamsRecordProcessorFactory.java // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.gsg; import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessor; import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessorFactory; public class StreamsRecordProcessorFactory implements IRecordProcessorFactory { private final AWSCredentialsProvider dynamoDBCredentials; private final String dynamoDBEndpoint; private final String tableName; public StreamsRecordProcessorFactory( AWSCredentialsProvider dynamoDBCredentials, String dynamoDBEndpoint, String serviceName, String tableName) { this.dynamoDBCredentials = dynamoDBCredentials; this.dynamoDBEndpoint = dynamoDBEndpoint; this.tableName = tableName; } @Override public IRecordProcessor createProcessor() { AmazonDynamoDBClient dynamoDBClient = new AmazonDynamoDBClient(dynamoDBCredentials, new ClientConfiguration()); dynamoDBClient.setEndpoint(dynamoDBEndpoint); return new StreamsRecordProcessor(dynamoDBClient, tableName); } } StreamsAdapterDemoHelper.java // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. API Version 2012-08-10 440 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 package com.amazonaws.codesamples.gsg; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import import import import import import import import import import import import import import import import import import import import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.model.AttributeAction; com.amazonaws.services.dynamodbv2.model.AttributeDefinition; com.amazonaws.services.dynamodbv2.model.AttributeValue; com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate; com.amazonaws.services.dynamodbv2.model.CreateTableRequest; com.amazonaws.services.dynamodbv2.model.CreateTableResult; com.amazonaws.services.dynamodbv2.model.DeleteItemRequest; com.amazonaws.services.dynamodbv2.model.DescribeTableRequest; com.amazonaws.services.dynamodbv2.model.DescribeTableResult; com.amazonaws.services.dynamodbv2.model.KeySchemaElement; com.amazonaws.services.dynamodbv2.model.KeyType; com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; com.amazonaws.services.dynamodbv2.model.PutItemRequest; com.amazonaws.services.dynamodbv2.model.ResourceInUseException; com.amazonaws.services.dynamodbv2.model.ScanRequest; com.amazonaws.services.dynamodbv2.model.ScanResult; com.amazonaws.services.dynamodbv2.model.StreamSpecification; com.amazonaws.services.dynamodbv2.model.StreamViewType; com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; public class StreamsAdapterDemoHelper { /** * @return StreamArn */ public static String createTable(AmazonDynamoDBClient client, String tableName) { java.util.List<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition().withAttributeName("Id").withAttributeType("N")); java.util.List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>(); keySchema.add(new KeySchemaElement().withAttributeName("Id").withKeyType(KeyType.HASH)); // Partition key ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput() .withReadCapacityUnits(2L).withWriteCapacityUnits(2L); StreamSpecification streamSpecification = new StreamSpecification(); streamSpecification.setStreamEnabled(true); streamSpecification.setStreamViewType(StreamViewType.NEW_IMAGE); CreateTableRequest createTableRequest = new CreateTableRequest() .withTableName(tableName) .withAttributeDefinitions(attributeDefinitions) .withKeySchema(keySchema) .withProvisionedThroughput(provisionedThroughput) .withStreamSpecification(streamSpecification); API Version 2012-08-10 441 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム Kinesis Adapter を使用したストリームレコードの処理 try { System.out.println("Creating table " + tableName); CreateTableResult result = client.createTable(createTableRequest); return result.getTableDescription().getLatestStreamArn(); } catch(ResourceInUseException e) { System.out.println("Table already exists."); return describeTable(client, tableName).getTable().getLatestStreamArn(); } } public static DescribeTableResult describeTable(AmazonDynamoDBClient client, String tableName) { return client.describeTable(new DescribeTableRequest().withTableName(tableName)); } public static ScanResult scanTable(AmazonDynamoDBClient client, String tableName) { return client.scan(new ScanRequest().withTableName(tableName)); } public static void putItem(AmazonDynamoDBClient client, String tableName, String id, String val) { java.util.Map<String, AttributeValue> item = new HashMap<String, AttributeValue>(); item.put("Id", new AttributeValue().withN(id)); item.put("attribute-1", new AttributeValue().withS(val)); PutItemRequest putItemRequest = new PutItemRequest() .withTableName(tableName) .withItem(item); client.putItem(putItemRequest); } public static void putItem(AmazonDynamoDBClient client, String tableName, java.util.Map<String, AttributeValue> items) { PutItemRequest putItemRequest = new PutItemRequest() .withTableName(tableName) .withItem(items); client.putItem(putItemRequest); } public static void updateItem(AmazonDynamoDBClient client, String tableName, String id, String val) { java.util.Map<String, AttributeValue> key = new HashMap<String, AttributeValue>(); key.put("Id", new AttributeValue().withN(id)); Map<String, AttributeValueUpdate> attributeUpdates = new HashMap<String, AttributeValueUpdate>(); AttributeValueUpdate update = new AttributeValueUpdate() .withAction(AttributeAction.PUT) .withValue(new AttributeValue().withS(val)); attributeUpdates.put("attribute-2", update); UpdateItemRequest updateItemRequest = new UpdateItemRequest() API Version 2012-08-10 442 Amazon DynamoDB 開発者ガイド チュートリアル : DynamoDB ス トリーム の低レベルの API .withTableName(tableName) .withKey(key) .withAttributeUpdates(attributeUpdates); client.updateItem(updateItemRequest); } public static void deleteItem(AmazonDynamoDBClient client, String tableName, String id) { java.util.Map<String, AttributeValue> key = new HashMap<String, AttributeValue>(); key.put("Id", new AttributeValue().withN(id)); DeleteItemRequest deleteItemRequest = new DeleteItemRequest() .withTableName(tableName) .withKey(key); client.deleteItem(deleteItemRequest); } } チュートリアル : DynamoDB ストリーム の低レベ ルの API このセクションは、動作中の DynamoDB ストリーム を示す Java プログラムのチュートリア ルです。 ソースコードについては、「完成したプログラム: 低レベルの DynamoDB ストリーム API (p. 446)」を参照してください。 このプログラムでは、次のような処理を実行します。 1. ストリームが有効になった DynamoDB テーブルを作成します。 2. このテーブルのストリーム設定を記述します。 3. テーブル内のデータを変更します。 4. ストリーム内のシャードを記述します。 5. シャードからストリームレコードを読み込みます。 6. クリーンアップ. Note このコードではすべての例外は処理されず、高トラフィックの条件下では確実に動作しませ ん。DynamoDB からストリームレコードを使用する推奨の方法は、「DynamoDB ストリー ム Kinesis Adapter を使用したストリームレコードの処理 (p. 430)」で説明しているよう に、Amazon Kinesis Client Library (KCL) を使用し、Kinesis Adapter を介して行うことです。 これらのステップについては次のセクションで説明します。完成したアプリケーションは、チュート リアルの最後に示します。 トピック • ステップ 1: ストリームが有効になったテーブルを作成する (p. 444) • ステップ 2: テーブルのストリーム設定を記述する (p. 444) • ステップ 3: テーブル内のデータを変更する (p. 445) • ステップ 4: ストリーム内のシャードを記述する (p. 445) • ステップ 5: ストリーム レコードを読み込む (p. 445) API Version 2012-08-10 443 Amazon DynamoDB 開発者ガイド チュートリアル : DynamoDB ス トリーム の低レベルの API • ステップ 6: クリーンアップ (p. 446) • 完成したプログラム: 低レベルの DynamoDB ストリーム API (p. 446) ステップ 1: ストリームが有効になったテーブルを作成する 最初のステップでは、次のコードスニペットに示すように、DynamoDB にテーブルを作成し ます。テーブルではストリームが有効になっています。ストリームは、変更された各項目の NEW_AND_OLD_IMAGES をキャプチャします。 ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("Id") .withAttributeType("N")); ArrayList<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>(); keySchema.add(new KeySchemaElement() .withAttributeName("Id") .withKeyType(KeyType.HASH)); //Partition key StreamSpecification streamSpecification = new StreamSpecification(); streamSpecification.setStreamEnabled(true); streamSpecification.setStreamViewType(StreamViewType.NEW_AND_OLD_IMAGES); CreateTableRequest createTableRequest = new CreateTableRequest() .withTableName(tableName) .withKeySchema(keySchema) .withAttributeDefinitions(attributeDefinitions) .withProvisionedThroughput(new ProvisionedThroughput() .withReadCapacityUnits(1L) .withWriteCapacityUnits(1L)) .withStreamSpecification(streamSpecification); ステップ 2: テーブルのストリーム設定を記述する DescribeTable API を使用すると、テーブルの現在のストリーム設定を表示することができます。 次のコードスニペットは、ストリームが有効になっていることと、適切なデータがキャプチャされる ことを確認するのに役立ちます。 DescribeTableResult describeTableResult = dynamoDBClient.describeTable(tableName); String myStreamArn = describeTableResult.getTable().getLatestStreamArn(); StreamSpecification myStreamSpec = describeTableResult.getTable().getStreamSpecification(); System.out.println("Current stream ARN for " + tableName + ": "+ myStreamArn); System.out.println("Stream enabled: "+ myStreamSpec.getStreamEnabled()); System.out.println("Update view type: "+ myStreamSpec.getStreamViewType()); API Version 2012-08-10 444 Amazon DynamoDB 開発者ガイド チュートリアル : DynamoDB ス トリーム の低レベルの API ステップ 3: テーブル内のデータを変更する 次のステップでは、テーブル内のデータにいくつかの変更を加えます。次のコードスニペットは、 テーブルに新しい項目を追加して、その項目の属性を更新し、項目を削除します。 // Add a new item int numChanges = 0; System.out.println("Making some changes to table data"); Map<String, AttributeValue> item = new HashMap<String, AttributeValue>(); item.put("Id", new AttributeValue().withN("101")); item.put("Message", new AttributeValue().withS("New item!")); dynamoDBClient.putItem(tableName, item); numChanges++; // Update the item Map<String, AttributeValue> key = new HashMap<String, AttributeValue>(); key.put("Id", new AttributeValue().withN("101")); Map<String, AttributeValueUpdate> attributeUpdates = new HashMap<String, AttributeValueUpdate>(); attributeUpdates.put("Message", new AttributeValueUpdate() .withAction(AttributeAction.PUT) .withValue(new AttributeValue().withS("This item has changed"))); dynamoDBClient.updateItem(tableName, key, attributeUpdates); numChanges++; // Delete the item dynamoDBClient.deleteItem(tableName, key); numChanges++; ステップ 4: ストリーム内のシャードを記述する テーブル内のデータを変更すると、ストリームレコードがテーブルのストリームに書き込まれます。 「 ステップ 2: テーブルのストリーム設定を記述する (p. 444)」では、現在のストリーム ARN を 調べ、それを変数 myStreamArn に割り当てました。これを DescribeStream アクションで使用する と、ストリーム内のシャードを取得できます。 DynamoDB テーブル内のデータを大きく変更したわけではないため、リストにはシャードが 1 つしか ありません。次のコードスニペットは、この情報を取得する方法を示しています。 DescribeStreamResult describeStreamResult = streamsClient.describeStream(new DescribeStreamRequest() .withStreamArn(myStreamArn)); String streamArn = describeStreamResult.getStreamDescription().getStreamArn(); List<Shard> shards = describeStreamResult.getStreamDescription().getShards(); ステップ 5: ストリーム レコードを読み込む リスト内のシャードごとに、シャードイテレーターを取得し、そのイテレーターを使用することでス トリームレコードを取得して印刷します。 API Version 2012-08-10 445 Amazon DynamoDB 開発者ガイド チュートリアル : DynamoDB ス トリーム の低レベルの API 次のコードスニペットは、シャード 1 つしかない場合でもループを使用してシャードリストを処理し ます。 for (Shard shard : shards) { String shardId = shard.getShardId(); System.out.println( "Processing " + shardId + " from stream "+ streamArn); // Get an iterator for the current shard GetShardIteratorRequest getShardIteratorRequest = new GetShardIteratorRequest() .withStreamArn(myStreamArn) .withShardId(shardId) .withShardIteratorType(ShardIteratorType.TRIM_HORIZON); GetShardIteratorResult getShardIteratorResult = streamsClient.getShardIterator(getShardIteratorRequest); String nextItr = getShardIteratorResult.getShardIterator(); while (nextItr != null && numChanges > 0) { // Use the iterator to read the data records from the shard GetRecordsResult getRecordsResult = streamsClient.getRecords(new GetRecordsRequest(). withShardIterator(nextItr)); List<Record> records = getRecordsResult.getRecords(); System.out.println("Getting records..."); for (Record record : records) { System.out.println(record); numChanges--; } nextItr = getRecordsResult.getNextShardIterator(); } } ステップ 6: クリーンアップ デモが完了したため、テーブルを削除できます。テーブルが削除されても、このテーブルに関連付け られたストリームは引き続き読み込み可能である点に注意してください。ストリームは 24 時間後に 自動的に削除されます。 dynamoDBClient.deleteTable(tableName); 完成したプログラム: 低レベルの DynamoDB ストリーム API このチュートリアルで説明したタスクを実行する、完成した Java プログラムを次に示します。実行 すると、各ストリームレコードがすべて表示されます。 Issuing CreateTable request for TestTableForStreams Waiting for TestTableForStreams to be created... Current stream ARN for TestTableForStreams: arn:aws:dynamodb:uswest-2:111122223333:table/TestTableForStreams/stream/2015-05-19T23:03:50.641 Stream enabled: true Update view type: NEW_AND_OLD_IMAGES Making some changes to table data API Version 2012-08-10 446 Amazon DynamoDB 開発者ガイド チュートリアル : DynamoDB ス トリーム の低レベルの API Processing shardId-00000001415575208348-98d954b6 from stream arn:aws:dynamodb:us-west-2:111122223333:table/TestTableForStreams/ stream/2015-05-19T23:03:50.641 Getting records... {eventID: 7f6ba6f037b9fdd5a43af22cb726f0cd,eventName: INSERT,eventVersion: 1.0,eventSource: aws:dynamodb,awsRegion: us-west-2,dynamodb: {Keys: {Id={N: 101,}},NewImage: {Message={S: New item!,}, Id={N: 101,}},SequenceNumber: 100000000000000507337,SizeBytes: 26,StreamViewType: NEW_AND_OLD_IMAGES}} {eventID: 8f546e78ab6183d1441c0680ec03dcfc,eventName: MODIFY,eventVersion: 1.0,eventSource: aws:dynamodb,awsRegion: us-west-2,dynamodb: {Keys: {Id={N: 101,}},NewImage: {Message={S: This item has changed,}, Id={N: 101,}},OldImage: {Message={S: New item!,}, Id={N: 101,}},SequenceNumber: 200000000000000507338,SizeBytes: 59,StreamViewType: NEW_AND_OLD_IMAGES}} {eventID: d9bb1e7a1684dfd66c8a3fb8ca2f6977,eventName: REMOVE,eventVersion: 1.0,eventSource: aws:dynamodb,awsRegion: us-west-2,dynamodb: {Keys: {Id={N: 101,}},OldImage: {Message={S: This item has changed,}, Id={N: 101,}},SequenceNumber: 300000000000000507339,SizeBytes: 38,StreamViewType: NEW_AND_OLD_IMAGES}} Deleting the table... Demo complete // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples.gsg; import import import import java.util.ArrayList; java.util.HashMap; java.util.List; java.util.Map; import import import import import import import import import import import import import import import import import import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.AmazonDynamoDBStreamsClient; com.amazonaws.services.dynamodbv2.model.AttributeAction; com.amazonaws.services.dynamodbv2.model.AttributeDefinition; com.amazonaws.services.dynamodbv2.model.AttributeValue; com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate; com.amazonaws.services.dynamodbv2.model.CreateTableRequest; com.amazonaws.services.dynamodbv2.model.DescribeStreamRequest; com.amazonaws.services.dynamodbv2.model.DescribeStreamResult; com.amazonaws.services.dynamodbv2.model.DescribeTableResult; com.amazonaws.services.dynamodbv2.model.GetRecordsRequest; com.amazonaws.services.dynamodbv2.model.GetRecordsResult; com.amazonaws.services.dynamodbv2.model.GetShardIteratorRequest; com.amazonaws.services.dynamodbv2.model.GetShardIteratorResult; com.amazonaws.services.dynamodbv2.model.KeySchemaElement; com.amazonaws.services.dynamodbv2.model.KeyType; com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; com.amazonaws.services.dynamodbv2.model.Record; com.amazonaws.services.dynamodbv2.model.Shard; com.amazonaws.services.dynamodbv2.model.ShardIteratorType; com.amazonaws.services.dynamodbv2.model.StreamSpecification; com.amazonaws.services.dynamodbv2.model.StreamViewType; com.amazonaws.services.dynamodbv2.util.Tables; public class StreamsLowLevelDemo { API Version 2012-08-10 447 Amazon DynamoDB 開発者ガイド チュートリアル : DynamoDB ス トリーム の低レベルの API private static AmazonDynamoDBClient dynamoDBClient = new AmazonDynamoDBClient(new ProfileCredentialsProvider()); private static AmazonDynamoDBStreamsClient streamsClient = new AmazonDynamoDBStreamsClient(new ProfileCredentialsProvider()); public static void main(String args[]) { dynamoDBClient.setEndpoint("DYNAMODB_ENDPOINT_GOES_HERE"); streamsClient.setEndpoint("STREAMS_ENDPOINT_GOES_HERE"); // Create the table String tableName = "TestTableForStreams"; ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition() .withAttributeName("Id") .withAttributeType("N")); ArrayList<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>(); keySchema.add(new KeySchemaElement() .withAttributeName("Id") .withKeyType(KeyType.HASH)); //Partition key StreamSpecification streamSpecification = new StreamSpecification(); streamSpecification.setStreamEnabled(true); streamSpecification.setStreamViewType(StreamViewType.NEW_AND_OLD_IMAGES); CreateTableRequest createTableRequest = new CreateTableRequest() .withTableName(tableName) .withKeySchema(keySchema) .withAttributeDefinitions(attributeDefinitions) .withProvisionedThroughput(new ProvisionedThroughput() .withReadCapacityUnits(1L) .withWriteCapacityUnits(1L)) .withStreamSpecification(streamSpecification); System.out.println("Issuing CreateTable request for " + tableName); dynamoDBClient.createTable(createTableRequest); System.out.println("Waiting for " + tableName + " to be created..."); try { Tables.awaitTableToBecomeActive(dynamoDBClient, tableName); } catch (InterruptedException e) { e.printStackTrace(); } // Determine the Streams settings for the table DescribeTableResult describeTableResult = dynamoDBClient.describeTable(tableName); String myStreamArn = describeTableResult.getTable().getLatestStreamArn(); API Version 2012-08-10 448 Amazon DynamoDB 開発者ガイド チュートリアル : DynamoDB ス トリーム の低レベルの API StreamSpecification myStreamSpec = describeTableResult.getTable().getStreamSpecification(); System.out.println("Current stream ARN for " + tableName + ": "+ myStreamArn); System.out.println("Stream enabled: "+ myStreamSpec.getStreamEnabled()); System.out.println("Update view type: "+ myStreamSpec.getStreamViewType()); // Add a new item int numChanges = 0; System.out.println("Making some changes to table data"); Map<String, AttributeValue> item = new HashMap<String, AttributeValue>(); item.put("Id", new AttributeValue().withN("101")); item.put("Message", new AttributeValue().withS("New item!")); dynamoDBClient.putItem(tableName, item); numChanges++; // Update the item Map<String, AttributeValue> key = new HashMap<String, AttributeValue>(); key.put("Id", new AttributeValue().withN("101")); Map<String, AttributeValueUpdate> attributeUpdates = new HashMap<String, AttributeValueUpdate>(); attributeUpdates.put("Message", new AttributeValueUpdate() .withAction(AttributeAction.PUT) .withValue(new AttributeValue().withS("This item has changed"))); dynamoDBClient.updateItem(tableName, key, attributeUpdates); numChanges++; // Delete the item dynamoDBClient.deleteItem(tableName, key); numChanges++; // Get the shards in the stream DescribeStreamResult describeStreamResult = streamsClient.describeStream(new DescribeStreamRequest() .withStreamArn(myStreamArn)); String streamArn = describeStreamResult.getStreamDescription().getStreamArn(); List<Shard> shards = describeStreamResult.getStreamDescription().getShards(); // Process each shard for (Shard shard : shards) { String shardId = shard.getShardId(); System.out.println( "Processing " + shardId + " from stream "+ streamArn); // Get an iterator for the current shard API Version 2012-08-10 449 Amazon DynamoDB 開発者ガイド クロスリージョン レプリケーション GetShardIteratorRequest getShardIteratorRequest = new GetShardIteratorRequest() .withStreamArn(myStreamArn) .withShardId(shardId) .withShardIteratorType(ShardIteratorType.TRIM_HORIZON); GetShardIteratorResult getShardIteratorResult = streamsClient.getShardIterator(getShardIteratorRequest); String nextItr = getShardIteratorResult.getShardIterator(); while (nextItr != null && numChanges > 0) { // Use the iterator to read the data records from the shard GetRecordsResult getRecordsResult = streamsClient.getRecords(new GetRecordsRequest(). withShardIterator(nextItr)); List<Record> records = getRecordsResult.getRecords(); System.out.println("Getting records..."); for (Record record : records) { System.out.println(record); numChanges--; } nextItr = getRecordsResult.getNextShardIterator(); } // Delete the table System.out.println("Deleting the table..."); dynamoDBClient.deleteTable(tableName); System.out.println("Demo complete"); } } } クロスリージョン レプリケーション Important AWS では、以前は AWS CloudFormation に基づいてクロスリージョンのレプリケーションソ リューションを提供していました。このソリューションは、オープンソースのコマンドライ ンツールを優先して廃止されています。詳細については、GitHub で詳細な手順を参照してく ださい。 • https://github.com/awslabs/dynamodb-cross-region-library/blob/master/README.md DynamoDB のクロスリージョンレプリケーションソリューションでは、Amazon DynamoDB のクロ スリージョンレプリケーションライブラリが使用されます。このライブラリは、DynamoDB ストリー ム を使用して、複数のリージョンにまたがる DynamoDB テーブルをほぼリアルタイムで同期しま す。 あるリージョンの DynamoDB テーブルに書き込みを行うと、クロスリージョンレプリケーショ ンライブラリによりその変更が他のリージョンのテーブルに自動的に反映されます。 お客様のアプリケーションでクロスリージョンレプリケーションライブラリを使用して、DynamoDB ストリーム による独自のレプリケーションソリューションを構築することができます。 詳細について とソースコードのダウンロードについてには、次の GitHub リポジトリを参照してください。 • https://github.com/awslabs/dynamodb-cross-region-library API Version 2012-08-10 450 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム と AWS Lambda のトリガー DynamoDB ストリーム と AWS Lambda のトリ ガー トピック • チュートリアル: DynamoDB テーブルの新しい項目の処理 (p. 451) • ベストプラクティス (p. 458) Amazon DynamoDB は AWS Lambda と統合されているため、トリガー (DynamoDB ストリーム 内の イベントに自動的に応答するコード) を作成できます。トリガーを使用すると、DynamoDB テーブル 内のデータ変更に対応するアプリケーションを構築できます。 テーブルで DynamoDB ストリーム を有効にした場合、書き込む Lambda 関数にストリーム ARN を 関連付けることができます。 テーブルの項目が変更されるとすぐに、新しいレコードがテーブルのス トリームに表示されます。AWS Lambda はストリームをポーリングし、新しいストリームレコードを 検出すると Lambda 関数を同期的に呼び出します。 Lambda 関数は、通知の送信やワークフローの開始など、指定したアクションを実行できます。 たとえば、Lambda 関数を記述すると、各ストリームレコードを Amazon Simple Storage Service (Amazon S3) などの永続的ストレージにコピーしたり、書き込みアクティビティの永続的な監査証跡 をテーブルに作成したりすることが簡単にできます。または、GameScores テーブルに書き込みを行 うモバイルゲームアプリがあるとします。GameScores テーブルの TopScore 属性が更新されるたび に、対応するストリームレコードがテーブルのストリームに書き込まれます。その後、このイベント によって Lambda 関数をトリガーし、ソーシャルメディアネットワークにおめでとうメッセージを投 稿できます (この関数は、GameScores の更新でないストリームレコードや、TopScore 属性を変更 しないストリームレコードを無視します)。 AWS Lambda の詳細については、「AWS Lambda Developer Guide」を参照してください。 チュートリアル: DynamoDB テーブルの新しい項目の処理 トピック • ステップ 1: ストリームが有効になった DynamoDB テーブルを作成する (p. 452) • ステップ 2: Lambda 実行ロールを作成する (p. 452) • ステップ 3: Amazon SNS トピックを作成する (p. 454) • ステップ 4: Lambda 関数を作成してテストする (p. 454) • ステップ 5: トリガーを作成してテストする (p. 457) このチュートリアルでは、AWS Lambda トリガーを作成して、DynamoDB テーブルからのストリー ムを処理します。 このチュートリアルのシナリオは、シンプルなソーシャルネットワークである Woofer です。Woofer ユーザーは、他の Woofer ユーザーに送信される bark (短いテキストメッセージ) を使用して通信しま す。次の図は、このアプリケーションのコンポーネントとワークフローを示しています。 1. ユーザーは DynamoDB テーブル (BarkTable) に項目を書き込みます。テーブルの各項目は bark を 表します。 2. 新しいストリームレコードが書き込まれ、新しい項目が BarkTable に追加されたことを反映しま す。 3. 新しいストリームレコードは AWS Lambda 関数 (publishNewBark) をトリガーします。 4. ストリームレコードに、新しい項目が BarkTable に追加されたことが示された場合、Lambda 関数 はストリームレコードからデータを読み取り、Amazon Simple Notification Service (Amazon SNS) のトピックにメッセージを発行します。 API Version 2012-08-10 451 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム と AWS Lambda のトリガー 5. メッセージは Amazon SNS トピックの受信者によって受信されます (このチュートリアルでは、唯 一の受信者は E メールアドレスです)。 開始する前に このチュートリアルでは AWS Command Line Interface を使用します。まだ行っていない場合は、 「AWS Command Line Interface ユーザーガイド」の手順に従って AWS CLI をインストールおよび設 定します。 ステップ 1: ストリームが有効になった DynamoDB テーブルを作成する このステップでは、Woofer ユーザーからのすべての bark を保存する DynamoDB テーブル (BarkTable) を作成します。プライマリキーは Username (パーティションキー) と Timestamp (ソート キー) で構成されます。これらの属性は両方とも文字列型になります。 BarkTable ではストリームが有効になります。このチュートリアルの後半では、AWS Lambda 関数を ストリームと関連付けてトリガーを作成します。 1. 次のコマンドを入力してテーブルを作成します。 aws dynamodb create-table \ --table-name BarkTable \ --attribute-definitions AttributeName=Username,AttributeType=S AttributeName=Timestamp,AttributeType=S \ --key-schema AttributeName=Username,KeyType=HASH AttributeName=Timestamp,KeyType=RANGE \ --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \ --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES 2. 出力で、LatestStreamArn を探します。 ... "LatestStreamArn": "arn:aws:dynamodb:region:acccountID:table/BarkTable/ stream/timestamp ... region と accountID をメモしておきます。これらは、このチュートリアルの他のステップで必 要になります。 ステップ 2: Lambda 実行ロールを作成する このステップでは、IAMロール (WooferLambdaRole) を作成し、それにアクセス権限を割り当て ます。このロールは、「ステップ 4: Lambda 関数を作成してテストする (p. 454)」で作成する Lambda 関数で使用されます。 また、ロールのポリシーを作成します。このポリシーには、Lambda 関数が実行時に必要とするすべ てのアクセス権限が含まれます。 1. 次の内容で、trust-relationship.json というファイルを作成します。 { "Version": "2012-10-17", "Statement": [ API Version 2012-08-10 452 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム と AWS Lambda のトリガー { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } 2. 次のコマンドを入力して WooferLambdaRole を作成します。 aws iam create-role --role-name WooferLambdaRole \ --path "/service-role/" \ --assume-role-policy-document file://trust-relationship.json 3. 次の内容で、role-policy.json というファイルを作成します (region および accountID を AWS リージョンとアカウント ID に置き換えます)。 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:region:accountID:function:publishNewBark*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:region:accountID:*" }, { "Effect": "Allow", "Action": [ "dynamodb:DescribeStream", "dynamodb:GetRecords", "dynamodb:GetShardIterator", "dynamodb:ListStreams" ], "Resource": "arn:aws:dynamodb:region:accountID:table/ BarkTable/stream/*" }, { "Effect": "Allow", "Action": [ "sns:Publish" ], "Resource": [ "*" ] API Version 2012-08-10 453 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム と AWS Lambda のトリガー } ] } ポリシーには 4 つのステートメントがあり、これにより WooferLambdaRole は以下を実行するこ とができます。 • Lambda 関数 (publishNewBark) を実行する。このチュートリアルの後半で、この関数を作成し ます。 • CloudWatch Logs にアクセスする。Lambda 関数は実行時に診断を CloudWatch Logs に書き込 みます。 • BarkTable の DynamoDB ストリームからデータを読み取る。 • Amazon SNS にメッセージを発行する。 4. 次のコマンドを入力して、WooferLambdaRole にポリシーをアタッチします。 aws iam put-role-policy --role-name WooferLambdaRole \ --policy-name WooferLambdaRolePolicy \ --policy-document file://role-policy.json ステップ 3: Amazon SNS トピックを作成する このステップでは、Amazon SNS トピック (wooferTopic) を作成し、そのトピックに E メールアドレ スを受信登録します。Lambda 関数はこのトピックを使用して、Woofer ユーザーからの新しい bark を公開します。 1. 次のコマンドを入力して、新しい Amazon SNS トピックを作成します。 aws sns create-topic --name wooferTopic 2. 次のコマンドを入力して、wooferTopic に E メールアドレスを受信登録します (region および accountID は AWS リージョンとアカウント ID に置き換え、[email protected] は有効な E メールアドレスと置き換えます)。 aws sns subscribe \ --topic-arn arn:aws:sns:region:accountID:wooferTopic \ --protocol email \ --notification-endpoint [email protected] 3. Amazon SNS は E メールアドレスに確認メッセージを送信します。そのメッセージの [Confirm subscription] リンクをクリックして、受信登録プロセスを完了します。 ステップ 4: Lambda 関数を作成してテストする このステップでは、AWS Lambda 関数 (publishNewBark) を作成して BarkTable からのストリームレ コードを処理します。 publishNewBark 関数は、BarkTable の新しい項目に対応するストリームイベントのみを処理します。 この関数は、そのようなイベントからデータを読み取ってから、Amazon SNS を呼び出してデータを 公開します。 1. 次の内容で、publishNewBark.js というファイルを作成します (region および accountID を AWS リージョンとアカウント ID に置き換えます)。 API Version 2012-08-10 454 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム と AWS Lambda のトリガー 'use strict'; var AWS = require("aws-sdk"); var sns = new AWS.SNS(); exports.handler = (event, context, callback) => { event.Records.forEach((record) => { console.log('Stream record: ', JSON.stringify(record, null, 2)); if (record.eventName == 'INSERT') { var who = JSON.stringify(record.dynamodb.NewImage.Username.S); var when = JSON.stringify(record.dynamodb.NewImage.Timestamp.S); var what = JSON.stringify(record.dynamodb.NewImage.Message.S); var params = { Subject: 'A new bark from ' + who, Message: 'Woofer user ' + who + ' barked the following at ' + when + ':\n\n ' + what, TopicArn: 'arn:aws:sns:region:accountID:wooferTopic' }; sns.publish(params, function(err, data) { if (err) { console.error("Unable to send message. Error JSON:", JSON.stringify(err, null, 2)); callback(err, null); } else { console.log("Results from sending message: ", JSON.stringify(data, null, 2)); callback(null, data); } }); } }); callback(null, `Successfully processed ${event.Records.length} records.`); }; 2. publishNewBark.js を含める zip ファイルを作成します。zip コマンドラインユーティリティが ある場合は、次のコマンドを入力してこれを行うことができます。 zip publishNewBark.zip publishNewBark.js 3. Lambda 関数を作成するときに、「ステップ 2: Lambda 実行ロールを作成する (p. 452)」で作 成した WooferLambdaRole の ARN を指定する必要があります。この ARN を取得するには、次 のコマンドを入力します。 aws iam get-role --role-name WooferLambdaRole 出力で、WooferLambdaRole の ARN を探します。 ... "Arn": "arn:aws:iam::region:role/service-role/WooferLambdaRole" ... API Version 2012-08-10 455 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム と AWS Lambda のトリガー ここで、次のコマンドを入力して Lambda 関数を作成します (roleARN を WooferLambdaRole の ARN に置き換えます)。 aws lambda create-function \ --region us-east-1 \ --function-name publishNewBark \ --zip-file fileb://publishNewBark.zip \ --role roleARN \ --handler publishNewBark.handler \ --timeout 5 \ --runtime nodejs4.3 4. ここで、publishNewBark をテストして、これが動作することを確認します。これを行うに は、DynamoDB ストリーム の地域レコードに似た情報を入力します。 次の内容で、payload.json というファイルを作成します。 { "Records": [ { "eventID": "7de3041dd709b024af6f29e4fa13d34c", "eventName": "INSERT", "eventVersion": "1.1", "eventSource": "aws:dynamodb", "awsRegion": "us-west-2", "dynamodb": { "ApproximateCreationDateTime": 1479499740, "Keys": { "Timestamp": { "S": "2016-11-18:12:09:36" }, "Username": { "S": "John Doe" } }, "NewImage": { "Timestamp": { "S": "2016-11-18:12:09:36" }, "Message": { "S": "This is a bark from the Woofer social network" }, "Username": { "S": "John Doe" } }, "SequenceNumber": "13021600000000001596893679", "SizeBytes": 112, "StreamViewType": "NEW_IMAGE" }, "eventSourceARN": "arn:aws:dynamodb:useast-1:123456789012:table/BarkTable/stream/2016-11-16T20:42:48.104" } ] } API Version 2012-08-10 456 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム と AWS Lambda のトリガー publishNewBark 関数をテストするには、次のコマンドを入力します。 aws lambda invoke --function-name publishNewBark --payload file:// payload.json output.txt テストが成功すると、次の出力が表示されます。 { "StatusCode": 200 } さらに、output.txt ファイルには次のテキストが含まれます。 "Successfully processed 1 records." また、数分以内に新しい E メールメッセージが届きます。 Note AWS Lambda は診断情報を Amazon CloudWatch Logs に書き込みます。Lambda 関数で エラーが発生した場合、この診断情報をトラブルシューティングに使用できます。 1. https://console.aws.amazon.com/cloudwatch/にある CloudWatch コンソールを開きま す。 2. ナビゲーションペインで [Logs] を選択します。 3. 次のロググループを選択: /aws/lambda/publishNewBark 4. 最新のログストリーミングを選択して、関数からの出力 (およびエラー) を表示しま す。 ステップ 5: トリガーを作成してテストする 「ステップ 4: Lambda 関数を作成してテストする (p. 454)」で、Lambda 関数をテストして、正し く実行されたことを確認しました。このステップでは、Lambda 関数 (publishNewBark) をイベント ソース (BarkTable ストリーム) に関連付けて、トリガーを作成します。 1. トリガーを作成するときは、BarkTable ストリーム用の ARN を指定する必要があります。この ARN を取得するには、次のコマンドを入力します。 aws dynamodb describe-table --table-name BarkTable 出力で、LatestStreamArn を探します。 ... "LatestStreamArn": "arn:aws:dynamodb:region:acccountID:table/BarkTable/ stream/timestamp ... 2. 次のコマンドを入力してトリガーを作成します (streamARN を l ストリーム ARN に置き換えま す)。 aws lambda create-event-source-mapping \ API Version 2012-08-10 457 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム と AWS Lambda のトリガー --region us-east-1 \ --function-name publishNewBark \ --event-source streamARN \ --batch-size 1 \ --starting-position TRIM_HORIZON 3. ここで、トリガーをテストします。次のコマンドを入力して、BarkTable に項目を追加します。 aws dynamodb put-item \ --table-name BarkTable \ --item Username={S="Jane Doe"},Timestamp={S="2016-11-18:14:32:17"},Message={S="Testing...1...2...3"} 数分以内に新しい E メールメッセージが届きます。 4. DynamoDB コンソールに移動し、さらにいくつかの項目を BarkTable に追加します。Username および Timestamp 属性の値を指定する必要があります (必須ではないものの、Message の値を 指定する必要があります)。BarkTable に追加した各項目について、新しい E メールメッセージが 届きます。 Lambda 関数は、BarkTable に追加した新しい項目のみを処理します。テーブル内の項目を更新 または削除すると、この関数は何も行いません。 Note AWS Lambda は診断情報を Amazon CloudWatch Logs に書き込みます。Lambda 関数でエ ラーが発生した場合、この診断情報をトラブルシューティングに使用できます。 1. https://console.aws.amazon.com/cloudwatch/にある CloudWatch コンソールを開きます。 2. ナビゲーションペインで [Logs] を選択します。 3. 次のロググループを選択: /aws/lambda/publishNewBark 4. 最新のログストリーミングを選択して、関数からの出力 (およびエラー) を表示します。 ベストプラクティス AWS Lambda 関数はコンテナ内で実行されます。これは他の関数から分離された実行環境です。この 関数を初めて実行すると、AWS Lambda は新しいコンテナを作成し、関数のコードを実行し始めま す。 Lambda 関数には、呼び出しごとに 1 回実行されるハンドラがあります。ハンドラには、関数用の 主要なビジネスロジックが含まれます。たとえば、「ステップ 4: Lambda 関数を作成してテストす る (p. 454)」に示す Lambda 関数には、DynamoDB ストリームのレコードを処理できるハンドラが あります。 コンテナの作成後に 1 回のみ実行される初期化コードを提供することもできますが、AWS Lambda がハンドラを初めて実行する前のみです。「ステップ 4: Lambda 関数を作成してテストす る (p. 454)」に示す Lambda 関数には、Node.js 内の SDK for JavaScript をインポートし、Amazon SNS 用のクライアントを作成する初期化コードがあります。これらのオブジェクトはハンドラの外部 で 1 回のみ定義します。 関数の実行後、AWS Lambda は関数のそれ以降の呼び出しに対してコンテナを再利用する場合があり ます。この場合、関数ハンドラは、初期化コードで定義したリソースを再利用できる可能性がありま す (AWS Lambda がコンテナを保持する期間や、コンテナを再利用するかどうかを制御することはで きません)。 AWS Lambda を使用した DynamoDB トリガーの場合は、次のことをお勧めします。 API Version 2012-08-10 458 Amazon DynamoDB 開発者ガイド DynamoDB ストリーム と AWS Lambda のトリガー • AWS のサービスのクライアントは、ハンドラではなく初期化コードでインスタンス化する必要があ ります。これにより、AWS Lambda コンテナは、コンテナの有効期間中は既存の接続を再利用する ことができます。 • 通常、お客様が明示的に接続を管理したり、接続プールを実装したりする必要はありません。これ は AWS Lambda によって自動的に管理されます。 詳細については、AWS Lambda Developer Guideの「AWS Lambda 関数を使用する際のベストプラク ティス」を参照してください。 API Version 2012-08-10 459 Amazon DynamoDB 開発者ガイド 認証 Amazon DynamoDB に対する認証 とアクセスコントロール Amazon DynamoDB へのアクセスには、認証情報が必要です。これらの認証情報には、Amazon DynamoDB table や Amazon Elastic Compute Cloud (Amazon EC2) インスタンスなどの AWS リソー スに対するアクセス権限が含まれている必要があります。次のセクションでは、AWS Identity and Access Management (IAM) と DynamoDB を使用して、リソースへのアクセスをセキュリティで保護 する方法について詳しく説明します。 • 認証 (p. 460) • アクセスコントロール (p. 461) 認証 AWS には、次のタイプのアイデンティティでアクセスできます。 • AWS アカウントのルートユーザー – AWS にサインアップするときは、AWS アカウントに関連付 けられた E メールアドレスとパスワードを指定します。これらは ルート認証情報であり、これらの 情報を使用すると、すべての AWS リソースへの完全なアクセスが可能になります。 Important セキュリティ上の理由から、AWS アカウントへの完全なアクセス権限を持つ管理者ユー ザー (IAM ユーザー) を作成するためにのみ、ルート認証情報を使用することをお勧めし ます。その後、この管理者ユーザーを使用して、制限されたアクセス権限を持つ他の IAM ユーザーとロールを作成できます。詳細については、『IAM ユーザーガイド』の「IAM の ベストプラクティス」および「管理者のユーザーおよびグループの作成」を参照してくだ さい。 • IAM ユーザー – IAM ユーザーは、特定のカスタム権限 (たとえば、DynamoDB で a table を作成す るアクセス権限) を持つ AWS アカウント内のアイデンティティです。IAM のユーザー名とパスワー ドを使用して、AWS マネジメントコンソール、AWS ディスカッションフォーラム、AWS Support Center などのセキュリティ保護された AWS ウェブページにサインインできます。 ユーザー名とパスワードに加えて、各ユーザーのアクセスキーを生成することもできます。いくつ かの SDK の 1 つまたは AWS Command Line Interface (CLI) を使ってプログラムで AWS サービス にアクセスするときに、これらのキーを使用します。SDK と CLI ツールでは、アクセスキーを使用 してリクエストが暗号で署名されます。AWS ツールを使用しない場合は、リクエストを自分で署名 API Version 2012-08-10 460 Amazon DynamoDB 開発者ガイド アクセスコントロール する必要があります。DynamoDB supports では、署名バージョン 4 がサポートされています。こ れは、インバウンド API リクエストを認証するためのプロトコルです。リクエストの認証の詳細に ついては、『AWS General Reference』の「署名バージョン 4 の署名プロセス」を参照してくださ い。 • IAM ロール – IAM ロールは、特定のアクセス権限を持ち、アカウントで作成できるもう 1 つの IAM アイデンティティです。これは IAM ユーザーに似ていますが、特定のユーザーに関連付けられてい ません。IAM ロールでは、AWS サービスおよびリソースにアクセスするために使用できる一時的な アクセスキーを取得することができます。IAM ロールと一時的な認証情報は、次の状況で役立ちま す。 • フェデレーティッドユーザーアクセス – IAM ユーザーを作成するのではなく、AWS Directory Service、エンタープライズユーザーディレクトリ、またはウェブアイデンティティプロバイダー の既存のユーザーアイデンティティを使用することもできます。このようなユーザーはフェデ レーティッドユーザーと呼ばれます。AWS では、アイデンティティプロバイダーを通じてアク セスがリクエストされたときに、フェデレーティッドユーザーにロールを割り当てます。フェデ レーティッドユーザーの詳細については、『IAM ユーザーガイド』の「フェデレーティッドユー ザーとロール」を参照してください。 • クロスアカウントアクセス – アカウントで IAM ロールを使って、お客様のアカウントのリソース へのアクセス権を別の AWS アカウントに付与できます。この例については、『IAM ユーザーガ イド』の「チュートリアル: AWS アカウント間の IAM ロールを使用したアクセスの委任」を参照 してください。 • AWS サービスアカウント – アカウントで IAM ロールを使って、お客様のアカウントのリソース にアクセスする AWS サービスのアクセス権限を付与できます。たとえば、Amazon Redshift が お客様に代わって Amazon S3 バケットにアクセスし、バケットに保存されたデータを Amazon Redshift クラスターにロードすることを許可するロールを作成できます。 詳細については、 『IAM ユーザーガイド』の「AWS ユーザーにアクセス権限を委任するロールの作成」を参照して ください。 • Amazon EC2 で実行されるアプリケーション – インスタンスで実行し、AWS API リクエストを 作成するアプリケーションで使用されるアクセスキーを EC2 インスタンス内に保存する代わり に、IAM ロールを使用して、これらのアプリケーション用の一時認証情報を管理できます。AWS ロールを EC2 インスタンスに割り当て、そのすべてのアプリケーションで使用できるようにする には、インスタンスにアタッチされたインスタンスプロファイルを作成できます。インスタンス プロファイルにはロールが含まれ、EC2 インスタンスで実行されるプログラムは一時認証情報を 取得することができます。詳細については、『IAM ユーザーガイド』の「Amazon EC2 上のアプ リケーションに対するロールの使用」を参照してください。 アクセスコントロール 有効な認証情報があればリクエストを認証できますが、許可を持っていないかぎり Amazon DynamoDB リソースの作成やアクセスはできません。たとえば、Amazon DynamoDB table を作成す るためのアクセス権限が必要です。 以下のセクションでは、Amazon DynamoDB のアクセス権限を管理する方法について説明します。最 初に概要のセクションを読むことをお勧めします。 API Version 2012-08-10 461 Amazon DynamoDB 開発者ガイド アクセス管理の概要 • アクセス管理の概要 (p. 462) • アイデンティティベースのポリシー (IAM ポリシー) を使用する (p. 465) • DynamoDB API の権限リファレンス (p. 473) • 条件の使用 (p. 477) Amazon DynamoDB リソースへのアクセス権限 の管理の概要 すべての AWS リソースは AWS アカウントによって所有され、となり、リソースの作成またはアク セスは、アクセス権限のポリシーによって管理されます。アカウント管理者は、アクセス権限ポリ シーを IAM アイデンティティ (ユーザー、グループ、ロール) にアタッチできます。一部のサービス (AWS Lambda など) では、アクセス権限ポリシーをリソースにアタッチすることもできます。 Note アカウント管理者 (または管理者ユーザー) は、管理者権限を持つユーザーです。詳細につい ては、IAM ユーザーガイド の「IAM のベストプラクティス」を参照してください。 アクセス権限を付与する場合、アクセス権限を取得するユーザー、取得するアクセス権限の対象とな るリソース、およびそれらのリソースに対して許可される特定のアクションを決定します。 トピック • Amazon DynamoDB リソースおよびオペレーション (p. 462) • リソース所有権について (p. 463) • リソースへのアクセスの管理 (p. 463) • ポリシー要素の指定 : アクション、効果、プリンシパル (p. 464) • ポリシーでの条件の指定 (p. 465) Amazon DynamoDB リソースおよびオペレーション DynamoDB では、プライマリ リソースはテーブルです。DynamoDB では、追加リソースタイプとし てインデックスとストリームもサポートされています。ただし、既存の DynamoDB テーブルのコン テキストでのみ、インデックスやストリームを作成できます。これらはサブリソースと呼ばれます。 これらのリソースとサブリソースには、次の表に示すとおり、一意の Amazon リソースネーム (ARN) が関連付けられています。 リソースタイプ ARN 形式 表 arn:aws:dynamodb:region:account-id:table/table-name 索引 arn:aws:dynamodb:region:account-id:table/table-name/ index/index-name ストリーム arn:aws:dynamodb:region:account-id:table/table-name/ stream/stream-label DynamoDB には、DynamoDB リソースを操作するための一連のオペレーションが用意されていま す。可能なオペレーションのリストについては、Amazon DynamoDB Actions を参照してください。 API Version 2012-08-10 462 Amazon DynamoDB 開発者ガイド リソース所有権について リソース所有権について AWS アカウントは、誰がリソースを作成したかにかかわらず、アカウントで作成されたリソースを所 有します。 具体的には、リソース所有者は、リソースの作成リクエストを認証するプリンシパルエン ティティ (ルートアカウント、IAM ユーザー、または IAM ロール) の AWS アカウントです。以下の例 では、このしくみを示しています。 • AWS アカウントのルートアカウント認証情報を使用して a table を作成する場合、この AWS アカ ウントがリソースの所有者です (DynamoDB では、リソースは a table です)。 • AWS アカウントに IAM ユーザーを作成し、そのユーザーに a table を作成するためのアクセス権 限を付与する場合、そのユーザーは a table リソースを作成できます。ただし、ユーザーが属する AWS アカウントは table リソースを所有しています。 • a table リソースを作成するためのアクセス権限を持つ AWS アカウントに IAM ロールを作成する場 合は、ロールを引き受けることのできるいずれのユーザーも a table を作成できます。ユーザーが属 する AWS アカウントは table リソースを所有しています。 リソースへのアクセスの管理 アクセスポリシーでは、誰が何にアクセスできるかを記述します。以下のセクションで、アクセス権 限のポリシーを作成するために使用可能なオプションについて説明します。 Note このセクションでは、DynamoDB のコンテキストでの IAM の使用について説明します。こ れは、IAM サービスに関する詳細情報を取得できません。完全な IAM ドキュメントについて は、「IAM とは?」 (IAM ユーザーガイド ) を参照してください。IAM ポリシー構文の詳細お よび説明については、IAM ユーザーガイド の「AWS IAM ポリシーリファレンス」を参照して ください。 IAM アイデンティティにアタッチされたポリシーはアイデンティティベースのポリシー (IAM ポ リシー) と呼ばれ、リソースにアタッチされたポリシーはリソースベースのポリシーと呼ばれま す。DynamoDB では、アイデンティティベースのポリシー (IAM ポリシー) のみサポートされます。 トピック • アイデンティティベースのポリシー (IAM ポリシー) (p. 463) • リソースベースのポリシー (p. 464) アイデンティティベースのポリシー (IAM ポリシー) ポリシーを IAM アイデンティティにアタッチできます。たとえば、次の操作を実行できます。 • アカウントのユーザーまたはグループにアクセス権限ポリシーをアタッチする – a table などの Amazon DynamoDB リソースを作成するためのアクセス権限を付与するには、ユーザーまたはユー ザーが所属するグループにアクセス権限ポリシーをアタッチできます。 • アクセス権限ポリシーをロールにアタッチする (クロスアカウントのアクセス権限を付与) – アイデ ンティティベースのアクセス権限ポリシーを IAM ロールにアタッチして、クロスアカウントのアク セス権限を付与することができます。たとえば、アカウント A の管理者は、次のように他のまたは AWS にクロスアカウントのアクセス権限を別の AWS アカウント (アカウント B) または AWS サー ビスに付与するロールを作成することができます。 1. アカウント A の管理者は、IAM ロールを作成して、アカウント A のリソースに権限を付与する ロールに権限ポリシーをアタッチします。 2. アカウント A の管理者は、アカウント B をそのロールを引き受けるプリンシパルとして識別する ロールに、信頼ポリシーをアタッチします。 API Version 2012-08-10 463 Amazon DynamoDB 開発者ガイド ポリシー要素の指定 : アクション、効果、プリンシパル 3. アカウント B の管理者は、アカウント B のユーザーにロールを引き受ける権限を委任できるよう になります。これにより、アカウント B のユーザーにアカウント A のリソースの作成とアクセス が許可されます。AWS サービスのアクセス権限を付与してロールを引き受けさせたい場合は、 信頼ポリシー内のプリンシパルも、AWS サービスのプリンシパルとなることができます。 IAM を使用したアクセス権限の委任の詳細については、「アクセス管理」 (IAM ユーザーガイド) を 参照してください。 DynamoDB アクション (dynamodb:ListTables) に許可を付与するポリシーの例を次に示しま す。Resource 値のワイルドカード文字 (*) は、このアクションを使用して、現在の AWS リージョン の AWS アカウントで所有されているすべてのテーブルの名前を取得できることを意味します。 { "Version": "2012-10-17", "Statement": [ { "Sid": "ListTables", "Effect": "Allow", "Action": [ "dynamodb:ListTables" ], "Resource": "*" } ] } DynamoDB でアイデンティティベースのポリシーを使用する詳細については、「Amazon DynamoDB でアイデンティティベースのポリシー (IAM ポリシー) を使用する (p. 465)」を参照してください。 ユーザー、グループ、ロール、アクセス権限の詳細については、「アイデンティティ (ユーザー、グ ループ、ロール)」 (IAM ユーザーガイド) を参照してください。 リソースベースのポリシー Amazon S3 などの他のサービスでは、リソースベースのアクセス権限ポリシーもサポートされていま す。たとえば、ポリシーを S3 バケットにアタッチして、そのバケットに対するアクセス権限を管理 できます。DynamoDB では、リソースベースのポリシーはサポートされていません。 ポリシー要素の指定 : アクション、効果、プリンシ パル DynamoDB リソースの種類ごとに、このサービスは、一連の API オペレーションを定義します。これ らの API オペレーションのアクセス権限を付与するために、DynamoDB は、ポリシー内に指定できる 一連のアクションを定義します。一部の API オペレーションは、API オペレーションを実行するため に複数のアクションに対するアクセス許可を要求できます。 リソースおよび API オペレーションの詳 細については、「Amazon DynamoDB リソースおよびオペレーション (p. 462)」および DynamoDB Actions を参照してください。 以下は、最も基本的なポリシーの要素です。 • リソース – Amazon Resource Name (ARN) を使用して、ポリシーを適用するリソースを識別しま す。詳細については、「Amazon DynamoDB リソースおよびオペレーション (p. 462)」を参照し てください。 • アクション – アクションのキーワードを使用して、許可または拒否するリソースオペレーショ ンを識別します。たとえば、dynamodb:Query を allows the user permissions to perform the DynamoDB Query operation に使用できます。 API Version 2012-08-10 464 Amazon DynamoDB 開発者ガイド ポリシーでの条件の指定 • 効果 – ユーザーが特定のアクションをリクエストする際の効果を指定します。許可または拒否のい ずれかになります。リソースへのアクセスを明示的に許可していない場合、アクセスは暗黙的に拒 否されます。また、明示的にリソースへのアクセスを拒否すると、別のポリシーによってアクセス が許可されている場合でも、ユーザーはそのリソースにアクセスできなくなります。 • プリンシパル – アイデンティティベースのポリシー (IAM ポリシー) で、ポリシーがアタッチされて いるユーザーが黙示的なプリンシパルとなります。リソースベースのポリシーでは、権限 (リソース ベースのポリシーにのみ適用) を受け取りたいユーザー、アカウント、サービス、またはその他のエ ンティティを指定します。DynamoDB doesn't support リソースベースのポリシー。 IAM ポリシーの構文と説明についての詳細については、IAM ユーザーガイド の「AWS IAM ポリシー の参照」を参照してください。 すべての Amazon DynamoDB API オペレーションとそれらが適用されるリソースのリストについて は、「DynamoDB API のアクセス権限: アクション、リソース、条件リファレンス (p. 473)」を参照 してください。 ポリシーでの条件の指定 アクセス権限を付与するとき、アクセスポリシー言語を使用して、ポリシーが有効になる必要がある 条件を指定できます。たとえば、特定の日付の後にのみ適用されるポリシーが必要になる場合があり ます。ポリシー言語での条件の指定の詳細については、IAM ユーザーガイド の「条件」を参照してく ださい。 条件を表すには、あらかじめ定義された条件キーを使用します。AWS 全体の条件キーと DynamoDB 固有のキーがあり、必要に応じて使用できます。AWS 全体を対象とするすべてのキーのリストにつ いては、『IAM ユーザーガイド』の「条件に利用可能なキー」を参照してください。DynamoDB 固有 のキーの一覧については、「詳細に設定されたアクセスコントロールのための IAM ポリシー条件の使 用 (p. 477)」を参照してください。 Amazon DynamoDB でアイデンティティベース のポリシー (IAM ポリシー) を使用する このトピックでは、アカウント管理者が IAM アイデンティティ (ユーザー、グループ、ロール) にアク セス権限ポリシーをアタッチし、それによって Amazon DynamoDB リソースでオペレーションを実行 するアクセス権限を付与する方法を示すアイデンティティベースのポリシーの例を示します。 Important 初めに、Amazon DynamoDB リソースへのアクセスを管理するための基本概念と使用可能 なオプションについて説明する概要トピックを読むことをお勧めします。詳細については、 「Amazon DynamoDB リソースへのアクセス権限の管理の概要 (p. 462)」を参照してくださ い。 このセクションでは、次のトピックを対象としています。 • Amazon DynamoDB コンソールを使用するために必要なアクセス権限 (p. 466) • Amazon DynamoDB での AWS 管理 (事前定義) ポリシー (p. 466) • お客様が管理するポリシーの例 (p. 467) 以下に示しているのは、アクセス権限ポリシーの例です。 { API Version 2012-08-10 465 Amazon DynamoDB 開発者ガイド コンソールのアクセス許可 "Version": "2012-10-17", "Statement": [ { "Sid": "DescribeQueryScanBooksTable", "Effect": "Allow", "Action": [ "dynamodb:DescribeTable", "dynamodb:Query", "dynamodb:Scan" ], "Resource": "arn:aws:dynamodb:us-west-2:account-id:table/Books" } ] } このポリシーには、us-west-2 リージョンのテーブルで 3 つの DynamoDB アクション (dynamodb:DescribeTable、dynamodb:Query、dynamodb:Scan) を許可する 1 つのステートメ ントがあります。これは、account-id で指定される AWS アカウントで所有されています。 値の Amazon リソースネーム (ARN)Resource では、アクセス権限が適用されるテーブルを指定します。 Amazon DynamoDB コンソールを使用するために必 要なアクセス権限 DynamoDB コンソールを使用して作業するユーザーに対しては、ユーザーに AWS アカウントの DynamoDB リソースの使用を許可する最小限のアクセス許可が必要です。これらの DynamoDB アク セス許可に加えて、コンソールでは次のサービスからのアクセス許可が必要になります。 • メトリクスとグラフを表示する Amazon CloudWatch アクセス許可。 • DynamoDB データをエクスポートおよびインポートする AWS Data Pipeline アクセス許可。 • エクスポートおよびインポートに必要なロールにアクセスする AWS Identity and Access Management アクセス許可。 • CloudWatch アラームがトリガーされるたびに通知する Amazon Simple Notification Service アクセ ス許可。 • DynamoDB ストリーム レコードを処理する AWS Lambda アクセス許可。 これらの最小限必要なアクセス権限よりも制限された IAM ポリシーを作成している場合、その IAM ポリシーを使用するユーザーに対してコンソールは意図したとおりには機能しません。「Amazon DynamoDB での AWS 管理 (事前定義) ポリシー (p. 466)」で説明されているとおり、ユーザーが DynamoDB コンソールを使用できること、および、AmazonDynamoDBReadOnlyAccess 管理対象ポ リシーがユーザーにアタッチされていることを確認してください。 AWS CLI または Amazon DynamoDB API のみを呼び出すユーザーには、最小限のコンソールアクセ ス権限を付与する必要はありません。 Amazon DynamoDB での AWS 管理 (事前定義) ポ リシー AWS は、AWS によって作成され管理されるスタンドアロンの IAM ポリシーが提供する多くの一般的 ユースケースに対応します。これらの AWS 管理ポリシーは、一般的ユースケースに必要なアクセス 権限を付与することで、どの権限が必要なのかをユーザーが調査する必要をなくすことができます。 詳細については、IAM ユーザーガイド の「AWS 管理ポリシー」を参照してください。 アカウントのユーザーにアタッチ可能な以下の AWS 管理ポリシーは、DynamoDB に固有のもので、 ユースケースシナリオ別にグループ化されます。 API Version 2012-08-10 466 Amazon DynamoDB 開発者ガイド お客様が管理するポリシーの例 • AmazonDynamoDBReadOnlyAccess – AWS マネジメントコンソール を使用して DynamoDB リ ソースへ読み取り専用アクセスを付与します。 • AmazonDynamoDBFullAccess – AWS マネジメントコンソール を使用して DynamoDB リソースへ のフルアクセスを付与します。 • AmazonDynamoDBFullAccesswithDataPipeline – AWS マネジメントコンソール を使用して、AWS Data Pipeline によるエクスポートおよびインポートを含む、DynamoDB リソースへのフルアクセス を付与します。 Note IAM コンソールにサインインし、特定のポリシーを検索することで、これらのアクセス権限 ポリシーを確認することができます。 独自のカスタム IAM ポリシーを作成して、DynamoDB アクションとリソースのための権限を許可す ることもできます。これらのカスタムポリシーは、それらのアクセス権限が必要な IAM ユーザーまた はグループにアタッチできます。 お客様が管理するポリシーの例 このセクションでは、さまざまな DynamoDB アクションのアクセス権限を付与するユーザーポリ シー例を示しています。これらのポリシーは、AWS SDK または AWS CLI を使用しているときに機能 します。コンソールを使用している場合は、「Amazon DynamoDB コンソールを使用するために必要 なアクセス権限 (p. 466)」で説明しているコンソールに固有の追加のアクセス権限を付与する必要が あります。 Note すべての例で、us-west-2 リージョンを使用し、架空のアカウント ID を含めています。 例 • 例 1: ユーザーがテーブルで任意の DynamoDB アクションを実行することを許可する (p. 467) • 例 2: テーブル内の項目の読み取り専用アクセスを許可する (p. 468) • 例 3: 特定のテーブルでの入力、更新、および削除オペレーションを許可する (p. 468) • 例 4: 特定のテーブルおよびそのテーブルのすべてのインデックスにアクセスを許可す る (p. 469) • 例 5: 別のテスト環境および運用環境のアクセス権限ポリシーの設定 (p. 469) • 例 6: リザーブドキャパシティーのサービス購入をユーザーに禁止する (p. 471) • 例 7: DynamoDB ストリームのみの読み取りアクセスを許可する (テーブルを除く) (p. 472) • 例 8: AWS Lambda 関数が DynamoDB ストリームレコードを処理できるようにする (p. 472) 例 1: ユーザーがテーブルで任意の DynamoDB アクションを 実行することを許可する 以下のアクセス権限のポリシーでは、テーブルでのすべての DynamoDB アクションのアクセス権限 を付与します。Resource で指定された ARN 値は、特定のリージョンのテーブルを識別します。 { "Version": "2012-10-17", "Statement": [ { "Sid": "AllAPIActionsOnBooks", API Version 2012-08-10 467 Amazon DynamoDB 開発者ガイド お客様が管理するポリシーの例 "Effect": "Allow", "Action": "dynamodb:*", "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/Books" } ] } Note リソース ARN のテーブル名 (Books) をワイルドカード文字 (*) に置き換える場合、アカウン トのすべてのテーブルで、任意の DynamoDB アクションが許可されます。これを行う場合 は、セキュリティへの影響について慎重に考慮してください。 例 2: テーブル内の項目の読み取り専用アクセスを許可する 以下のアクセス権限のポリシーでは、GetItem および BatchGetItem DynamoDB アクションのみの アクセス権限を付与し、それによってテーブルへの読み取り専用アクセスを設定します。 { "Version": "2012-10-17", "Statement": [ { "Sid": "ReadOnlyAPIActionsOnBooks", "Effect": "Allow", "Action": [ "dynamodb:GetItem", "dynamodb:BatchGetItem" ], "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/Books" } ] } 例 3: 特定のテーブルでの入力、更新、および削除オペレー ションを許可する 次のアクセス権限ポリシーでは、特定の DynamoDB テーブルで、PutItem、UpdateItem、および DeleteItem アクションのアクセス権限を付与します。 { "Version": "2012-10-17", "Statement": [ { "Sid": "PutUpdateDeleteOnBooks", "Effect": "Allow", "Action": [ "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem" ], "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/Books" } ] } API Version 2012-08-10 468 Amazon DynamoDB 開発者ガイド お客様が管理するポリシーの例 例 4: 特定のテーブルおよびそのテーブルのすべてのインデッ クスにアクセスを許可する 以下のアクセス権限ポリシーでは、テーブル (Book) のすべての DynamoDB アクションと、そのテー ブルのすべてのインデックスにアクセス権限を付与します。インデックスの動作の詳細については、 「セカンダリインデックスを使用したデータアクセス性の向上 (p. 333)」を参照してください。 { "Version": "2012-10-17", "Statement": [ { "Sid": "AccessAllIndexesOnBooks", "Effect": "Allow", "Action": [ "dynamodb:*" ], "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/Books", "arn:aws:dynamodb:us-west-2:123456789012:table/Books/index/*" ] } ] } 例 5: 別のテスト環境および運用環境のアクセス権限ポリシー の設定 たとえば、テスト環境と本番環境が別々にあり、各環境で、ProductCatalog という名前のテーブル を独自のバージョンで維持するとします。これらの ProductCatalog テーブルを同じ AWS アカウン トから作成する場合、アクセス権限の設定方法により、本番環境に対してテスト作業の影響が発生す る可能性があります。この理由として、同時発生の作成アクションと削除アクションに対する制限が AWS アカウントレベルで設定されていることなどが挙げられます。この結果、テスト環境内の各ア クションによって、本番環境で利用可能なアクションの数が減少します。また、テスト環境内のコー ドが本番環境内のテーブルに偶然にアクセスしてしまう危険性もあります。このような問題を防ぐに は、本番環境とテスト環境に別々の AWS アカウントを作成することを検討します。 さらに、Bob と Alice という 2 人の開発者が ProductCatalog テーブルをテストしているとし ます。開発者ごとに別々の AWS アカウントを作成する代わりに、開発者間で同じテストアカウ ントを共有することができます。このテスト用アカウントでは、Alice_ProductCatalog や Bob_ProductCatalog など、対象の開発者ごとに、同じテーブルのコピーを作成できます。この場 合、テスト環境用に作成した AWS アカウント内で、IAM ユーザーの Alice と Bob を作成できます。 このとき、所有するテーブルに対して DynamoDB アクションを実行できるように、この 2 人のユー ザーにアクセス権限を付与することができます。 これらのユーザーアクセス権限を付与するには、次のいずれかを実行します。 • 各ユーザーに別々のポリシーを作成し、各ユーザーに個別に割り当てます。たとえば、以下の ポリシーをユーザー Alice に割り当てることで、Alice_ProductCatalog テーブルに対する DynamoDB アクションをすべて許可することができます。 { "Version": "2012-10-17", "Statement": [ { "Sid": "AllAPIActionsOnAliceTable", "Effect": "Allow", API Version 2012-08-10 469 Amazon DynamoDB 開発者ガイド お客様が管理するポリシーの例 "Action": [ "dynamodb:*" ], "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/ Alice_ProductCatalog" } ] } 次に、ユーザー Bob に対して、同様のポリシーを異なるリソース (Bob_ProductCatalog テーブ ル) で作成できます。 • 個々のユーザーにポリシーを付与する代わりに、IAM ポリシー変数を使用して単一のポリ シーを記述し、グループに付与することができます。この例では、グループを作成し、そ のグループにユーザー Alice とユーザー Bob の両者を追加する必要があります。次の例で は、${aws:username}_ProductCatalog テーブルのすべての DynamoDB アクションを実行で きる権限を付与します。ポリシーが評価されると、ポリシー変数 ${aws:username} はリクエス ターのユーザー名に置き換えられます。たとえば、Alice が項目の追加要求を送信する場合、Alice が Alice_ProductCatalog テーブルにアイテムを追加する場合にのみ、そのアクションが許可さ れます。 { "Version": "2012-10-17", "Statement": [ { "Sid": "AllAPIActionsOnUserSpecificTable", "Effect": "Allow", "Action": [ "dynamodb:*" ], "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/ ${aws:username}_ProductCatalog" }, { "Sid": "AdditionalPrivileges", "Effect": "Allow", "Action": [ "dynamodb:ListTables", "dynamodb:DescribeTable", "cloudwatch:*", "sns:*" ], "Resource": "*" } ] } Note IAM ポリシー変数を使用する場合、ポリシーで明示的にアクセスポリシー言語の 2012-10-17 バージョンを指定する必要があります。アクセスポリシー言語のデフォルト バージョン (2008-10-17) では、ポリシー変数をサポートしていません。 具体的なテーブルをリソースとして特定する代わりに、ワイルドカード文字 (*) を使用して、すべての テーブルに権限を付与することができます。次に示すように、各テーブル名の先頭には、リクエスト を行っている IAM ユーザーの名前が付きます。 API Version 2012-08-10 470 Amazon DynamoDB 開発者ガイド お客様が管理するポリシーの例 "Resource":"arn:aws:dynamodb:us-west-2:123456789012:table/${aws:username}_*" 例 6: リザーブドキャパシティーのサービス購入をユーザーに 禁止する DynamoDB のお客様は、「Amazon DynamoDB 料金表」に説明されているように、リザーブドキャ パシティーを購入することができます。リザーブドキャパシティーでは、1 回限りの前払い料金を支 払い、期間中、大幅な節約ができる最小使用レベルを支払う契約を結びます。AWS マネジメントコ ンソール を使用して、リザーブドキャパシティーを表示し、購入できます。ただし、組織のすべての ユーザーに、同じレベルのアクセスを付与しないことをお勧めします。 DynamoDB は、リザーブドキャパシティー管理へのアクセスの制御のために、次の API オペレーショ ンを提供します。 • dynamodb:DescribeReservedCapacity – 現在有効なリザーブドキャパシティーの購入を返しま す。 • dynamodb:DescribeReservedCapacityOfferings – AWS で現在提供されているリザーブド キャパシティープランについての詳細を返します。 • dynamodb:PurchaseReservedCapacityOfferings – リザーブドキャパシティーの実際の注文 を実行します。 AWS マネジメントコンソール はこれらの API オペレーションを使用してリザーブドキャパシティー の情報を表示し、購入を行います。アプリケーションプログラムからこれらのオペレーションを呼 び出すことはできません。オペレーションはコンソールからのみアクセス可能であるためです。ただ し、IAM アクセス権限ポリシーでこれらのオペレーションへのアクセスを許可または拒否することが できます。 次のポリシーでは、ユーザーは AWS マネジメントコンソール を使用してリザーブドキャパシティー のサービスと現在の購入を確認できます。ただし、新しい購入は拒否されます。 { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowReservedCapacityDescriptions", "Effect": "Allow", "Action": [ "dynamodb:DescribeReservedCapacity", "dynamodb:DescribeReservedCapacityOfferings" ], "Resource": "arn:aws:dynamodb:us-west-2:123456789012:*" }, { "Sid": "DenyReservedCapacityPurchases", "Effect": "Deny", "Action": "dynamodb:PurchaseReservedCapacityOfferings", "Resource": "arn:aws:dynamodb:us-west-2:123456789012:*" } ] } API Version 2012-08-10 471 Amazon DynamoDB 開発者ガイド お客様が管理するポリシーの例 例 7: DynamoDB ストリームのみの読み取りアクセスを許可す る (テーブルを除く) テーブルで DynamoDB ストリーム を有効にすると、テーブル内のデータ項目に加えられた各変更に 関する情報がキャプチャされます。詳細については、「DynamoDB ストリーム を使用したテーブル アクティビティのキャプチャ (p. 426)」を参照してください。 場合によっては、アプリケーションが DynamoDB テーブルからデータを読み取らないようにする一 方で、そのテーブルのストリームへのアクセスは許可したいことがあります。たとえば、項目の更新 が検出されたときにストリームをポーリングし、Lambda 関数を呼び出して、追加の処理を実行する よう AWS Lambda を設定できます。 DynamoDB ストリーム へのアクセスを制御するために、以下のアクションを使用できます。 • dynamodb:DescribeStream • dynamodb:GetRecords • dynamodb:GetShardIterator • dynamodb:ListStreams これらのアクションは、DynamoDB ストリーム API に対応します。詳細については、「DynamoDB ストリーム API リファレンス」を参照してください。 次の例では、GameScores という名前のテーブルでストリームにアクセスするアクセス権限をユー ザーに付与するポリシーを作成します。ARN の最後のワイルドカード (*) は、そのテーブルに関連付 けられた任意のストリーム ID に一致します。 { "Version": "2012-10-17", "Statement": [ { "Sid": "AccessGameScoresStreamOnly", "Effect": "Allow", "Action": [ "dynamodb:DescribeStream", "dynamodb:GetRecords", "dynamodb:GetShardIterator", "dynamodb:ListStreams" ], "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/ GameScores/stream/*" } ] } このポリシーは GameScores テーブルのストリームへのアクセスを許可しますが、テーブル自体への アクセスは許可しないことに注意してください。 例 8: AWS Lambda 関数が DynamoDB ストリームレコードを 処理できるようにする DynamoDB ストリームの新しいイベントに基づいて特定のアクションを実行する場合、それらの新 しいイベントによってトリガーされる AWS Lambda 関数を記述できます。ストリームイベントでの Lambda の使用の詳細については、「DynamoDB ストリーム と AWS Lambda のトリガー (p. 451)」 API Version 2012-08-10 472 Amazon DynamoDB 開発者ガイド DynamoDB API の権限リファレンス を参照してください。このような Lambda 関数には、DynamoDB ストリームからデータを読み取るア クセス権限が必要です。 Lambda にアクセス権限を付与するには、Lambda 関数の IAM ロール (実行ロール) に関連付けられた アクセス権限ポリシーを使用します。これは、Lambda 関数を作成するときに指定します。 たとえば、次のアクセス権限ポリシーを実行ロールに関連付けて、リストされた DynamoDB スト リーム アクションを実行するアクセス権限を Lambda に付与できます。 { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowLambdaFunctionInvocation", "Effect": "Allow", "Action": [ "lambda:InvokeFunction" ], "Resource": [ "*" ] }, { "Sid": "AllAPIAccessForDynamoDBStreams", "Effect": "Allow", "Action": [ "dynamodb:GetRecords", "dynamodb:GetShardIterator", "dynamodb:DescribeStream", "dynamodb:ListStreams" ], "Resource": "*" } ] } 詳細については、『AWS Lambda Developer Guide』の「AWS Lambda のアクセス権限モデル」を参 照してください。 DynamoDB API のアクセス権限: アクション、リ ソース、条件リファレンス アクセスコントロール (p. 461) をセットアップし、IAM アイデンティティにアタッチできるアクセ ス権限ポリシー (アイデンティティベースのポリシー) を作成するときは、以下のリストをリファレン スとして使用できます。 リストには各 DynamoDB API オペレーション、アクションを実行するため のアクセス権限を付与できる対応するアクション、およびアクセス権限を付与できる AWS リソース が掲載されています。ポリシーの Action フィールドでアクションを指定し、ポリシーの Resource フィールドでリソースの値を指定します。 DynamoDB ポリシーで AWS 全体の条件キーを使用して、条件を表現することができます。AWS 全 体を対象とするすべてのキーのリストについては、IAM ユーザーガイド の「利用可能なキー」を参照 してください。 AWS 全体を対象とする条件キーに加え、DynamoDB には条件内で使用可能な独自の固有のキーもあ ります。詳細については、「詳細に設定されたアクセスコントロールのための IAM ポリシー条件の使 用 (p. 477)」を参照してください。 API Version 2012-08-10 473 Amazon DynamoDB 開発者ガイド DynamoDB API の権限リファレンス Note アクションを指定するには、API オペレーション名 (dynamodb:CreateTable など) の前に dynamodb: プレフィックスを使用します。 DynamoDB API のアクセス権限: アクション、リソース、および条件キーリファレンス BatchGetItem アクション: dynamodb:BatchGetItem リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* BatchWriteItem アクション: dynamodb:BatchWriteItem リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* CreateTable アクション: dynamodb:CreateTable リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* DeleteItem アクション: dynamodb:DeleteItem リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* DeleteTable アクション: dynamodb:DeleteTable リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* DescribeReservedCapacity アクション: dynamodb:DeleteTable リソース: API Version 2012-08-10 474 Amazon DynamoDB 開発者ガイド DynamoDB API の権限リファレンス arn:aws:dynamodb:region:account-id:* DescribeReservedCapacityOfferings アクション: dynamodb:DescribeReservedCapacityOfferings リソース: arn:aws:dynamodb:region:account-id:* DescribeStream アクション: dynamodb:DescribeStream リソース: arn:aws:dynamodb:region:account-id:table/table-name/stream/stream-label または arn:aws:dynamodb:region:account-id:table/table-name/stream/* DescribeTable アクション: dynamodb:DescribeTable リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* GetItem アクション: dynamodb:GetItem リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* GetRecords アクション: dynamodb:GetRecords リソース: arn:aws:dynamodb:region:account-id:table/table-name/stream/stream-label または arn:aws:dynamodb:region:account-id:table/table-name/stream/* GetShardIterator アクション: dynamodb:GetShardIterator リソース: arn:aws:dynamodb:region:account-id:table/table-name/stream/stream-label または arn:aws:dynamodb:region:account-id:table/table-name/stream/* ListStreams アクション: dynamodb:ListStreams リソース: API Version 2012-08-10 475 Amazon DynamoDB 開発者ガイド DynamoDB API の権限リファレンス arn:aws:dynamodb:region:account-id:table/table-name/stream/* または arn:aws:dynamodb:region:account-id:table/*/stream/* ListTables アクション: dynamodb:ListTables リソース: * PurchaseReservedCapacityOfferings アクション: dynamodb:PurchaseReservedCapacityOfferings リソース: arn:aws:dynamodb:region:account-id:* PutItem アクション: dynamodb:PutItem リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* Query アクション: dynamodb:Query リソース: テーブルに対してクエリを実行するには:arn:aws:dynamodb:region:accountid:table/table-name または: arn:aws:dynamodb:region:account-id:table/table-name インデックスでクエリを実行するには arn:aws:dynamodb:region:account-id:table/table-name/index/index-name または: arn:aws:dynamodb:region:account-id:table/table-name/index/* Scan アクション: dynamodb:Scan リソース: テーブルをスキャンするには arn:aws:dynamodb:region:account-id:table/table-name または: arn:aws:dynamodb:region:account-id:table/table-name インデックスをスキャンするには arn:aws:dynamodb:region:account-id:table/table-name/index/index-name API Version 2012-08-10 476 Amazon DynamoDB 開発者ガイド 関連トピック または: arn:aws:dynamodb:region:account-id:table/table-name/index/* UpdateItem アクション: dynamodb:UpdateItem リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* UpdateTable アクション: dynamodb:UpdateTable リソース: arn:aws:dynamodb:region:account-id:table/table-name または arn:aws:dynamodb:region:account-id:table/* 関連トピック • アクセスコントロール (p. 461) • 詳細に設定されたアクセスコントロールのための IAM ポリシー条件の使用 (p. 477) 詳細に設定されたアクセスコントロールのための IAM ポリシー条件の使用 DynamoDB でアクセス権限を付与するときは、アクセス権限ポリシーを有効にする方法を決める条件 を指定できます。 概要 DynamoDB では、IAM ポリシー (「アクセスコントロール (p. 461)」を参照) を使用してアクセス権 限を付与するとき、条件を指定することもできます。たとえば、次のようにすることができます。 • テーブルまたはセカンダリインデックス内の項目と属性に対する読み取り専用アクセスをユーザー に許可するアクセス権限を付与します。 • ユーザーのアイデンティティに基づいて、テーブルの特定の属性への書き込み専用アクセスをユー ザーを許可するアクセス権限を付与します。 DynamoDB では、次のセクションのユースケースに示すように、条件キーを使用して IAM ポリシー の条件を指定できます。 Note 一部の AWS サービスはタグベースの条件もサポートしますが、DynamoDB はサポートしま せん。 API Version 2012-08-10 477 Amazon DynamoDB 開発者ガイド 概要 アクセス権限のユースケース DynamoDB API アクションへのアクセスを制御するだけでなく、個別のデータ項目と属性へのアクセ スも制御できます。たとえば、次の操作を実行できます。 • テーブルでアクセス権限を付与しますが、特定のプライマリキー値に基づいて、そのテーブル内の 特定の項目へのアクセスを制限します。この例として、ゲーム用のソーシャルネットワーキングア プリケーションがあります。次の図に示すように、すべてのユーザーのゲームデータは 1 つのテー ブルに保存されますが、いずれのユーザーも、自分が所有していないデータ項目にアクセスするこ とはできません。 • 属性のサブセットのみがユーザー表示されるように、情報を非表示にします。この例として、ユー ザーの位置に基づいて、近くの空港の運航便データを表示するアプリケーションがあります。航空 会社名、到着時間、出発時間、および運航便番号がすべて表示されます。ただし、次の図に示すよ うに、パイロット名や乗客数などの属性は非表示になります。 このような種類のきめ細かなアクセス制御を実装するには、セキュリティ認証情報と関連する権限に アクセスするための条件を指定した IAM アクセス権限ポリシーを作成します。次に、IAM コンソール を使用して作成する IAM ユーザー、グループ、またはロールにそのポリシーを適用します。IAM ポリ シーによって、テーブルの個別の項目へのアクセス、その項目の属性へのアクセス、またはその両方 へのアクセスを同時に制御できます。 必要に応じて、ウェブ ID フェデレーションを使用して、Login with Amazon、Facebook、または Google によって認証されるユーザーによるアクセスを制御できます。詳細については、「ウェブアイ デンティティフェデレーションの使用 (p. 488)」を参照してください。 IAM の Condition 要素を使用して、詳細なアクセスコントロールポリシーを実装できま す。Condition 要素をアクセス権限ポリシーに追加することで、特定のビジネス要件に基づい て、DynamoDB テーブルとインデックスの項目と属性へのアクセスを許可または拒否できます。 例として、プレーヤーがさまざまなゲームを選択してプレイできるモバイルゲームアプリケーション を考えてみます。このアプリケーションでは、GameScores という名前の DynamoDB テーブルを使 用して、高スコアなどのユーザーデータを記録します。テーブルの各項目は、ユーザー ID とユーザー がプレイしたゲームの名前で一意に識別されます。GameScores テーブルには、パーティションキー (UserId) およびソートキー (GameTitle) で構成されているプライマリキーがあります。ユーザー は、そのユーザー ID に関連付けられたゲームデータだけにアクセスできます。ゲームをプレイする API Version 2012-08-10 478 Amazon DynamoDB 開発者ガイド 概要 ユーザーは、GameRole という名前の IAM ロールに属する必要があります。このロールには、セキュ リティポリシーが関連付けられています。 このアプリケーションのユーザーアクセス権限を管理するには、次のようなアクセス権限ポリシーを 記述できます。 { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowAccessToOnlyItemsMatchingUserID", "Effect": "Allow", "Action": [ "dynamodb:GetItem", "dynamodb:BatchGetItem", "dynamodb:Query", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:BatchWriteItem" ], "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores" ], "Condition": { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [ "${www.amazon.com:user_id}" ], "dynamodb:Attributes": [ "UserId", "GameTitle", "Wins", "Losses", "TopScore", "TopScoreDateTime" ] }, "StringEqualsIfExists": { "dynamodb:Select": "SPECIFIC_ATTRIBUTES" } } } ] } GameScores テーブル (Resource 要素) の特定の DynamoDB アクション (Action 要素) に対するア クセス権限の付与に加えて、Condition 要素は、次のようにアクセス権限を制限する DynamoDB に 固有の次の条件キーを使用します。 • dynamodb:LeadingKeys – この条件キーにより、ユーザーはパーティションキーの値がユー ザー ID に一致する項目にのみアクセスできます。この ID、${www.amazon.com:user_id} は、 置換変数です。置換変数の詳細については、「ウェブアイデンティティフェデレーションの使 用 (p. 488)」を参照してください。 • dynamodb:Attributes – この条件キーは指定された属性へのアクセスを制限し、アクセス権限 ポリシーに示されたアクションのみが、これらの属性の値を返すことができるようにします。さら に、StringEqualsIfExists 句は、アプリケーションが常に対象となる特定の属性のリストを提 供し、すべての属性をリクエストできないようにします。 API Version 2012-08-10 479 Amazon DynamoDB 開発者ガイド 条件の指定: 条件キーの使用 IAM ポリシーが評価されると、結果は必ず true (アクセス許可) または false (アクセス拒否) になりま す。Condition 要素のいずれかの部分が false の場合、ポリシー全体が false と評価され、アクセス は拒否されます。 Important dynamodb:Attributes を使用する場合、ポリシーでリストに記載されているテーブルとす べてのセカンダリインデックスについて、すべてのプライマリキー属性とインデックスキー 属性の名前を指定する必要があります。指定しなかった場合、DynamoDB は、このキー属性 を使用して、リクエストされたアクションを実行できません。 IAM ポリシードキュメントには、次の Unicode 文字のみを含めることができます。水平タブ (U +0009)、ラインフィード (U+000A)、キャリッジリターン (U+000D)、および U+0020~U+00FF の範 囲内の文字。 条件の指定: 条件キーの使用 AWS には、アクセスコントロールのために IAM をサポートするすべての AWS サービスに合わ せて事前定義された一連の条件キー (AWS 全体に対する条件キー) が用意されています。たとえ ば、aws:SourceIp 条件キーを使用して、リクエスタの IP アドレスを確認してから、アクションの 実行を許可できます。AWS 全体に対するキーの詳細とリストについては、『IAM ユーザーガイド』の 「条件に利用可能なキー」を参照してください。 Note 条件キーは大文字と小文字が区別されます。 以下の表では、DynamoDB に適用される DynamoDB サービス固有の条件キーを示しています。 DynamoDB 条件キー 説明 dynamodb:LeadingKeysテーブルの最初のキー属性、つまりパーティションキーを表します。キー が 1 つの項目のアクションで使用される場合も、キー名 LeadingKeys は 複数形であることに注意してください。また、条件で ForAllValues を 使用するときには、LeadingKeys 修飾子を使用する必要があります。 dynamodb:Select Select または Query リクエストの Scan パラメータを表しま す。Select には次のいずれかの値を指定できます。 • ALL_ATTRIBUTES • ALL_PROJECTED_ATTRIBUTES • SPECIFIC_ATTRIBUTES • COUNT dynamodb:Attributes リクエストの属性名、またはリクエストから返される属性のリストを表し ます。次に示すように、Attributes 値は、特定の DynamoDB API アク ション用のパラメーターと同じ方法で名前が付けられ、同じ意味を持ちま す。 • AttributesToGet 用途: BatchGetItem, GetItem, Query, Scan • AttributeUpdates 用途: UpdateItem API Version 2012-08-10 480 Amazon DynamoDB 開発者ガイド 条件の指定: 条件キーの使用 DynamoDB 条件キー 説明 • Expected 用途: DeleteItem, PutItem, UpdateItem • Item 用途: PutItem • ScanFilter 用途: Scan dynamodb:ReturnValues リクエストの ReturnValues パラメータを表します。ReturnValues に は次のいずれかの値を指定できます。 • ALL_OLD • UPDATED_OLD • ALL_NEW • UPDATED_NEW • NONE dynamodb:ReturnConsumedCapacity リクエストの ReturnConsumedCapacity パラメータを表しま す。ReturnConsumedCapacity には、次のいずれかの値を指定できま す。 • TOTAL • NONE ユーザーアクセスの制限 多くの IAM アクセス権限ポリシーでは、パーティションキーの値がユーザー識別子 と一致するテーブルの項目へのアクセスのみをユーザーに許可します。たとえば、 前述のゲームアプリケーションは、この方法でアクセスを制限し、ユーザーは自分の ユーザー ID に関連付けらたゲームデータのみにアクセスできるようにします。IAM 置換変数 ${www.amazon.com:user_id}、${graph.facebook.com:id}、および ${accounts.google.com:sub} には、Login with Amazon、Facebook、および Google のユーザー 識別子が格納されます。アプリケーションがこのようなアイデンティティプロバイダーのいずれかに ログインし、この識別子を取得する方法については、「ウェブアイデンティティフェデレーションの 使用 (p. 488)」を参照してください。 Note 以下のセクションの各例では、Effect 句を Allow に設定して、許可されるアクション、リ ソース、およびパラメーターだけを指定します。IAM ポリシーで明示的に指定されたものへ のアクセスだけが許可されます。 場合によっては、拒否ベースとなるようにこのポリシーを書き直すことができます。つ まり、Effect 句を Deny に設定して、ポリシーのすべてのロジックを逆にします。ただ し、拒否ベースのポリシーを DynamoDB で使用しないことをお勧めします。このような ポリシーは、許可ベースのポリシーと比べて、正しく記述することが難しいためです。ま た、DynamoDB API への将来の変更(または、既存の API 入力への変更)が原因で、拒否 ベースのポリシーが機能しなくなる可能性があります。 API Version 2012-08-10 481 Amazon DynamoDB 開発者ガイド 条件の指定: 条件キーの使用 ポリシー例: きめ細かなアクセスコントロールのための IAM ポ リシー条件の使用 このセクションでは、DynamoDB テーブルとインデックスに対してきめ細かなアクセス制御を実装す るためのポリシーについて説明します。 Note すべての例で、us-west-2 リージョンを使用し、架空のアカウント ID を含めています。 1: 特定のパーティションのキー値を持つ項目へのアクセスを制限するアクセ ス権限の付与 以下のアクセス権限ポリシーは、GamesScore テーブルで DynamoDB アクションのセットを許 可するアクセス権限を付与します。このポリシーは dynamodb:LeadingKeys 条件キーを使用し て、UserID パーティションキーの値が、このアプリケーション用の Login with Amazon の一意の ユーザー ID と一致する項目のみでユーザーアクションを制限します。 Important Scan 用のアクセス権限は、アクションのリストに含まれていません。これは、Scan が主要 なキーにかかわらずすべての項目を返すためです。 { "Version": "2012-10-17", "Statement": [ { "Sid": "FullAccessToUserItems", "Effect": "Allow", "Action": [ "dynamodb:GetItem", "dynamodb:BatchGetItem", "dynamodb:Query", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:BatchWriteItem" ], "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores" ], "Condition": { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [ "${www.amazon.com:user_id}" ] } } } ] } API Version 2012-08-10 482 Amazon DynamoDB 開発者ガイド 条件の指定: 条件キーの使用 Note ポリシー変数を使用する場合は、2012-10-17 をポリシー内で明示的に指定する必要があり ます。アクセスポリシー言語のデフォルトバージョン、2008-10-17 では、ポリシー変数を サポートしていません。 読み取りアクセスを実装するには、データを変更可能なアクションを削除します。次のポリシーで は、読み込み専用アクセスを提供するアクションだけが条件に追加されています。 { "Version": "2012-10-17", "Statement": [ { "Sid": "ReadOnlyAccessToUserItems", "Effect": "Allow", "Action": [ "dynamodb:GetItem", "dynamodb:BatchGetItem", "dynamodb:Query" ], "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores" ], "Condition": { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [ "${www.amazon.com:user_id}" ] } } } ] } Important dynamodb:Attributes を使用する場合、ポリシーでリストに記載されているテーブルとす べてのセカンダリインデックスについて、すべてのプライマリキー属性とインデックスキー 属性の名前を指定する必要があります。指定しなかった場合、DynamoDB は、このキー属性 を使用して、リクエストされたアクションを実行できません。 2: テーブルの特定の属性へのアクセスを制限するアクセス権限の付与 次のアクセス権限ポリシーは、dynamodb:Attributes 条件キーを追加して、テーブルの 2 つの特定 の属性のみへアクセスを許可します。この属性に対して、読み込み、書き込み、または条件付き書き 込みまたはスキャンフィルタでの評価を実行できます。 { "Version": "2012-10-17", "Statement": [ { "Sid": "LimitAccessToSpecificAttributes", "Effect": "Allow", "Action": [ "dynamodb:UpdateItem", "dynamodb:GetItem", API Version 2012-08-10 483 Amazon DynamoDB 開発者ガイド 条件の指定: 条件キーの使用 "dynamodb:Query", "dynamodb:BatchGetItem", "dynamodb:Scan" ], "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores" ], "Condition": { "ForAllValues:StringEquals": { "dynamodb:Attributes": [ "UserId", "TopScore" ] }, "StringEqualsIfExists": { "dynamodb:Select": "SPECIFIC_ATTRIBUTES", "dynamodb:ReturnValues": [ "NONE", "UPDATED_OLD", "UPDATED_NEW" ] } } } ] } Note このポリシーでは、ホワイトリスト手法を使用し、名前の付いた一連の属性へのアクセスを 許可します。代わりに、他の属性へのアクセスを拒否する同等のポリシーを記述できます (ブ ラックリスト手法)。このブラックリスト 手法は、お勧めしません。それは、ユーザーが、す べての考えられる属性名を使用してリクエストを繰り返し発行し、最終的に、アクセスが許 可されていない属性を見つけることで、ブラックリストに記載されている属性の名前を特定 できる可能性があるためです。これを回避するには、Wikipedia (http://en.wikipedia.org/wiki/ Principle_of_least_privilege) で説明されているように、最小権限の原則に従ってホワイトリス ト手法を使用し、拒否される属性を指定するのではなく、許可されるすべての値を列挙しま す。 このポリシーでは、PutItem、DeleteItem、または BatchWriteItem は許可されません。これら のアクションでは常に前の項目全体が置き換えられ、アクセスが許可されていない属性の以前の値 を、ユーザーが削除できる可能性があるためです。 アクセス権限ポリシーの StringEqualsIfExists 句により、以下を実施することができます。 • ユーザーが Select パラメータを指定する場合、その値は SPECIFIC_ATTRIBUTES である必要が あります。この要件により、インデックスの射影からなど、API アクションが許可されていない属 性を返さないようにします。 • ユーザーが ReturnValues パラメータを指定する場合、その値は、NONE、UPDATED_OLD、ま たは UPDATED_NEW にする必要があります。これが必要なのは、UpdateItem アクションでは、 置換する前に項目が存在するかどうかをチェックするために、および、リクエストされた場合 に前の属性値を返すことができるように、暗黙的な読み込みオペレーションが実行されるためで す。ReturnValues をこのように制限することで、確実にユーザーが許可された属性だけを読み込 むまたは書き込むことができるようにします。 • StringEqualsIfExists 節により、許可されたアクションのコンテキストで、リクエストごとに Select または ReturnValues パラメータのいずれか 1 つだけを使用できるようにすることができ ます。 API Version 2012-08-10 484 Amazon DynamoDB 開発者ガイド 条件の指定: 条件キーの使用 次に、このポリシーのバリエーションをいくつか示します。 • 読み込みアクションだけを許可するには、許可されるアクションのリストから UpdateItem を削除できます。残りのどのアクションも ReturnValues を受け付けないので、条件から ReturnValues を削除できます。また、Select パラメーターには必ず値 (特に指定のない限 り、ALL_ATTRIBUTES) があるので、StringEqualsIfExists を StringEquals に変更できま す。 • 書き込みアクションだけを許可するには、許可されるアクションのリストから、UpdateItem を除 くすべてのアクションを削除します。UpdateItem では Select パラメーターを使用しないので、 条件から Select を削除できます。また、ReturnValues パラメーターには必ず値 (特に指定のな い限り、NONE) があるので、StringEqualsIfExists を StringEquals に変更する必要がありま す。 • 名前がパターンに一致するすべての属性を許可するには、StringEquals ではなく StringLike を使用し、複数文字パターン照合ワイルドカード文字 (*) を使用します。 3: 特定の属性で更新を回避するアクセス権限の付与 以下のアクセス権限のポリシーでは、dynamodb:Attributes 条件キーによって識別される特定の属 性のみを更新するようユーザーアクセスを制限します。StringNotLike 条件によって、アプリケー ションが、dynamodb:Attributes 条件キーを使用して指定された属性を更新できないようになりま す。 { "Version": "2012-10-17", "Statement": [ { "Sid": "PreventUpdatesOnCertainAttributes", "Effect": "Allow", "Action": [ "dynamodb:UpdateItem" ], "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/ GameScores", "Condition": { "ForAllValues:StringNotLike": { "dynamodb:Attributes": [ "FreeGamesAvailable", "BossLevelUnlocked" ] }, "StringEquals": { "dynamodb:ReturnValues": [ "NONE", "UPDATED_OLD", "UPDATED_NEW" ] } } } ] } 次の点に注意してください。 • UpdateItem アクションは、他の書き込みアクションと同じように、更新前の値と更新後 の値を返すことができるように、項目への読み取りアクセスを必要とします。ポリシーで は、dynamodb:ReturnValues 条件キーを指定して、更新が許可される属性のみにアクセ API Version 2012-08-10 485 Amazon DynamoDB 開発者ガイド 条件の指定: 条件キーの使用 スするようアクションを制限します。条件キーは、リクエストの ReturnValues を制限して NONE、UPDATED_OLD、または UPDATED_NEW のみを指定し、ALL_OLD または ALL_NEW は含まれ ません。 • PutItem および DeleteItem アクションは項目全体を置き換えるため、アプリケーションは任意 の属性を変更することができます。したがって、特定の属性のみを更新するようアプリケーション を制限するときは、それらの API 用のアクセス権限を付与しないようにします。 4: インデックスで射影された属性のみのクエリを許可するアクセス権限の付 与 以下のアクセス権限ポリシーでは、dynamodb:Attributes 条件キーを使用して、セカンダリイン デックス (TopScoreDateTimeIndex) でクエリを許可します。また、このポリシーでは、インデック スに射影された特定の属性だけをリクエストするようクエリを制限します。 アプリケーションがクエリで属性のリストを指定するよう要求するには、ポリシーで dynamodb:Select 条件キーを指定して、DynamoDB の Query アクションの Select パラメーター が SPECIFIC_ATTRIBUTES であることを要求します。属性のリストは、dynamodb:Attributes 条 件キーを使用して提供される特定のリストに制限されます。 { "Version": "2012-10-17", "Statement": [ { "Sid": "QueryOnlyProjectedIndexAttributes", "Effect": "Allow", "Action": [ "dynamodb:Query" ], "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores/ index/TopScoreDateTimeIndex" ], "Condition": { "ForAllValues:StringEquals": { "dynamodb:Attributes": [ "TopScoreDateTime", "GameTitle", "Wins", "Losses", "Attempts" ] }, "StringEquals": { "dynamodb:Select": "SPECIFIC_ATTRIBUTES" } } } ] } 次のアクセス権限ポリシーは、似ていますが、クエリでは、インデックスに射影されたすべての属性 をリクエストする必要があります。 { "Version": "2012-10-17", "Statement": [ { API Version 2012-08-10 486 Amazon DynamoDB 開発者ガイド 条件の指定: 条件キーの使用 "Sid": "QueryAllIndexAttributes", "Effect": "Allow", "Action": [ "dynamodb:Query" ], "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores/ index/TopScoreDateTimeIndex" ], "Condition": { "StringEquals": { "dynamodb:Select": "ALL_PROJECTED_ATTRIBUTES" } } } ] } 5: 特定の属性とパーティションキー値へのアクセスを制限するアクセス権限 の付与 以下のアクセス権限ポリシーでは、特定の DynamoDB アクション (Action 要素で指定) をテーブルとテーブルインデックス (Resource 要素で指定) で許可します。このポリシー は、dynamodb:LeadingKeys 条件キーを使用して、パーティションキーの値がユーザーの Facebook ID に一致する項目のみにアクセス権限を制限します。 { "Version": "2012-10-17", "Statement": [ { "Sid": "LimitAccessToCertainAttributesAndKeyValues", "Effect": "Allow", "Action": [ "dynamodb:UpdateItem", "dynamodb:GetItem", "dynamodb:Query", "dynamodb:BatchGetItem" ], "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores", "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores/ index/TopScoreDateTimeIndex" ], "Condition": { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [ "${graph.facebook.com:id}" ], "dynamodb:Attributes": [ "attribute-A", "attribute-B" ] }, "StringEqualsIfExists": { "dynamodb:Select": "SPECIFIC_ATTRIBUTES", "dynamodb:ReturnValues": [ "NONE", "UPDATED_OLD", API Version 2012-08-10 487 Amazon DynamoDB 開発者ガイド 関連トピック "UPDATED_NEW" ] } } } ] } 次の点に注意してください。 • ポリシー (UpdateItem) によって許可された書き込みアクションでは、attribute-A または attribute-B のみを変更できます。 • ポリシーでは UpdateItem が許可されるため、アプリケーションは新しい項目を挿入でき、その非 表示の属性は、新しい項目では null として表示されます。この属性が TopScoreDateTimeIndex に射影されている場合、テーブルからのフェッチを引き起こすクエリを防止するという利点がポリ シーに追加されます。 • アプリケーションは、dynamodb:Attributes に列挙されている属性以外の属性を読み込むこ とができません。このポリシーにより、アプリケーションは、読み込みリクエストで Select パ ラメーターを SPECIFIC_ATTRIBUTES に設定する必要があり、ホワイトリストに記載されてい る属性だけをリクエストすることができます。書き込みリクエストの場合、アプリケーション は、ReturnValues を ALL_OLD または ALL_NEW に設定できません。また、他の属性に基づく条件 付き書き込みオペレーションを実行できません。 関連トピック • アクセスコントロール (p. 461) • DynamoDB API のアクセス権限: アクション、リソース、条件リファレンス (p. 473) ウェブアイデンティティフェデレーションの使用 多数のユーザーを対象とするアプリケーションを記述している場合、必要に応じて、ウェブアイデン ティティフェデレーションを使用して、認証と認可を実行できます。ウェブアイデンティティフェデ レーションを使用すると、IAM ユーザーを作成する必要がなくなります。ユーザーは、アイデンティ ティプロバイダーにサインインして、AWS Security Token Service(AWS STS)から一時的なセキュ リティ認証情報を取得できます。アプリケーションでは、この認証情報を使用して AWS サービスに アクセスできます。 ウェブアイデンティティフェデレーションでは、次のアイデンティティプロバイダーをサポートして います。 • Login with Amazon • Facebook • Google ウェブアイデンティティフェデレーションに関する その他のリソース ウェブアイデンティティフェデレーションの詳細を理解するのに、次のリソースが役に立ちます。 • 「Web Identity Federation Playground」は、インタラクティブなウェブサイトで、Login with Amazon、Facebook、または Google を介して認証を行い、一時的なセキュリティ認証情報を取得 し、その認証情報を使用して AWS にリクエストを行うプロセスを体験できます。 API Version 2012-08-10 488 Amazon DynamoDB 開発者ガイド ウェブアイデンティティフェデレーションのポリシー例 • AWS .NET Development ブログの記事「Web Identity Federation using the AWS SDK for .NET」で は、ウェブ ID フェデレーションと Facebook を使用する方法について説明し、ウェブ ID を使用し て IAM ロールを前提とする方法を示す C# コード例と、一時的なセキュリティ認証情報を使用して AWS リソースにアクセスする方法を示す C# コード例を掲載しています。 • 「AWS SDK for iOS」と「AWS SDK for Android」には、サンプルアプリケーションが用意されて います。このアプリケーションには、アイデンティティプロバイダーを呼び出す方法、そのプロ バイダーからの情報を使用して、一時的なセキュリティ認証情報を取得および使用する方法を示す コードが含まれています。 • 記事「Web Identity Federation with Mobile Applications」では、ウェブアイデンティティフェデレー ションについて説明し、ウェブアイデンティティフェデレーションを使用して AWS リソースにア クセスする例を挙げています。 ウェブアイデンティティフェデレーションのポリ シー例 ウェブアイデンティティフェデレーションを DynamoDB で使用する方法を説明するために、「詳 細に設定されたアクセスコントロールのための IAM ポリシー条件の使用 (p. 477)」で示した GameScores テーブルをもう一度取り上げます。次に、GameScores のプライマリキーを示します。 テーブル名 プライマリキーのタイ プ GameScores(UserId、GameTitle、...) 複合 パーティションキーの 名前と型 ソートキーの名前と型 属性名: UserId 属性名: GameTitle 型: 文字列 型: 文字列 ここで、あるモバイルゲームアプリケーションがこのテーブルを使用し、そのアプリケーションで は、数千人、数百万人のユーザーをサポートする必要があるとします。この規模では、個別のアプリ ケーションユーザーを管理し、各ユーザーが GameScores テーブルの自分のデータにだけアクセス できることを確実にするのは非常に難しいです。多くのユーザーは、Facebook、Google、Login with Amazon などのサードパーティのアイデンティティプロバイダーのアカウントを持っているので、こ のようなプロバイダーのいずれかを利用して、認証タスクを行うことができます。 ウェブアイデンティティフェデレーションを使用して認証を行うには、アプリケーション開発者は、 そのアプリケーションをアイデンティティプロバイダー(Login with Amazon など)に登録して、一 意のアプリケーション ID を取得する必要があります。次に、IAM ロールを作成する必要があります。 (この例では、このロールに GameRole という名前を付けます)。このロールには、IAM ポリシード キュメントを関連付ける必要があります。このドキュメントでは、アプリケーションが GameScores テーブルにアクセスできるように条件を指定します。 ユーザーは、ゲームをプレイするとき、ゲームアプリケーション内から Login with Amazon アカウン トにサインインします。アプリケーションは、AWS Security Token Service(AWS STS)を呼び出 し、Login with Amazon アプリケーション ID を提供し、GameRole のメンバーシップをリクエスト します。AWS STS は、一時的な AWS 認証情報をアプリケーションに返し、GameRolel ポリシード キュメントに従って GameScores テーブルへのアクセスをアプリケーションに許可します。 次の図は、これらの要素を組み合わせるとどのようになるかを示しています。 API Version 2012-08-10 489 Amazon DynamoDB 開発者ガイド ウェブアイデンティティフェデレーションのポリシー例 ウェブ ID フェデレーションの概要 1. アプリケーションは、サードパーティのアイデンティティプロバイダーを呼び出して、ユーザーと アプリケーションを認証します。アイデンティティプロバイダーは、ウェブアイデンティティトー クンをアプリケーションに返します。 2. アプリケーションは、AWS STS を呼び出し、ウェブアイデンティティトークンを入力として渡し ます。AWS STS は、アプリケーションを認可し、一時的な AWS アクセス認証情報をアプリケー ションに渡します。アプリケーションは、IAM ロール(GameRole)を想定し、そのロールのセ キュリティポリシーに従って AWS リソースにアクセスすることが許可されます。 3. アプリケーションは、DynamoDB を呼び出して、GameScores テーブルにアクセスします。アプ リケーションは GameRole を想定しているので、そのロールに関連付けられたセキュリティポリ シーの影響を受けます。ポリシードキュメントによって、ユーザーに属していないデータにアプリ ケーションはアクセスできません。 もう一度、「詳細に設定されたアクセスコントロールのための IAM ポリシー条件の使用 (p. 477)」 で示した GameRole のセキュリティポリシーを示します。 { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowAccessToOnlyItemsMatchingUserID", API Version 2012-08-10 490 Amazon DynamoDB 開発者ガイド ウェブアイデンティティフェデ レーションを使用するための準備 "Effect": "Allow", "Action": [ "dynamodb:GetItem", "dynamodb:BatchGetItem", "dynamodb:Query", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:BatchWriteItem" ], "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores" ], "Condition": { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [ "${www.amazon.com:user_id}" ], "dynamodb:Attributes": [ "UserId", "GameTitle", "Wins", "Losses", "TopScore", "TopScoreDateTime" ] }, "StringEqualsIfExists": { "dynamodb:Select": "SPECIFIC_ATTRIBUTES" } } } ] } Condition 節によって、アプリケーションに表示される GameScores の項目が決まります。Login with Amazon ID と GameScores の UserId パーティションキーの値を比較することで、これを行 います。このポリシーに列挙されている DynamoDB アクションのいずれかを使用して処理できるの は、現在のユーザーに属する項目だけです。テーブルのその他の項目にはアクセスできません。さら に、ポリシーに列挙されている特定の属性にだけアクセスできます。 ウェブアイデンティティフェデレーションを使用す るための準備 アプリケーション開発者がアプリケーションにウェブアイデンティティフェデレーションを使用する 場合、次の手順に従います。 1. 開発者としてサードパーティのアイデンティティプロバイダーにサインアップします。次の外部リ ンクには、サポートされるアイデンティティプロバイダーにサインアップする方法に関する情報が 記載されています。 • Login with Amazon 開発者センター • Facebook サイトの登録 • Google サイトの Using OAuth 2.0 to Access Google APIs 2. アプリケーションをアイデンティティプロバイダーに登録します。登録すると、プロバイダーから アプリケーションに固有の ID が提供されます。複数のアイデンティティプロバイダーで機能する API Version 2012-08-10 491 Amazon DynamoDB 開発者ガイド ウェブアイデンティティフェデレーショ ンを使用するアプリケーションの記述 ようにアプリケーションを構築する場合は、各プロバイダーからアプリケーション ID を取得する 必要があります。 3. 1 つ以上の IAM ロールを作成します。各アプリケーションのアイデンティティプロバイダーごと に 1 つのロールが必要です。たとえば、ユーザーが Login with Amazon を使用してサインインする アプリケーションで想定できるロール、ユーザーが Facebook を使用してサインインする同じアプ リケーションの 2 つ目のロール、およびユーザーが Google を使用してサインインするアプリケー ションの 3 つ目のロールを作成します。 ロール作成プロセスの中で、IAM ポリシーをロールに関連付ける必要があります。ポリシードキュ メントでは、アプリケーションに必要な DynamoDB リソース、そのリソースにアクセスするため の権限を定義する必要があります。 詳細については、『IAM ユーザーガイド』の「ウェブ ID フェデレーションの詳細について」を参照し てください。 Note AWS Security Token Service の代わりに、Amazon Cognito を使用することもできま す。Amazon Cognito の方が、モバイルアプリの一時的認証情報の管理用としては望ましい サービスです。詳細については、次のページを参照してください。 • 「ユーザーの認証方法(AWS Mobile SDK for iOS)」 • 「ユーザーの認証方法(AWS Mobile SDK for Android)」 DynamoDB コンソールを使用した IAM ポリシーの生成 DynamoDB コンソールでは、ウェブアイデンティティフェデレーションで使用する IAM ポリシーを 作成できます。作成するには、DynamoDB テーブルを選択し、ポリシーに追加するアイデンティティ プロバイダー、アクション、および属性を指定します。DynamoDB コンソールによって、IAM ロール に関連付けることができるポリシーが生成されます。 1. AWS マネジメントコンソール にサインインし、DynamoDB コンソール (https:// console.aws.amazon.com/dynamodb/) を開きます。 2. ナビゲーションペインで、[ Tables] を選択します。 3. テーブルの一覧で、IAM ポリシーを作成するテーブルを選択します。 4. [Access control] タブを選択します。 5. ポリシーの ID プロバイダー、アクション、および属性を選択します。 ポリシーの設定が正しいことを確認したら、[Create policy] をクリックします。生成されたポリ シーが表示されます。 6. [Attach policy instructions] をクリックし、必要な手順に従って、生成されたポリシーを IAM ロー ルにアタッチします。 ウェブアイデンティティフェデレーションを使用す るアプリケーションの記述 ウェブアイデンティティフェデレーションを使用するには、アプリケーションで、作成した IAM ロー ルを想定する必要があります。その時点から、アプリケーションは、そのロールに関連付けられたア クセスポリシーに従います。 実行時、アプリケーションがウェブアイデンティティフェデレーションを使用する場合、次の手順に 従う必要があります。 API Version 2012-08-10 492 Amazon DynamoDB 開発者ガイド ウェブアイデンティティフェデレーショ ンを使用するアプリケーションの記述 1. サードパーティのアイデンティティプロバイダーと認証を行います。アプリケーションは、アイデ ンティティプロバイダーが提供するインターフェイスを使用してそのプロバイダーを呼び出す必要 があります。ユーザーを認証するときの正確な方法は、プロバイダーおよびアプリケーションを実 行しているプラットフォームによって異なります。一般的に、ユーザーがまだサインインしていな い場合、アイデンティティプロバイダーはそのプロバイダーのサインインページを表示するように 対処します。 アイデンティティプロバイダーはユーザーを認証した後、ウェブアイデンティティトークンをアプ リケーションに返します。このトークンの形式は、プロバイダーによって異なりますが、通常は、 非常に長い文字列です。 2. 一時的な AWS セキュリティ認証情報を取得します。取得するために、アプリケーションは AssumeRoleWithWebIdentity リクエストを AWS Security Token Service(AWS STS)に送信 します。このリクエストでは以下を指定します。 • 前の手順からのウェブアイデンティティトークン • アイデンティティプロバイダーからのアプリケーション ID • このアプリケーションのこのアイデンティティプロバイダー用に作成した IAM ロールの Amazon リソースネーム(ARN) AWS STS は、一定の時間(デフォルトでは、3600 秒)経過した後に失効する AWS セキュリティ 認証情報のセットを返します。 次に、AWS STS で AssumeRoleWithWebIdentity アクションを実行するときのサンプルリクエ ストとレスポンスを示します。ウェブアイデンティティトークンは、Login with Amazon アイデン ティティプロバイダーから取得しました。 GET / HTTP/1.1 Host: sts.amazonaws.com Content-Type: application/json; charset=utf-8 URL: https://sts.amazonaws.com/?ProviderId=www.amazon.com &DurationSeconds=900&Action=AssumeRoleWithWebIdentity &Version=2011-06-15&RoleSessionName=web-identity-federation &RoleArn=arn:aws:iam::123456789012:role/GameRole &WebIdentityToken=Atza|IQEBLjAsAhQluyKqyBiYZ8-kclvGTYM81e...(remaining characters omitted) <AssumeRoleWithWebIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/"> <AssumeRoleWithWebIdentityResult> <SubjectFromWebIdentityToken>amzn1.account.AGJZDKHJKAUUSW6C44CHPEXAMPLE</ SubjectFromWebIdentityToken> <Credentials> <SessionToken>AQoDYXdzEMf//////////wEa8AP6nNDwcSLnf+cHupC... (remaining characters omitted)</SessionToken> <SecretAccessKey>8Jhi60+EWUUbbUShTEsjTxqQtM8UKvsM6XAjdA==</ SecretAccessKey> <Expiration>2013-10-01T22:14:35Z</Expiration> <AccessKeyId>06198791C436IEXAMPLE</AccessKeyId> </Credentials> <AssumedRoleUser> <Arn>arn:aws:sts::123456789012:assumed-role/GameRole/web-identityfederation</Arn> <AssumedRoleId>AROAJU4SA2VW5SZRF2YMG:web-identity-federation</ AssumedRoleId> </AssumedRoleUser> API Version 2012-08-10 493 Amazon DynamoDB 開発者ガイド ウェブアイデンティティフェデレーショ ンを使用するアプリケーションの記述 </AssumeRoleWithWebIdentityResult> <ResponseMetadata> <RequestId>c265ac8e-2ae4-11e3-8775-6969323a932d</RequestId> </ResponseMetadata> </AssumeRoleWithWebIdentityResponse> 3. AWS リソースにアクセスします。AWS STS からのレスポンスには、DynamoDB リソースにアク セスするためにアプリケーションに必要な情報が格納されています。 • AccessKeyID、SecretAccessKey、および SessionToken フィールドには、このユーザーと このアプリケーションにのみ有効なセキュリティ認証情報が入っています。 • Expiration フィールドは、この認証情報の時間制限を示します。この時間を経過すると、認証 情報は無効になります。 • AssumedRoleId フィールドには、アプリケーションによって想定されたセッション固有の IAM ロールの名前が入っています。アプリケーションは、このセッションの期間中、IAM ポリシード キュメントのアクセスコントロールに従います。 • SubjectFromWebIdentityToken フィールドには、この特定のアイデンティティプロバイダー 用の IAM ポリシー変数に表示される一意の ID が入っています。次に、サポートされるプロバイ ダーの IAM ポリシー変数と、その値の例を示します。 ポリシー変数 値の例 ${www.amazon.com:user_id} amzn1.account.AGJZDKHJKAUUSW6C44CHPEXAMPLE ${graph.facebook.com:id} 123456789 ${accounts.google.com:sub} 123456789012345678901 このポリシー変数が使用される IAM ポリシーの例については、「ポリシー例: きめ細かなアクセスコ ントロールのための IAM ポリシー条件の使用 (p. 482)」を参照してください。 AWS Security Token Service が一時的なアクセス認証情報を生成する方法については、『IAM ユー ザーガイド』の「一時的セキュリティ認証情報のリクエスト」を参照してください。 API Version 2012-08-10 494 Amazon DynamoDB 開発者ガイド Amazon DynamoDB のモニタリン グ モニタリングは、Amazon DynamoDB と AWS ソリューションの信頼性、可用性、パフォーマンスを 維持する上で重要な部分です。マルチポイント障害が発生した場合は、その障害をより簡単にデバッ グできるように、AWS ソリューションのすべての部分からモニタリングデータを収集する必要があり ます。Amazon DynamoDB のモニタリングを開始する前に、以下の質問に対する回答を反映したモニ タリング計画を作成する必要があります。 • どのような目的でモニタリングしますか? • モニタリングの対象となるリソースとは ? • どのくらいの頻度でこれらのリソースをモニタリングしますか? • 使用するモニタリングツールは? • 誰がモニタリングタスクを実行しますか? • 誰が問題が発生したときに通知を受け取りますか? 次のステップは、さまざまなタイミングと負荷条件でパフォーマンスを測定することにより、お客様 の環境で通常の Amazon DynamoDB パフォーマンスのベースラインを確定することです。Amazon DynamoDB を監視するには、モニタリングデータの履歴を保存することを検討します。保存データ を、最新のパフォーマンスデータと比較するベースラインとして使用し、通常のパフォーマンスのパ ターンやパフォーマンスの異常を検出して、問題への対応を検討することができます。 ベースラインを確立するには、少なくとも、次の項目をモニタリングする必要があります。 • 指定の期間内に消費された読み取りおよび書き込み容量ユニットの数。これにより、どれだけのプ ロビジョンドスループットが使用されたかをトラックすることができます。 • テーブルにプロビジョニングされた書き込みまたは読み取り容量を指定期間で超えたリクエスト で、テーブルにプロビジョニングされたスループット制限をどのリクエストが超えたかを判断でき ます。 • システムエラーで、いずれかのリクエストでエラーが発生したかどうかを判断できます。 トピック • モニタリングツール (p. 496) API Version 2012-08-10 495 Amazon DynamoDB 開発者ガイド モニタリングツール • Amazon CloudWatch でのモニタリング (p. 497) • AWS CloudTrail を使用した DynamoDB オペレーションのログ記録 (p. 511) モニタリングツール AWS では、Amazon DynamoDB のモニタリングに使用できるツールを提供しています。これらの中 には、自動モニタリングを設定できるものもあれば、手操作を必要とするものもあります。モニタリ ングタスクをできるだけ自動化することをお勧めします。 自動モニタリングツール 以下に示す自動化されたモニタリングツールを使用すると、Amazon DynamoDB がモニタリングさ れ、問題が検出されたときにレポートされます。 • Amazon CloudWatch Alarms – Watch a single metric over a time period that you specify, and perform one or more actions based on the value of the metric relative to a given threshold over a number of time periods. The action is a notification sent to an Amazon Simple Notification Service (Amazon SNS) topic or Auto Scaling policy. CloudWatch alarms do not invoke actions simply because they are in a particular state; the state must have changed and been maintained for a specified number of periods. For more information, see Amazon CloudWatch でのモニタリン グ (p. 497). • Amazon CloudWatch Logs – Monitor, store, and access your log files from AWS CloudTrail or other sources. For more information, see Monitoring Log Files in the Amazon CloudWatch ユーザーガイ ド. • Amazon CloudWatch Events – Match events and route them to one or more target functions or streams to make changes, capture state information, and take corrective action. For more information, see Using Events in the Amazon CloudWatch ユーザーガイド. • AWS CloudTrail Log Monitoring – Share log files between accounts, monitor CloudTrail log files in real time by sending them to CloudWatch Logs, write log processing applications in Java, and validate that your log files have not changed after delivery by CloudTrail. For more information, see Working with CloudTrail Log Files in the AWS CloudTrail User Guide. 手動モニタリングツール Amazon DynamoDB のモニタリングにおけるもう 1 つの重要な部分は、CloudWatch アラームで網羅 されていない項目を手動でモニタリングすることです。Amazon DynamoDB、CloudWatch、Trusted Advisor、その他の AWS コンソールのダッシュボードには、AWS 環境の状態が一目でわかるビュー が表示されます。Amazon DynamoDB のログファイルを確認することもお勧めします。 • Amazon DynamoDB ダッシュボードは以下のように表示されます。 • 最近のアラート • 合計容量 • サービス状態 • CloudWatch ホーム ページは以下のように表示されます。 • 現在のアラームとステータス • アラームとリソースのグラフ • サービス状態ステータス さらに、CloudWatch を使用して次のことが行えます。 • 重視するサービスをモニタリングするためのカスタマイズしたダッシュボードを作成する • メトリクスデータをグラフ化して、問題のトラブルシューティングを行い、傾向を確認する API Version 2012-08-10 496 Amazon DynamoDB 開発者ガイド Amazon CloudWatch でのモニタリング • AWS リソースのすべてのメトリクスを検索して参照する • 問題があることを通知するアラームを作成/編集する Amazon CloudWatch でのモニタリング CloudWatch を使用して Amazon DynamoDB をモニタリングすることで、Amazon DynamoDB から 未加工データを収集し、リアルタイムに近い読み取り可能なメトリクスに加工することができます。 これらの統計は 2 週間記録されるため、履歴情報にアクセスしてウェブアプリケーションまたはサー ビスの動作をより的確に把握することができます。デフォルトでは、Amazon DynamoDB メトリック スデータは CloudWatch に自動的に送信されます。詳細については、「Amazon CloudWatch とは何 ですか?」を参照してください。」 (Amazon CloudWatch ユーザーガイド) を参照してください。 トピック • Amazon DynamoDB のメトリクスとディメンション (p. 497) • Amazon DynamoDB のメトリクスの使用方法 (p. 508) • Amazon DynamoDB をモニタリングする CloudWatch アラームの作成 (p. 509) Amazon DynamoDB のメトリクスとディメンション DynamoDB を操作するとき、以下のメトリックスとディメンションが CloudWatch に送信されます。 以下の手順を使用して、Amazon DynamoDB のメトリクスを表示できます。 メトリックスを表示するには (コンソール) メトリクスはまずサービスの名前空間ごとにグループ化され、次に各名前空間内のさまざまなディメ ンションの組み合わせごとにグループ化されます。 1. https://console.aws.amazon.com/cloudwatch/にある CloudWatch コンソールを開きます。 2. ナビゲーションペインで メトリクスを選択します。 3. 名前空間に [DynamoDB] を選択します。 メトリックスを表示するには (CLI) • コマンドプロンプトで、次のコマンドを使用します。 aws cloudwatch list-metrics --namespace "AWS/DynamoDB" CloudWatch では、Amazon DynamoDB の以下のメトリクスが表示されます。 Amazon DynamoDB のディメンションとメトリックス Amazon DynamoDB が Amazon CloudWatch に送信するメトリックスおよびディメンションは次のと おりです。 DynamoDB Metrics The following metrics are available from Amazon DynamoDB. Note that DynamoDB only sends metrics to CloudWatch when they have a non-zero value. For example, the UserErrors metric is incremented whenever a request generates an HTTP 400 status code. If no HTTP 400 errors were encountered during a time period, CloudWatch will not provide metrics for UserErrors during that period. API Version 2012-08-10 497 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Note Amazon CloudWatch aggregates the following DynamoDB metrics at one-minute intervals: • ConditionalCheckFailedRequests • ConsumedReadCapacityUnits • ConsumedWriteCapacityUnits • ReadThrottleEvents • ReturnedBytes • ReturnedItemCount • ReturnedRecordsCount • SuccessfulRequestLatency • SystemErrors • ThrottledRequests • UserErrors • WriteThrottleEvents For all other DynamoDB metrics, the aggregation granularity is five minutes. Not all statistics, such as Average or Sum, are applicable for every metric. However, all of these values are available through the Amazon DynamoDB console, or by using the CloudWatch console, AWS CLI, or AWS SDKs for all metrics. In the following table, each metric has a list of Valid Statistics that is applicable to that metric. Metric Description ConditionalCheckFailedRequests The number of failed attempts to perform conditional writes. The PutItem, UpdateItem, and DeleteItem operations let you provide a logical condition that must evaluate to true before the operation can proceed. If this condition evaluates to false, ConditionalCheckFailedRequests is incremented by one. Note A failed conditional write will result in an HTTP 400 error (Bad Request). These events are reflected in the ConditionalCheckFailedRequests metric, but not in the UserErrors metric. Units: Count Dimensions: TableName Valid Statistics: • Minimum • Maximum • Average • SampleCount • Sum ConsumedReadCapacityUnits The number of read capacity units consumed over the specified time period, so you can track how much of your provisioned API Version 2012-08-10 498 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Metric Description throughput is used. You can retrieve the total consumed read capacity for a table and all of its global secondary indexes, or for a particular global secondary index. For more information, see Provisioned Throughput in Amazon DynamoDB. Note Use the Sum statistic to calculate the consumed throughput. For example, get the Sum value over a span of one minute, and divide it by the number of seconds in a minute (60) to calculate the average ConsumedReadCapacityUnits per second (recognizing that this average will not highlight any large but brief spikes in read activity that occurred during that minute). You can compare the calculated value to the provisioned throughput value you provide DynamoDB. Units: Count Dimensions: TableName, GlobalSecondaryIndexName Valid Statistics: • Minimum – Minimum number of read capacity units consumed by any individual request to the table or index. • Maximum – Maximum number of read capacity units consumed by any individual request to the table or index. • Average – Average per-request read capacity consumed. • Sum – Total read capacity units consumed. This is the most useful statistic for the ConsumedReadCapacityUnits metric. • SampleCount – Number of requests to DynamoDB that consumed read capacity. API Version 2012-08-10 499 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Metric Description ConsumedWriteCapacityUnits The number of write capacity units consumed over the specified time period, so you can track how much of your provisioned throughput is used. You can retrieve the total consumed write capacity for a table and all of its global secondary indexes, or for a particular global secondary index. For more information, see Provisioned Throughput in Amazon DynamoDB. Note Use the Sum statistic to calculate the consumed throughput. For example, get the Sum value over a span of one minute, and divide it by the number of seconds in a minute (60) to calculate the average ConsumedWriteCapacityUnits per second (recognizing that this average will not highlight any large but brief spikes in write activity that occurred during that minute). You can compare the calculated value to the provisioned throughput value you provide DynamoDB. Units: Count Dimensions: TableName, GlobalSecondaryIndexName Valid Statistics: • Minimum – Minimum number of write capacity units consumed by any individual request to the table or index. • Maximum – Maximum number of write capacity units consumed by any individual request to the table or index. • Average – Average per-request write capacity consumed. • Sum – Total write capacity units consumed. This is the most useful statistic for the ConsumedWriteCapacityUnits metric. • SampleCount – Number of requests to DynamoDB that consumed write capacity. API Version 2012-08-10 500 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Metric Description OnlineIndexConsumedWriteCapacity The number of write capacity units consumed when adding a new global secondary index to a table. If the write capacity of the index is too low, incoming write activity during the backfill phase might be throttled; this can increase the time it takes to create the index. You should monitor this statistic while the index is being built to determine whether the write capacity of the index is underprovisioned. You can adjust the write capacity of the index using the UpdateTable operation, even while the index is still being built. Note that the ConsumedWriteCapacityUnits metric for the index does not include the write throughput consumed during index creation. Units: Count Dimensions: TableName, GlobalSecondaryIndexName Valid Statistics: • Minimum • Maximum • Average • SampleCount • Sum OnlineIndexPercentageProgress The percentage of completion when a new global secondary index is being added to a table. DynamoDB must first allocate resources for the new index, and then backfill attributes from the table into the index. For large tables, this process might take a long time. You should monitor this statistic to view the relative progress as DynamoDB builds the index. Units: Count Dimensions: TableName, GlobalSecondaryIndexName Valid Statistics: • Minimum • Maximum • Average • SampleCount • Sum API Version 2012-08-10 501 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Metric Description OnlineIndexThrottleEvents The number of write throttle events that occur when adding a new global secondary index to a table. These events indicate that the index creation will take longer to complete, because incoming write activity is exceeding the provisioned write throughput of the index. You can adjust the write capacity of the index using the UpdateTable operation, even while the index is still being built. Note that the WriteThrotttleEvents metric for the index does not include any throttle events that occur during index creation. Units: Count Dimensions: TableName, GlobalSecondaryIndexName Valid Statistics: • Minimum • Maximum • Average • SampleCount • Sum ProvisionedReadCapacityUnits The number of provisioned read capacity units for a table or a global secondary index. The TableName dimension returns the ProvisionedReadCapacityUnits for the table, but not for any global secondary indexes. To view ProvisionedReadCapacityUnits for a global secondary index, you must specify both TableName and GlobalSecondaryIndex. Units: Count Dimensions: TableName, GlobalSecondaryIndexName Valid Statistics: • Minimum – Lowest setting for provisioned read capacity. If you use UpdateTable to increase read capacity, this metric shows the lowest value of provisioned ReadCapacityUnits during this time period. • Maximum – Highest setting for provisioned read capacity. If you use UpdateTable to decrease read capacity, this metric shows the highest value of provisioned ReadCapacityUnits during this time period. • Average – Average provisioned read capacity. The ProvisionedReadCapacityUnits metric is published at five-minute intervals. Therefore, if you rapidly adjust the provisioned read capacity units, this statistic might not reflect the true average. API Version 2012-08-10 502 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Metric Description ProvisionedWriteCapacityUnits The number of provisioned write capacity units for a table or a global secondary index The TableName dimension returns the ProvisionedWriteCapacityUnits for the table, but not for any global secondary indexes. To view ProvisionedWriteCapacityUnits for a global secondary index, you must specify both TableName and GlobalSecondaryIndex. Units: Count Dimensions: TableName, GlobalSecondaryIndexName Valid Statistics: • Minimum – Lowest setting for provisioned write capacity. If you use UpdateTable to increase write capacity, this metric shows the lowest value of provisioned WriteCapacityUnits during this time period. • Maximum – Highest setting for provisioned write capacity. If you use UpdateTable to decrease write capacity, this metric shows the highest value of provisioned WriteCapacityUnits during this time period. • Average – Average provisioned write capacity. The ProvisionedWriteCapacityUnits metric is published at five-minute intervals. Therefore, if you rapidly adjust the provisioned write capacity units, this statistic might not reflect the true average. ReadThrottleEvents Requests to DynamoDB that exceed the provisioned read capacity units for a table or a global secondary index. A single request can result in multiple events. For example, a BatchGetItem that reads 10 items is processed as ten GetItem events. For each event, ReadThrottleEvents is incremented by one if that event is throttled. The ThrottledRequests metric for the entire BatchGetItem is not incremented unless all ten of the GetItem events are throttled. The TableName dimension returns the ReadThrottleEvents for the table, but not for any global secondary indexes. To view ReadThrottleEvents for a global secondary index, you must specify both TableName and GlobalSecondaryIndex. Units: Count Dimensions: TableName, GlobalSecondaryIndexName Valid Statistics: • SampleCount • Sum API Version 2012-08-10 503 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Metric Description ReturnedBytes The number of bytes returned by GetRecords operations (Amazon DynamoDB Streams) during the specified time period. Units: Bytes Dimensions: Operation, StreamLabel, TableName Valid Statistics: • Minimum • Maximum • Average • SampleCount • Sum ReturnedItemCount The number of items returned by Query or Scan operations during the specified time period. Note that the number of items returned is not necessarily the same as the number of items that were evaluated. For example, suppose you requested a Scan on a table that had 100 items, but specified a FilterExpression that narrowed the results so that only 15 items were returned. In this case, the response from Scan would contain a ScanCount of 100 and a Count of 15 returned items. Units: Count Dimensions: TableName Valid Statistics: • Minimum • Maximum • Average • SampleCount • Sum ReturnedRecordsCount The number of stream records returned by GetRecords operations (Amazon DynamoDB Streams) during the specified time period. Units: Count Dimensions: Operation, StreamLabel, TableName Valid Statistics: • Minimum • Maximum • Average • SampleCount • Sum API Version 2012-08-10 504 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Metric Description SuccessfulRequestLatency Successful requests to DynamoDB or Amazon DynamoDB Streams during the specified time period. SuccessfulRequestLatency can provide two different kinds of information: • The elapsed time for successful requests (Minimum, Maximum, Sum, or Average). • The number of successful requests (SampleCount). SuccessfulRequestLatency reflects activity only within DynamoDB or Amazon DynamoDB Streams, and does not take into account network latency or client-side activity. Units: Milliseconds Dimensions: TableName, Operation Valid Statistics: • Minimum • Maximum • Average • SampleCount SystemErrors Requests to DynamoDB or Amazon DynamoDB Streams that generate an HTTP 500 status code during the specified time period. An HTTP 500 usually indicates an internal service error. Units: Count Dimensions: All dimensions Valid Statistics: • Sum • SampleCount API Version 2012-08-10 505 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Metric Description ThrottledRequests Requests to DynamoDB that exceed the provisioned throughput limits on a resource (such as a table or an index). ThrottledRequests is incremented by one if any event within a request exceeds a provisioned throughput limit. For example, if you update an item in a table with global secondary indexes, there are multiple events—a write to the table, and a write to each index. If one or more of these events are throttled, then ThrottledRequests is incremented by one. Note In a batch request (BatchGetItem or BatchWriteItem), ThrottledRequests is only incremented if every request in the batch is throttled. If any individual request within the batch is throttled, one of the following metrics is incremented: • ReadThrottleEvents – For a throttled GetItem event within BatchGetItem. • WriteThrottleEvents – For a throttled PutItem or DeleteItem event within BatchWriteItem. To gain insight into which event is throttling a request, compare ThrottledRequests with the ReadThrottleEvents and WriteThrottleEvents for the table and its indexes. Note A throttled request will result in an HTTP 400 status code. All such events are reflected in the ThrottledRequests metric, but not in the UserErrors metric. Units: Count Dimensions: TableName, Operation Valid Statistics: • Sum • SampleCount API Version 2012-08-10 506 Amazon DynamoDB 開発者ガイド メトリクスとディメンション Metric Description UserErrors Requests to DynamoDB or Amazon DynamoDB Streams that generate an HTTP 400 status code during the specified time period. An HTTP 400 usually indicates a client-side error such as an invalid combination of parameters, attempting to update a nonexistent table, or an incorrect request signature. All such events are reflected in the UserErrors metric, except for the following: • ProvisionedThroughputExceededException – See the ThrottledRequests metric in this section. • ConditionalCheckFailedException – See the ConditionalCheckFailedRequests metric in this section. UserErrors represents the aggregate of HTTP 400 errors for DynamoDB or Amazon DynamoDB Streams requests for the current region and the current AWS account. Units: Count Valid Statistics: • Sum • SampleCount WriteThrottleEvents Requests to DynamoDB that exceed the provisioned write capacity units for a table or a global secondary index. A single request can result in multiple events. For example, a PutItem request on a table with three global secondary indexes would result in four events—the table write, and each of the three index writes. For each event, the WriteThrottleEvents metric is incremented by one if that event is throttled. For single PutItem requests, if any of the events are throttled, ThrottledRequests is also incremented by one. For BatchWriteItem, the ThrottledRequests metric for the entire BatchWriteItem is not incremented unless all of the individual PutItem or DeleteItem events are throttled. The TableName dimension returns the WriteThrottleEvents for the table, but not for any global secondary indexes. To view WriteThrottleEvents for a global secondary index, you must specify both TableName and GlobalSecondaryIndex. Units: Count Dimensions: TableName, GlobalSecondaryIndexName Valid Statistics: • Sum • SampleCount API Version 2012-08-10 507 Amazon DynamoDB 開発者ガイド メトリクスの使用 Dimensions for DynamoDB Metrics The metrics for DynamoDB are qualified by the values for the account, table name, global secondary index name, or operation. You can use the CloudWatch console to retrieve DynamoDB data along any of the dimensions in the table below. Dimension Description GlobalSecondaryIndexName This dimension limits the data to a global secondary index on a table. If you specify GlobalSecondaryIndexName, you must also specify TableName. Operation This dimension limits the data to one of the following DynamoDB operations: • PutItem • DeleteItem • UpdateItem • GetItem • BatchGetItem • Scan • Query • BatchWriteItem In addition, you can limit the data to the following Amazon DynamoDB Streams operation: • GetRecords StreamLabel This dimension limits the data to a specific stream label. It is used with metrics originating from Amazon DynamoDB Streams GetRecords operations. TableName This dimension limits the data to a specific table. This value can be any table name in the current region and the current AWS account. Amazon DynamoDB のメトリクスの使用方法 Amazon DynamoDB によってレポートされるメトリクスが提供する情報は、さまざまな方法で分析で きます。以下のリストは、メトリクスの一般的な利用方法をいくつか示しています。ここで紹介する のは開始するための提案事項です。すべてを網羅しているわけではありません。 どのように 関連するメトリクス How can I determine how much of my provisioned throughput is being used? 指定した期間に ConsumedReadCapacityUnits または ConsumedWriteCapacityUnits をモニタリングして、プロビ ジョニングしたスループットがどれだけ使用されているかトラッ キングできます。 How can I determine which requests exceed the provisioned throughput limits of a table? リクエスト内で任意のイベントがプロビジョンドスループッ トの制限を超過した場合、ThrottledRequests は 1 ずつ増 加します。その後、どのイベントがリクエストをスロットリ ングしているかを確認するには、ThrottledRequests と、 そのテーブルとインデックスの ReadThrottleEvents と WriteThrottleEvents メトリックスを比較してください。 API Version 2012-08-10 508 Amazon DynamoDB 開発者ガイド アラームの作成 どのように 関連するメトリクス How can I determine if any system errors occurred? SystemErrors をモニタリングして、リクエストが HTTP 500 (サーバーエラー) コードを生じさせたかを確認できます。通常、 このメトリックスはゼロと等しくなります。ゼロでない場合、調 査が必要な可能性があります。 Note 項目の操作中に内部サーバーエラーが発生することがあ ります。これはテーブルの存続期間中に発生すると予想 されます。失敗したリクエストは速やかに再試行できま す。 Amazon DynamoDB をモニタリングする CloudWatch アラームの作成 CloudWatch アラームを作成できます。これは、アラームの状態が変わったときに Amazon SNS メッ セージを送信します。 アラームは、指定期間にわたって単一のメトリクスを監視し、その値と複 数期間に対するしきい値との比較結果に基づいて 1 つ以上のアクションを実行します。アクション は、Amazon SNS トピックまたは Auto Scaling ポリシーに送信される通知です。 アラームは、持続 している状態変化に対してのみアクションを呼び出します。CloudWatch アラームはそれが特定の状 態にあるという理由だけではアクションを呼び出しません。アクションを呼び出すには、状態が変更 され、その状態が特定の期間にわたって維持されている必要があります。 読み取り容量全体を使い切る前にどのように通知を受け取るこ とができますか。 1. Amazon SNS トピック arn:aws:sns:us-east-1:123456789012:capacity-alarm を作成し ます。 詳細については、「Amazon Simple Notification Service をセットアップする」を参照してくださ い。 2. アラームを作成します。この例では、5 つの読み込みキャパシティーユニットがプロビジョニン グされた容量を前提としています。 Prompt>aws cloudwatch put-metric-alarm \ --alarm-name ReadCapacityUnitsLimitAlarm \ --alarm-description "Alarm when read capacity reaches 80% of my provisioned read capacity" \ --namespace AWS/DynamoDB \ --metric-name ConsumedReadCapacityUnits \ --dimensions Name=TableName,Value=myTable \ --statistic Sum \ --threshold 240 \ --comparison-operator GreaterThanOrEqualToThreshold \ --period 60 \ --evaluation-periods 1 \ --alarm-actions arn:aws:sns:us-east-1:123456789012:capacity-alarm 3. アラームのテストを行います。 API Version 2012-08-10 509 Amazon DynamoDB 開発者ガイド アラームの作成 Prompt>aws cloudwatch set-alarm-state --alarm-name ReadCapacityUnitsLimitAlarm --state-reason "initializing" --state-value OK Prompt>aws cloudwatch set-alarm-state --alarm-name ReadCapacityUnitsLimitAlarm --state-reason "initializing" --state-value ALARM Note アラームは、消費された読み取り容量が 1 分間 (60 秒) で少なくとも毎秒 4 ユニット (プロ ビジョニングされた 5 つの読み取り容量の 80%) になるとアクティブ化されます。ですか ら、threshold は 240 読み取りキャパシティーユニット (4ユニット/秒 * 60 秒) です。読み 取り容量が更新されるたびに、アラーム計算を適切に更新する必要があります。DynamoDB コンソールを使用してアラームを作成すると、このプロセスを回避することができます。そ うすることで、アラームが自動的に更新されます。 テーブルにプロビジョニングされたスループット制限をリクエ ストが超えた場合にどのように通知を受け取ることができます か。 1. Amazon SNS トピック arn:aws:sns:us-east-1:123456789012:requests-exceedingthroughput を作成します。 詳細については、「Amazon Simple Notification Service をセットアップする」を参照してくださ い。 2. アラームを作成します。 Prompt>aws cloudwatch put-metric-alarm \ --alarm-name RequestsExceedingThroughputAlarm\ --alarm-description "Alarm when my requests are exceeding provisioned throughput limits of a table" \ --namespace AWS/DynamoDB \ --metric-name ThrottledRequests \ --dimensions Name=TableName,Value=myTable \ --statistic Sum \ --threshold 0 \ --comparison-operator GreaterThanThreshold \ --period 300 \ --unit Count \ --evaluation-periods 1 \ --alarm-actions arn:aws:sns:us-east-1:123456789012:requests-exceedingthroughput 3. アラームのテストを行います。 Prompt>aws cloudwatch set-alarm-state --alarm-name RequestsExceedingThroughputAlarm --state-reason "initializing" --statevalue OK API Version 2012-08-10 510 Amazon DynamoDB 開発者ガイド AWS CloudTrail を使用した DynamoDB オペレーションのログ記録 Prompt>aws cloudwatch set-alarm-state --alarm-name RequestsExceedingThroughputAlarm --state-reason "initializing" --statevalue ALARM システムエラーが発生した場合にどのように通知を受け取るこ とができますか。 1. Amazon SNS トピック arn:aws:sns:us-east-1:123456789012:notify-on-systemerrors を作成します。 詳細については、「Amazon Simple Notification Service をセットアップする」を参照してくださ い。 2. アラームを作成します。 Prompt>aws cloudwatch put-metric-alarm \ --alarm-name SystemErrorsAlarm \ --alarm-description "Alarm when system errors occur" \ --namespace AWS/DynamoDB \ --metric-name SystemErrors \ --dimensions Name=TableName,Value=myTable \ --statistic Sum \ --threshold 0 \ --comparison-operator GreaterThanThreshold \ --period 60 \ --unit Count \ --evaluation-periods 1 \ --alarm-actions arn:aws:sns:us-east-1:123456789012:notify-on-systemerrors 3. アラームのテストを行います。 Prompt>aws cloudwatch set-alarm-state --alarm-name SystemErrorsAlarm -state-reason "initializing" --state-value OK Prompt>aws cloudwatch set-alarm-state --alarm-name SystemErrorsAlarm -state-reason "initializing" --state-value ALARM AWS CloudTrail を使用した DynamoDB オペレー ションのログ記録 DynamoDB は CloudTrail と統合されています。CloudTrail は、AWS アカウントで DynamoDB に よって行われたか、それに代わって行われた 低レベル API リクエストをキャプチャし、指定した Amazon S3 バケットにログファイルを渡すサービスです。CloudTrail は、DynamoDB コンソールま たは DynamoDB 低レベル API から行われた呼び出しをキャプチャします。CloudTrail によって収集 された情報を使用して、DynamoDB に対してどのようなリクエストが行われたか(リクエストの実行 元 IP アドレス、実行者、実行日時など)を判断できます。CloudTrail の詳細(設定して有効にする方 法など)については、AWS CloudTrail User Guideを参照してください。 API Version 2012-08-10 511 Amazon DynamoDB 開発者ガイド CloudTrail での DynamoDB 情報 CloudTrail での DynamoDB 情報 AWS アカウントで CloudTrail のログ記録を有効にすると、DynamoDB アクションに対する低レベル API 呼び出しがログファイルに記録されます。DynamoDB レコードは、他の AWS サービスレコー ドと一緒にログファイルに記録されます。CloudTrail は、期間とファイルサイズに基づいて、新しい ファイルをいつ作成して書き込むかを決定します。 以下の DynamoDB アクションがサポートされています。 • CreateTable • DeleteTable • DescribeTable • ListTables • UpdateTable • DescribeReservedCapacity • DescribeReservedCapacityOfferings • PurchaseReservedCapacityOfferings 以下の DynamoDB ストリーム アクションもサポートされています。 • DescribeStream • ListStreams 各ログエントリには、誰がリクエストを生成したかに関する情報が含まれます。ログのユーザー ID 情 報は、リクエストが、ルートまたは IAM ユーザーの認証情報を使用して送信されたか、ロールまたは フェデレーションユーザーの一時的なセキュリティ認証情報を使用して送信されたか、あるいは別の AWS サービスによって送信されたかを確認するのに役立ちます。詳細については、CloudTrail Event Reference の userIdentity フィールドを参照してください。 必要な場合はログファイルを自身のバケットに保管できますが、ログファイルを自動的にアーカイブ または削除するにように Amazon S3 ライフサイクルルールを定義することもできます。デフォルト では Amazon S3 のサーバー側の暗号化 (SSE) を使用して、ログファイルが暗号化されます。 ログファイルの配信時にすぐにアクションを実行する場合、新しいログファイルの配信時に CloudTrail により Amazon SNS 通知を発行することを選択できます。詳細については、「Amazon SNS 通知の構成」を参照してください。 また、複数の AWS リージョンと複数の AWS アカウントからの DynamoDB ログファイルを 1 つの Amazon S3 バケットに集約することもできます。詳細については、「Receiving CloudTrail Log Files from Multiple Regions」を参照してください。 DynamoDB ログファイルエントリの概要 CloudTrail ログファイルには、複数の JSON 形式イベントで構成される 1 つ以上のログエントリを 記録できます。ログエントリは任意の送信元からの単一のリクエストを表し、リクエストされたアク ション、パラメーター、アクションの日時などに関する情報を含みます。ログエントリは、特定の順 序になるように生成されるわけではありません。つまり、低レベル DynamoDB API 呼び出しの順序付 けられたスタック トレースではありません。 CloudTrail ログの例を次に示します。 {"Records": [ { "eventVersion": "1.03", "userIdentity": { API Version 2012-08-10 512 Amazon DynamoDB 開発者ガイド DynamoDB ログファイルエントリの概要 "type": "AssumedRole", "principalId": "AKIAIOSFODNN7EXAMPLE:bob", "arn": "arn:aws:sts::111122223333:assumed-role/users/bob", "accountId": "111122223333", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2015-05-28T18:06:01Z" }, "sessionIssuer": { "type": "Role", "principalId": "AKIAI44QH8DHBEXAMPLE", "arn": "arn:aws:iam::444455556666:role/admin-role", "accountId": "444455556666", "userName": "bob" } } }, "eventTime": "2015-05-01T07:24:55Z", "eventSource": "dynamodb.amazonaws.com", "eventName": "CreateTable", "awsRegion": "us-west-2", "sourceIPAddress": "192.0.2.0", "userAgent": "console.aws.amazon.com", "requestParameters": { "provisionedThroughput": { "writeCapacityUnits": 10, "readCapacityUnits": 10 }, "tableName": "Music", "keySchema": [ { "attributeName": "Artist", "keyType": "HASH" }, { "attributeName": "SongTitle", "keyType": "RANGE" } ], "attributeDefinitions": [ { "attributeType": "S", "attributeName": "Artist" }, { "attributeType": "S", "attributeName": "SongTitle" } ] }, "responseElements": {"tableDescription": { "tableName": "Music", "attributeDefinitions": [ { "attributeType": "S", "attributeName": "Artist" }, API Version 2012-08-10 513 Amazon DynamoDB 開発者ガイド DynamoDB ログファイルエントリの概要 { "attributeType": "S", "attributeName": "SongTitle" } ], "itemCount": 0, "provisionedThroughput": { "writeCapacityUnits": 10, "numberOfDecreasesToday": 0, "readCapacityUnits": 10 }, "creationDateTime": "May 1, 2015 7:24:55 AM", "keySchema": [ { "attributeName": "Artist", "keyType": "HASH" }, { "attributeName": "SongTitle", "keyType": "RANGE" } ], "tableStatus": "CREATING", "tableSizeBytes": 0 }}, "requestID": "KAVGJR1Q0I5VHF8FS8V809EV7FVV4KQNSO5AEMVJF66Q9ASUAAJG", "eventID": "a8b5f864-480b-43bf-bc22-9b6d77910a29", "eventType": "AwsApiCall", "apiVersion": "2012-08-10", "recipientAccountId": "111122223333" }, { "eventVersion": "1.03", "userIdentity": { "type": "AssumedRole", "principalId": "AKIAIOSFODNN7EXAMPLE:bob", "arn": "arn:aws:sts::111122223333:assumed-role/users/bob", "accountId": "444455556666", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2015-05-28T18:06:01Z" }, "sessionIssuer": { "type": "Role", "principalId": "AKIAI44QH8DHBEXAMPLE", "arn": "arn:aws:iam::444455556666:role/admin-role", "accountId": "444455556666", "userName": "bob" } } }, "eventTime": "2015-05-04T02:43:11Z", "eventSource": "dynamodb.amazonaws.com", "eventName": "DescribeTable", "awsRegion": "us-west-2", "sourceIPAddress": "192.0.2.0", API Version 2012-08-10 514 Amazon DynamoDB 開発者ガイド DynamoDB ログファイルエントリの概要 "userAgent": "console.aws.amazon.com", "requestParameters": {"tableName": "Music"}, "responseElements": null, "requestID": "DISTSH6DQRLCC74L48Q51LRBHFVV4KQNSO5AEMVJF66Q9ASUAAJG", "eventID": "c07befa7-f402-4770-8c1b-1911601ed2af", "eventType": "AwsApiCall", "apiVersion": "2012-08-10", "recipientAccountId": "111122223333" }, { "eventVersion": "1.03", "userIdentity": { "type": "AssumedRole", "principalId": "AKIAIOSFODNN7EXAMPLE:bob", "arn": "arn:aws:sts::111122223333:assumed-role/users/bob", "accountId": "111122223333", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2015-05-28T18:06:01Z" }, "sessionIssuer": { "type": "Role", "principalId": "AKIAI44QH8DHBEXAMPLE", "arn": "arn:aws:iam::444455556666:role/admin-role", "accountId": "444455556666", "userName": "bob" } } }, "eventTime": "2015-05-04T02:14:52Z", "eventSource": "dynamodb.amazonaws.com", "eventName": "UpdateTable", "awsRegion": "us-west-2", "sourceIPAddress": "192.0.2.0", "userAgent": "console.aws.amazon.com", "requestParameters": {"provisionedThroughput": { "writeCapacityUnits": 25, "readCapacityUnits": 25 }}, "responseElements": {"tableDescription": { "tableName": "Music", "attributeDefinitions": [ { "attributeType": "S", "attributeName": "Artist" }, { "attributeType": "S", "attributeName": "SongTitle" } ], "itemCount": 0, "provisionedThroughput": { "writeCapacityUnits": 10, "numberOfDecreasesToday": 0, "readCapacityUnits": 10, API Version 2012-08-10 515 Amazon DynamoDB 開発者ガイド DynamoDB ログファイルエントリの概要 "lastIncreaseDateTime": "May 3, 2015 11:34:14 PM" }, "creationDateTime": "May 3, 2015 11:34:14 PM", "keySchema": [ { "attributeName": "Artist", "keyType": "HASH" }, { "attributeName": "SongTitle", "keyType": "RANGE" } ], "tableStatus": "UPDATING", "tableSizeBytes": 0 }}, "requestID": "AALNP0J2L244N5O15PKISJ1KUFVV4KQNSO5AEMVJF66Q9ASUAAJG", "eventID": "eb834e01-f168-435f-92c0-c36278378b6e", "eventType": "AwsApiCall", "apiVersion": "2012-08-10", "recipientAccountId": "111122223333" }, { "eventVersion": "1.03", "userIdentity": { "type": "AssumedRole", "principalId": "AKIAIOSFODNN7EXAMPLE:bob", "arn": "arn:aws:sts::111122223333:assumed-role/users/bob", "accountId": "111122223333", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2015-05-28T18:06:01Z" }, "sessionIssuer": { "type": "Role", "principalId": "AKIAI44QH8DHBEXAMPLE", "arn": "arn:aws:iam::444455556666:role/admin-role", "accountId": "444455556666", "userName": "bob" } } }, "eventTime": "2015-05-04T02:42:20Z", "eventSource": "dynamodb.amazonaws.com", "eventName": "ListTables", "awsRegion": "us-west-2", "sourceIPAddress": "192.0.2.0", "userAgent": "console.aws.amazon.com", "requestParameters": null, "responseElements": null, "requestID": "3BGHST5OVHLMTPUMAUTA1RF4M3VV4KQNSO5AEMVJF66Q9ASUAAJG", "eventID": "bd5bf4b0-b8a5-4bec-9edf-83605bd5e54e", "eventType": "AwsApiCall", "apiVersion": "2012-08-10", "recipientAccountId": "111122223333" }, API Version 2012-08-10 516 Amazon DynamoDB 開発者ガイド DynamoDB ログファイルエントリの概要 { "eventVersion": "1.03", "userIdentity": { "type": "AssumedRole", "principalId": "AKIAIOSFODNN7EXAMPLE:bob", "arn": "arn:aws:sts::111122223333:assumed-role/users/bob", "accountId": "111122223333", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2015-05-28T18:06:01Z" }, "sessionIssuer": { "type": "Role", "principalId": "AKIAI44QH8DHBEXAMPLE", "arn": "arn:aws:iam::444455556666:role/admin-role", "accountId": "444455556666", "userName": "bob" } } }, "eventTime": "2015-05-04T13:38:20Z", "eventSource": "dynamodb.amazonaws.com", "eventName": "DeleteTable", "awsRegion": "us-west-2", "sourceIPAddress": "192.0.2.0", "userAgent": "console.aws.amazon.com", "requestParameters": {"tableName": "Music"}, "responseElements": {"tableDescription": { "tableName": "Music", "itemCount": 0, "provisionedThroughput": { "writeCapacityUnits": 25, "numberOfDecreasesToday": 0, "readCapacityUnits": 25 }, "tableStatus": "DELETING", "tableSizeBytes": 0 }}, "requestID": "4KBNVRGD25RG1KEO9UT4V3FQDJVV4KQNSO5AEMVJF66Q9ASUAAJG", "eventID": "a954451c-c2fc-4561-8aea-7a30ba1fdf52", "eventType": "AwsApiCall", "apiVersion": "2012-08-10", "recipientAccountId": "111122223333" } ]} API Version 2012-08-10 517 Amazon DynamoDB 開発者ガイド Amazon Redshift との統合 他の AWS のサービスと DynamoDB の統合 Amazon DynamoDB は他の AWS サービスと統合して、繰り返しタスクを自動化したり、複数のサー ビスにまたがるアプリケーションを作成したりできます。以下に例を示します。 • 同じリージョン内で、またはリージョン間で、DynamoDB データを Amazon S3 に定期的にエクス ポートします。 • Amazon EMR を使用して DynamoDB データに対する複雑なクエリを実行します。 • 完全なデータウェアハウジングソリューションのために、DynamoDB から Amazon Redshift にデー タをロードします。 トピック • DynamoDB から Amazon Redshift へのデータのロード (p. 518) • Amazon EMR 上の Apache Hive を使用した DynamoDB の処理 (p. 519) • AWS Data Pipeline を使用して DynamoDB データをエクスポートおよびインポートす る (p. 548) DynamoDB から Amazon Redshift へのデータの ロード Amazon Redshift は、高度なビジネスインテリジェンス機能と強力な SQL ベースのインターフェイス を使用して Amazon DynamoDB を補完します。DynamoDB テーブルのデータを Amazon Redshift に コピーすると、Amazon Redshift クラスター内の他のテーブルとの結合など、複雑なデータ分析のク エリを実行することができます。 プロビジョニングされたスループットの面から見ると、DynamoDB テーブルからのコピーオペ レーションによって、テーブルの読み込み容量が低下します。いずれにせよ、データをコピーし た後は、Amazon Redshift 内で SQL クエリを実行しても DynamoDB に影響はありません。これ は、DynamoDB 自身に対してではなく、DynamoDB からのデータのコピーに対してクエリが実行さ れるためです。 DynamoDB テーブルからデータをロードするには、まずデータのロード先として Amazon Redshift テーブルを作成する必要があります。注意していただきたいのは、NoSQL 環境から SQL 環境にデー タをコピーしていることと、1 つの環境での特定のルールが他の環境には適用されないことです。考 慮すべき相違点の例を以下に示します。 API Version 2012-08-10 518 Amazon DynamoDB 開発者ガイド Amazon EMR との統合 • DynamoDB テーブル名には、最大 255 文字を指定できます。これには、"."(ドット)および "-"(ダッシュ)を含み、大文字と小文字が区別されます。Amazon Redshift テーブル名は 127 文字 に制限され、ドットおよびダッシュは含まず、大文字と小文字は区別されません。さらに、テーブ ル名には、Amazon Redshift の予約語と重複しない値を指定する必要があります。 • DynamoDB では、SQL の NULL の概念がサポートされません。Amazon Redshift におい て、DynamoDB 内の空白またはブランクの属性値をどのように解釈するか、つまり、NULL と空白 フィールドのどちらで処理するかを指定する必要があります。 • DynamoDB のデータ型は、Amazon Redshift のデータ型と直接には対応していません。Amazon Redshift テーブルの各列において、データ型が正しく、DynamoDB からのデータに対応したサイズ であることを確認する必要があります。 Amazon Redshift SQL からの COPY コマンドの例を以下に示します。 copy favoritemovies from 'dynamodb://my-favorite-movies-table' credentials 'aws_access_key_id=<Your-Access-KeyID>;aws_secret_access_key=<Your-Secret-Access-Key>' readratio 50; この例では、DynamoDB 内のソーステーブルは、my-favorite-movies-table です。Amazon Redshift 内のターゲットテーブルは、favoritemovies です。readratio 50 節により、プロビ ジョニングされたスループットの消費される割合が制限されます。この場合、COPY コマンドで は、my-favorite-movies-table用にプロビジョニングされた読み込みキャパシティーの 50% 以下 しか使用されません。この割合については、未使用のプロビジョニングされたスループットの平均よ りも小さい値に設定することを強くお勧めします。 DynamoDB から Amazon Redshift へのデータロードに関する詳細な説明については、Amazon Redshift Database Developer Guide 内の以下のセクションを参照してください。 • DynamoDB テーブルからのデータのロード • The COPY command • COPY の例 Amazon EMR 上の Apache Hive を使用した DynamoDB の処理 Amazon EMR 上で実行するデータウェアハウスアプリケーション、Apache Hive と Amazon DynamoDB を統合します。Hive は DynamoDB テーブルのデータの読み込みと書き込みができ、以下 を許可します。 • SQL のような言語 (HiveQL) を使用してライブ DynamoDB データにクエリを実行します。 • DynamoDB テーブルから Amazon S3 バケット (またはその逆) にデータをコピーします。 • DynamoDB テーブルから Hadoop Distributed File System (HDFS) (またはその逆) にデータをコピー します。 • DynamoDB テーブルで結合操作を実行します。 トピック • 概要 (p. 520) • チュートリアル: Amazon DynamoDB および Apache Hive の使用 (p. 520) • Hive に外部テーブルを作成します。 (p. 527) • HiveQL ステートメントの処理 (p. 529) API Version 2012-08-10 519 Amazon DynamoDB 開発者ガイド 概要 • DynamoDB でのデータのクエリ (p. 530) • Amazon DynamoDB でデータを出し入れする (p. 532) • パフォーマンスの調節 (p. 544) 概要 Amazon EMR は、大量のデータを高いコスト効率で素早くかつ簡単に処理するためのサービスで す。Amazon EMR を使用するには、Hadoop オープンソースフレームワークを実行する Amazon EC2 インスタンスのマネージド型クラスターを起動します。Hadoop は、タスクがクラスター内の複数の ノードにマップされる MapReduce アルゴリズムを実装する分散アプリケーションです。各ノード は、指定された作業を他のノードと並列に処理します。最後に、出力は単一のノードにまとめられ、 最終結果を提供します。 永続的または一時的となるように、Amazon EMR クラスターの起動を選択できます。 • 永続的なクラスターはシャットダウンするまで実行されます。永続的なクラスターはデータ分析、 データウェアハウス、または他のインタラクティブな使用などに最適です。 • 一時的なクラスターは、ジョブフローが処理されるまでの間実行され、自動的にシャットダウンさ れます。一時的なクラスターは、スクリプトの実行などの定期的な処理タスクに最適です。 Amazon EMR アーキテクチャーおよび管理の詳細については、「Amazon EMR 管理ガイド」を参照 してください。 Amazon EMR クラスターを起動する場合、Amazon EC2 インスタンスの開始値とタイプを指定しま す。また、クラスターで実行する他の分散アプリケーション (Hadoop 自体に加えて) も指定します。 これらのアプリケーションには Hue、Mahout、Pig、Spark などが含まれます。 Amazon EMR 用アプリケーションの詳細については、「Amazon EMR リリースガイド」を参照して ください。 クラスター構成によっては、次のノードタイプのうちの 1 つ以上を持つことができます。 • マスターノード – クラスターの管理、コアおよびタスクインスタンスグループへの MapReduce 実 行可能ファイルおよび raw データのサブセットのディストリビューションを調整します。また、実 行される各タスクのステータスを追跡し、インスタンスグループの状態を監視します。クラスター にマスターノードは 1 つしか存在しません。 • コアノード – Hadoop Distributed File System (HDFS) を使用して MapReduce タスクを実行し、 データを格納します。 • タスクノード (オプション) — MapReduce タスクを実行します。 チュートリアル: Amazon DynamoDB および Apache Hive の使用 このチュートリアルでは、Amazon EMR クラスターを起動し、DynamoDB テーブルに格納されてい るデータを処理するため Apache Hive を使用します。 Hive は、複数のソースからのデータを処理して分析できる Hadoop 用のデータウェアハウスアプ リケーションです。Hive は、SQL のような言語である HiveQL を提供し、この言語を使用する と、Amazon EMR クラスターでローカルに保存されたデータ、または外部データソース (Amazon DynamoDB など) のデータを操作できます。 詳細については、「Hive のチュートリアル」を参照してください。 トピック API Version 2012-08-10 520 Amazon DynamoDB 開発者ガイド チュートリアル: Amazon DynamoDB および Apache Hive の使用 • 開始する前に (p. 521) • ステップ 1: Amazon EC2 キーペアの作成 (p. 521) • ステップ 2: Amazon EMR クラスターの起動 (p. 522) • ステップ 3: マスターノードに接続する (p. 522) • ステップ 4: HDFS にデータをロードする (p. 523) • ステップ 5: DynamoDB にデータをコピーします。 (p. 525) • ステップ 6: DynamoDB テーブル内のデータにクエリを実行する (p. 526) • ステップ 7: (オプション) クリーンアップする (p. 526) 開始する前に このチュートリアルでは、以下が必要になります。 • AWS アカウント。アカウントがない場合は、「AWS にサインアップする (p. 48)」を参照してくだ さい。 • SSH クライアント (Secure Shell)。SSH クライアントを使用して Amazon EMR クラスターのマス ターノードに接続して、インタラクティブコマンドを実行します。デフォルトでは、SSH クライ アントはほとんどの Linux、Unix、および Mac OS X インストールで使用できます。Windows ユー ザーは、SSH サポートがある PuTTY クライアントをダウンロードしてインストールできます。 次のステップ ステップ 1: Amazon EC2 キーペアの作成 (p. 521) ステップ 1: Amazon EC2 キーペアの作成 このステップでは、Amazon EMR マスターノードへの接続に必要な Amazon EC2 キーペアを作成し て、Hive コマンドを実行します。 1. AWS マネジメントコンソールにサインインをしたあと、https://console.aws.amazon.com/ec2/ に ある Amazon EC2 コンソールを開きます。 2. リージョンを選択します (US West (Oregon) など)。これは DynamoDB テーブルがあるのと同 じリージョンです。 3. ナビゲーションペインで、[Key Pairs] を選択します。 4. [Create Key Pair] を選択します。 5. [キーペア名] で、キーペアの名前を入力し (mykeypair など)、[作成] を選択します。 6. プライベートキーファイルをダウンロードします。ファイル名は .pem で終わります (mykeypair.pem など)。このプライベートキーファイルを安全な場所に保存します。このキー ファイルは、このキーペアで起動する Amazon EMR クラスターにアクセスするときに必要で す。 Important キーペアを紛失した場合は、Amazon EMR クラスターのマスターノードに接続できませ ん。 キーペアの詳細については、『Linux インスタンス用 Amazon EC2 ユーザーガイド』の 「Amazon EC2 のキーペア」を参照してください。 次のステップ ステップ 2: Amazon EMR クラスターの起動 (p. 522) API Version 2012-08-10 521 Amazon DynamoDB 開発者ガイド チュートリアル: Amazon DynamoDB および Apache Hive の使用 ステップ 2: Amazon EMR クラスターの起動 このステップでは、Amazon EMR クラスターを設定して起動します。Hive と DynamoDB のストレー ジハンドラはクラスターにインストールされています。 1. 2. Amazon EMR コンソール(https://console.aws.amazon.com/elasticmapreduce/)を開きます。 [Create Cluster] を選択します。 3. [クラスターの作成 - クイックオプション] ページで、次の作業を行います。 4. a. [クラスター名] で、クラスターの名前を入力します (My EMR cluster など)。 b. [EC2 キーペア] で、先に作成したキーペアを選択します。 その他の設定はデフォルトのままにしておきます。 [Create cluster] を選択します。 クラスターが起動されるまで数分かかる場合があります。Amazon EMR コンソールの [クラスターの 詳細] ページを使用して、進捗状況を監視できます。 ステータスが [Waiting] に変わると、クラスターは使用可能です。 クラスター上のログファイルと Amazon S3 Amazon EMR クラスターは、クラスターのステータス、およびデバッグ情報に関する情報を含むロ グファイルを生成します。デフォルトの [クラスターの作成 - クイックオプション] 設定には Amazon EMR ログの設定が含まれます。 存在しない場合、AWS マネジメントコンソール は Amazon S3 バケットを作成します。バケット名 は、aws-logs-account-id-region で、 account-id は AWS アカウント番号、region はクラ スターを起動したリージョンです (aws-logs-123456789012-us-west-2 など)。 Note Amazon S3 コンソールを使用して、ログファイルを表示できます。詳細については、 「Amazon EMR 管理ガイド」の「ログファイルを表示する」を参照してください。 このバケットをロギングに加えて他の目的のために使用できます。たとえば、データを Amazon DynamoDB から Amazon S3 にエクスポートする場合に、Hive スクリプトを保存する場所または送信 先としてバケットを使用できます。 次のステップ ステップ 3: マスターノードに接続する (p. 522) ステップ 3: マスターノードに接続する Amazon EMR クラスターのステータスが [Waiting] に変わると、SSH およびコマンドラインオペ レーションを使用してマスターノードに接続できます。 1. 2. 3. Amazon EMR コンソールで、ステータスを表示するにはクラスターの名前を選択します。 [クラスターの詳細] ページで、[マスターパブリック DNS] フィールドを見つけます。これ は、Amazon EMR クラスターのマスターノードのパブリック DNS 名です。 DNS 名の右側で、[SSH] リンクを選択します。 4. [SSH を使用してマスターノードに接続する] の手順に従います。 オペレーティングシステムに応じて、[Windows] タブまたは [Mac/Linux] タブを選択し、マスター ノードに接続する手順に従います。 API Version 2012-08-10 522 Amazon DynamoDB 開発者ガイド チュートリアル: Amazon DynamoDB および Apache Hive の使用 SSH または PuTTY を使用してマスターノードに接続すると、次のようなコマンドプロンプトが表示 されます。 [hadoop@ip-192-0-2-0 ~]$ 次のステップ ステップ 4: HDFS にデータをロードする (p. 523) ステップ 4: HDFS にデータをロードする このステップでは、Hadoop Distributed File System (HDFS) にデータファイルをコピーし、データ ファイルにマッピングされる外部 Hive テーブルを作成します。 サンプルデータをダウンロードします。 1. サンプルデータアーカイブをダウンロードします (features.zip)。 wget http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ samples/features.zip 2. アーカイブから features.txt ファイルを抽出します。 unzip features.zip 3. features.txt ファイルの最初の数行を表示します。 head features.txt 結果は以下のようになります。 1535908|Big Run|Stream|WV|38.6370428|-80.8595469|794 875609|Constable Hook|Cape|NJ|40.657881|-74.0990309|7 1217998|Gooseberry Island|Island|RI|41.4534361|-71.3253284|10 26603|Boone Moore Spring|Spring|AZ|34.0895692|-111.410065|3681 1506738|Missouri Flat|Flat|WA|46.7634987|-117.0346113|2605 1181348|Minnow Run|Stream|PA|40.0820178|-79.3800349|1558 1288759|Hunting Creek|Stream|TN|36.343969|-83.8029682|1024 533060|Big Charles Bayou|Bay|LA|29.6046517|-91.9828654|0 829689|Greenwood Creek|Stream|NE|41.596086|-103.0499296|3671 541692|Button Willow Island|Island|LA|31.9579389|-93.0648847|98 データファイルには、アメリカ地名委員会が提供するデータのサブセットが含まれています (http://geonames.usgs.gov/domestic/download_data.htm)。 API Version 2012-08-10 523 Amazon DynamoDB 開発者ガイド チュートリアル: Amazon DynamoDB および Apache Hive の使用 features.txt ファイルには、アメリカ地名委員会からのデータのサブセットが含まれています (http://geonames.usgs.gov/domestic/download_data.htm)。各行のフィールドは以下を表します。 • 地物 ID (一意の識別子) • 名前 • クラス (湖、森、川など) • 状態 • 緯度 (度) • 経度 (度) • 高さ (フィート) 4. コマンドプロンプトで、次のコマンドを入力します。 hive コマンドプロンプトがこれに変わります: hive> 5. 次の HiveQL ステートメントを入力して、ネイティブ Hive テーブルを作成します。 CREATE TABLE hive_features (feature_id BIGINT, feature_name STRING , feature_class STRING , state_alpha STRING, prim_lat_dec DOUBLE , prim_long_dec DOUBLE , elev_in_ft BIGINT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n'; 6. 次の HiveQL ステートメントを入力して、テーブルにデータをロードします。 LOAD DATA LOCAL INPATH './features.txt' OVERWRITE INTO TABLE hive_features; 7. これで、features.txt ファイルからのデータが入力されたネイティブ Hive テーブルが作成さ れました。確認するには、次の HiveQL ステートメントを入力します。 SELECT state_alpha, COUNT(*) FROM hive_features GROUP BY state_alpha; 出力には、状態のリストとそれぞれの地理的特徴の数が表示されます。 次のステップ API Version 2012-08-10 524 Amazon DynamoDB 開発者ガイド チュートリアル: Amazon DynamoDB および Apache Hive の使用 ステップ 5: DynamoDB にデータをコピーします。 (p. 525) ステップ 5: DynamoDB にデータをコピーします。 このステップでは、Hive テーブル (hive_features) から DynamoDB の新しいテーブルにデータを コピーします。 1. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 2. [Create Table] を選択します。 3. [DynamoDB テーブルの作成] ページで、次の操作を行います。 a. [テーブル] で、「##」を入力します。 b. [パーティションキー] フィールドの、[プライマリキー] に、「ID」を入力します。データ型 を [Number] に設定します。 [デフォルト設定の使用] をクリアします。[プロビジョニングされた容量] に、次を入力しま す。 • 読み込みキャパシティーユニット—10 • 書き込みキャパシティーユニット—10 [Create] を選択します。 4. Hive プロンプトでは、次の HiveQL ステートメントを入力します。 CREATE EXTERNAL TABLE ddb_features (feature_id BIGINT, feature_name STRING, feature_class STRING, state_alpha STRING, prim_lat_dec DOUBLE, prim_long_dec DOUBLE, elev_in_ft BIGINT) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES( "dynamodb.table.name" = "Features", "dynamodb.column.mapping"="feature_id:Id,feature_name:Name,feature_class:Class,state_al ); これで、Hive と DynamoDB の地物テーブルとの間のマッピングが確立されました。 5. 次の HiveQL ステートメントを入力して、DynamoDB にデータをインポートします。 INSERT OVERWRITE TABLE ddb_features SELECT feature_id, feature_name, feature_class, state_alpha, prim_lat_dec, prim_long_dec, elev_in_ft FROM hive_features; API Version 2012-08-10 525 Amazon DynamoDB 開発者ガイド チュートリアル: Amazon DynamoDB および Apache Hive の使用 Hive は Amazon EMR クラスターによって処理される MapReduce ジョブを送信します。ジョブ を完了するまでに数分かかります。 6. DynamoDB にデータがロードされたことを確認してください。 a. DynamoDB コンソールのナビゲーションペインで、[テーブル] を選択します。 b. 地物テーブルを選択し、[項目] タブを選択してデータを表示します。 次のステップ ステップ 6: DynamoDB テーブル内のデータにクエリを実行する (p. 526) ステップ 6: DynamoDB テーブル内のデータにクエリを実行す る このステップでは、HiveQL を使用して DynamoDB 内の地物テーブルにクエリを実行します。次の Hive クエリを試してください。 1. アルファベット順のすべての地物タイプ (feature_class)。 SELECT DISTINCT feature_class FROM ddb_features ORDER BY feature_class; 2. 「M」から始まるすべての湖。 SELECT feature_name, state_alpha FROM ddb_features WHERE feature_class = 'Lake' AND feature_name LIKE 'M%' ORDER BY feature_name; 3. 少なくとも 3 つの地物が 1 マイルより高い州 (5,280 フィート)。 SELECT state_alpha, feature_class, COUNT(*) FROM ddb_features WHERE elev_in_ft > 5280 GROUP by state_alpha, feature_class HAVING COUNT(*) >= 3 ORDER BY state_alpha, feature_class; 次のステップ ステップ 7: (オプション) クリーンアップする (p. 526) ステップ 7: (オプション) クリーンアップする チュートリアルは完了したので、続けてこのセクションから Amazon EMR の DynamoDB データの使 用方法の詳細について学ぶことができます。その間 Amazon EMR クラスターを維持して実行するこ ともできます。 API Version 2012-08-10 526 Amazon DynamoDB 開発者ガイド Hive に外部テーブルを作成します。 クラスターが不要になった場合は、それを終了し、関連するリソースを削除する必要があります。こ れは、不要なリソースに料金が発生しないようにするのに役立ちます。 1. 2. 3. Amazon EMR クラスターを終了します。 a. Amazon EMR コンソール(https://console.aws.amazon.com/elasticmapreduce/)を開きま す。 b. Amazon EMR クラスターを選択して、[終了] を選択し、確認します。 DynamoDB の地物テーブルを削除します。 a. https://console.aws.amazon.com/dynamodb/ にある DynamoDB コンソールを開きます。 b. ナビゲーションペインで、[ Tables] を選択します。 c. 地物テーブルを選択します。[アクション] メニューから、[テーブルの削除] を選択します。 Amazon EMR ログファイルを含む Amazon S3 バケットを削除します。 a. https://console.aws.amazon.com/s3/ にある Amazon S3 コンソールを開きます。 b. バケットのリストから、aws-logs- accountID-region を選択します。accountID は AWS アカウント番号で、#####はクラスターを起動したリージョンです。 c. [アクション] メニューから、[削除] を選択します。 Hive に外部テーブルを作成します。 チュートリアル: Amazon DynamoDB および Apache Hive の使用 (p. 520) で、DynamoDB テーブル にマッピングした外部 Hive テーブルを作成しました。外部テーブルに対して HiveQL ステートメント を発行すると、DynamoDB テーブルに読み取りと書き込みのオペレーションが渡されます。 外部テーブルは、他の場所で管理され格納されているデータソースへのポインタと考えることができ ます。この場合、基盤となるデータソースは DynamoDB テーブルです。(テーブルはすでに存在して いる必要があります。Hive 内から DynamoDB テーブルを作成、更新、または削除することはできま せん。)CREATE EXTERNAL TABLE ステートメントを使用して外部テーブルを作成します。その後、 データが Hive 内でローカルに保管されている DynamoDB のデータの操作に HiveQL を使用できま す。 Note 外部テーブルにデータを挿入するために INSERT ステートメントを使用でき、そこからデー タを選択するために SELECT ステートメントを使用できます。ただし、テーブル内のデータ の操作に UPDATE または DELETE ステートメントを使用することはできません。 外部テーブルが不要になった場合には、DROP TABLE ステートメントを使用してそれを削除できま す。この場合、DROP TABLE は Hive の外部テーブルのみを削除します。基盤となる DynamoDB テー ブルやそのいずれのデータも影響を受けません。 トピック • CREATE EXTERNAL TABLE の構文 (p. 527) • データ型マッピング (p. 528) CREATE EXTERNAL TABLE の構文 DynamoDB にマッピングされる外部 Hive テーブルを作成するための HiveQL の構文を以下に示しま す。 API Version 2012-08-10 527 Amazon DynamoDB 開発者ガイド Hive に外部テーブルを作成します。 CREATE EXTERNAL TABLE hive_table (hive_column1_name hive_column1_datatype, hive_column2_name hive_column2_datatype...) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES ( "dynamodb.table.name" = "dynamodb_table", "dynamodb.column.mapping" = "hive_column1_name:dynamodb_attribute1_name,hive_column2_name:dynamodb_attribute2_name..." ); 行 1 は、CREATE EXTERNAL TABLE ステートメントの開始で、作成する Hive テーブル (hive_table) の名前を指定します。 行 2 では、hive_table の列およびデータ型を指定します。DynamoDB テーブルの属性に対応する列お よびデータ型を定義する必要があります。 行 3 は STORED BY 句で、Hive と DynamoDB テーブル間のデータ管 理を処理するクラスを指定します。DynamoDB では、STORED BY は 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' のように設定する必要があ ります。 行 4 は TBLPROPERTIES 句の開始で、DynamoDBStorageHandler に次のパラメーターを定義しま す。 • dynamodb.table.name— DynamoDB テーブルの名前。 • dynamodb.column.mapping— Hive テーブルの列名と DynamoDB テーブルの対応する属性のペ ア。各ペアは hive_column_name:dynamodb_attribute_name の形式で、ペアはカンマで区切られま す。 次の点に注意してください。 • Hive テーブルの名前は、DynamoDB テーブル名と同じである必要はありません。 • Hive テーブルの列名は、DynamoDB テーブルの列名と同じである必要はありません。 • dynamodb.table.name で指定されたテーブルは DynamoDB 内にある必要があります。 • 複数 dynamodb.column.mapping: • DynamoDB テーブルのキースキーマ属性をマッピングする必要があります。これには、パーティ ションキーおよびソートキーが含まれます (存在する場合)。 • DynamoDB テーブルの非キー属性をマッピングする必要はありません。ただし、Hive テーブル のクエリを実行する場合は、これらの属性のデータは表示されません。 • Hive テーブルの列と DynamoDB 属性のデータ型は互換性があり、Hive テーブルのクエリを実行 する場合、これらの列に NULL が表示されます。 Note CREATE EXTERNAL TABLE ステートメントは TBLPROPERTIES 句で検証を実行しませ ん。dynamodb.table.name および dynamodb.column.mapping に指定した値は、テー ブルにアクセスを試みるときに DynamoDBStorageHandler クラスによってのみ評価されま す。 データ型マッピング 次の表は、DynamoDB データ型および互換性のある Hive データ型を示しています。 API Version 2012-08-10 528 Amazon DynamoDB 開発者ガイド HiveQL ステートメントの処理 DynamoDB データ型 Hive データ型 文字列 STRING 数値 BIGINT または DOUBLE バイナリ BINARY 文字列セット ARRAY<STRING> 数値セット ARRAY<BIGINT> または ARRAY<DOUBLE> バイナリセット ARRAY<BINARY> Note 以下の DynamoDB データ型は、DynamoDBStorageHandler クラスでサポートされていない ため、dynamodb.column.mapping には使用できません。 • マップ • リスト • ブール • Null 数値型の DynamoDB 属性をマッピングする場合、適切な Hive の型を選択する必要があります。 • Hive BIGINT 型は 8 バイトの符号付き整数です。これは、Java の long データ型と同じです。 • Hive DOUBLE 型は 8 ビット倍精度浮動小数点数です。これは、Java の double データ型と同じで す。 DynamoDB に格納されている数値データが選択した Hive データよりも高精度な場合、DynamoDB データにアクセスすると精度が低下する場合があります。 バイナリ型のデータを DynamoDB から (Amazon S3) または HDFS にエクスポートすると、データは Base64 エンコード文字列として格納されます。Amazon S3 または HDFS から DynamoDB バイナリ 型にデータをインポートする場合、データが Base64 エンコード文字列であることを確認する必要が あります。 HiveQL ステートメントの処理 Hive は、MapReduce ジョブを実行するバッチ志向のフレームワークで、Hadoop 上で実行するアプ リケーションです。HiveQL ステートメントを発行すると、Hive はすぐに結果を返すことができる か、MapReduce ジョブを送信する必要があるかを決定します。 たとえば、(チュートリアル: Amazon DynamoDB および Apache Hive の使用 (p. 520) からの) ddb_features テーブルについて検討します。次の Hive クエリは州の略称と各山頂の数を表示します。 SELECT state_alpha, count(*) FROM ddb_features WHERE feature_class = 'Summit' GROUP BY state_alpha; Hive はすぐに結果を返しません。代わりに、Hadoop フレームワークによって処理される MapReduce ジョブを送信します。Hive はクエリからの結果を参照する前に、ジョブが完了するまで 待機します。 API Version 2012-08-10 529 Amazon DynamoDB 開発者ガイド DynamoDB でのデータのクエリ AK 2 AL 2 AR 2 AZ 3 CA 7 CO 2 CT 2 ID 1 KS 1 ME 2 MI 1 MT 3 NC 1 NE 1 NM 1 NY 2 OR 5 PA 1 TN 1 TX 1 UT 4 VA 1 VT 2 WA 2 WY 3 Time taken: 8.753 seconds, Fetched: 25 row(s) ジョブのモニタリングとキャンセル Hive が Hadoop ジョブを起動すると、そのジョブの出力を表示します。ジョブの完了ステータスは ジョブの進行に合わせて更新されます。場合によっては、ステータスは長い間更新されない場合があ ります。(これは読み込みキャパシティーが小さく設定された大きな DynamoDB テーブルにクエリを 実行しているときに発生することがあります。) ジョブが完了する前にキャンセルすることが必要な場合は、Ctrl+C と入力することができます。 DynamoDB でのデータのクエリ 次の例は、HiveQL を使用して DynamoDB のデータにクエリを行う方法を示します。 これらの例では、チュートリアル (ステップ 5: DynamoDB にデータをコピーします。 (p. 525)) の ddb_features テーブルを参照します。 トピック • 集計関数の使用 (p. 530) • GROUP BY 句および HAVING 句の使用 (p. 531) • 2 つの DynamoDB テーブルの結合 (p. 531) • 異なるソースのテーブルの結合 (p. 532) 集計関数の使用 HiveQL は、データ値をまとめるための組み込み関数を提供します。たとえば、MAX 関数を使用して 選択した列の最大値を見つけることができます。次の例では、コロラド州の最高地物の標高を返しま す。 API Version 2012-08-10 530 Amazon DynamoDB 開発者ガイド DynamoDB でのデータのクエリ SELECT MAX(elev_in_ft) FROM ddb_features WHERE state_alpha = 'CO'; GROUP BY 句および HAVING 句の使用 GROUP BY 句を使用して、複数のレコードのデータを収集できます。多くの場合、これは SUM、COUNT、MIN、またはMAX のような集計関数とともに使用されます。HAVING 句を使用して、特 定の基準を満たさない結果を破棄することもできます。 次の例では、ddb_features テーブルに 5 つ以上の地物のある州からの最高標高のリストを返します。 SELECT state_alpha, max(elev_in_ft) FROM ddb_features GROUP BY state_alpha HAVING count(*) >= 5; 2 つの DynamoDB テーブルの結合 次の例では、別の Hive テーブル (east_coast_states) を DynamoDB. のテーブルにマッピングしま す。SELECT ステートメントは、これらの 2 つのテーブルの結合です。結合がクラスターで計算され て返されます。join は DynamoDB では発生しません。 以下のデータを含む EastCoastStates という名前の DynamoDB テーブルについて検討します。 StateName StateAbbrev Maine New Hampshire Massachusetts Rhode Island Connecticut New York New Jersey Delaware Maryland Virginia North Carolina South Carolina Georgia Florida ME NH MA RI CT NY NJ DE MD VA NC SC GA FL そのテーブルは、east_coast_states という名前の Hive 外部テーブルとして実行可能であると仮定し ます。 CREATE EXTERNAL TABLE ddb_east_coast_states (state_name STRING, state_alpha STRING) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' API Version 2012-08-10 531 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする TBLPROPERTIES ("dynamodb.table.name" = "EastCoastStates", "dynamodb.column.mapping" = "state_name:StateName,state_alpha:StateAbbrev"); 次の結合は、少なくとも 3 つの地物のある米国東海岸の州を返します。 SELECT ecs.state_name, f.feature_class, COUNT(*) FROM ddb_east_coast_states ecs JOIN ddb_features f on ecs.state_alpha = f.state_alpha GROUP BY ecs.state_name, f.feature_class HAVING COUNT(*) >= 3; 異なるソースのテーブルの結合 次の例では、s3_east_coast_states は、Amazon S3 に格納された CSV ファイルに関連付けられた Hive テーブルです。ddb_features テーブルは DynamoDB のデータと関連付けられます。次の例で は、これらの 2 つのテーブルを結合し、名前が「New」で始まる州の地理的特徴を返します。 create external table s3_east_coast_states (state_name STRING, state_alpha STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION 's3://bucketname/path/subpath/'; SELECT ecs.state_name, f.feature_name, f.feature_class FROM s3_east_coast_states ecs JOIN ddb_features f ON ecs.state_alpha = f.state_alpha WHERE ecs.state_name LIKE 'New%'; Amazon DynamoDB でデータを出し入れする チュートリアル: Amazon DynamoDB および Apache Hive の使用 (p. 520) で、データをネイティブ Hive テーブルから外部 DynamoDB テーブルにコピーして、外部 DynamoDB テーブルにクエリを実行 しました。テーブルは Hive の外に存在するため、外部にあります。それにマッピングする Hive テー ブルを削除しても、DynamoDB のテーブルは影響を受けません。 Hive は DynamoDB テーブル、Amazon S3 バケット、ネイティブ Hive テーブル、および Hadoop Distributed File System (HDFS) 間でデータをコピーするのに優れたソリューションです。このセク ションでは、これらの操作の例を示します。 トピック • DynamoDB とネイティブ Hive テーブルの間でデータをコピーする (p. 533) • DynamoDB と Amazon S3 間のデータのコピー (p. 534) • DynamoDB と HDFS 間のデータのコピー (p. 538) • データ圧縮の使用 (p. 543) • 印刷不可の UTF-8 文字データを読み取る (p. 544) API Version 2012-08-10 532 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする DynamoDB とネイティブ Hive テーブルの間でデータをコピー する DynamoDB テーブルにデータが存在する場合は、ネイティブ Hive テーブルにデータをコピーできま す。それをコピーした時点でデータのスナップショットを得られます。 多くの HiveQL クエリを実行する必要があり、DynamoDB からプロビジョニングされたスループッ ト容量を消費したくない場合、これを行うことがあります。ネイティブ Hive テーブルのデータ は、DynamoDB からのデータのコピーであり、ライブデータではないため、クエリはデータが最新の 状態であると期待できません。 このセクションの例は、チュートリアル: Amazon DynamoDB および Apache Hive の使用 (p. 520) の手順に従ったこと、また DynamoDB (ddb_features) でマスターされている外部テーブルがあること を前提にしています。 ネイティブ Hive テーブルから DynamoDB へ ネイティブ Hive テーブルを作成し、このような、ddb_features からのデータを入力することができま す。 CREATE TABLE features_snapshot AS SELECT * FROM ddb_features; データはいつでも更新できます。 INSERT OVERWRITE TABLE features_snapshot SELECT * FROM ddb_features; Note これらの例では、サブクエリ SELECT * FROM ddb_features は、ddb_features からのす べてのデータを取得します。データのサブセットのみをコピーする場合は、サブクエリ内の WHERE 句を使用できます。 次の例は湖および山頂の属性の一部のみを含むネイティブ Hive テーブルを作成します。 CREATE TABLE lakes_and_summits AS SELECT feature_name, feature_class, state_alpha FROM ddb_features WHERE feature_class IN ('Lake','Summit'); DynamoDB からネイティブ Hive テーブルへ 次の HiveQL ステートメントを使用して、ネイティブ Hive テーブルから ddb_features にデータをコ ピーします。 API Version 2012-08-10 533 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする INSERT OVERWRITE TABLE ddb_features SELECT * FROM features_snapshot; DynamoDB と Amazon S3 間のデータのコピー DynamoDB テーブルにデータが存在する場合は、Hive を使用して Amazon S3 バケットにデータをコ ピーできます。 DynamoDB テーブルのデータのアーカイブを作成する場合、これを行う場合があります。たとえ ば、DynamoDB の一連のベースラインテストデータを使用する必要のあるテスト環境があるとしま す。ベースラインデータを Amazon S3 バケットにコピーでき、それからテストを実行します。その 後、ベースラインデータを Amazon S3 バケットから DynamoDB に復元して、テスト環境をリセット できます。 チュートリアル: Amazon DynamoDB および Apache Hive の使用 (p. 520) を完了している場合、既 に Amazon EMR ログを含む Amazon S3 バケットがあります。バケットのルートパスが分かっている 場合は、このセクションの例では、このバケットを使用します。 1. Amazon EMR コンソール(https://console.aws.amazon.com/elasticmapreduce/)を開きます。 2. [Name] には、クラスターを選択します。 3. URI は、[設定の詳細] の [Log URI] に一覧表示されます。 4. バケットのルートパスを書きとめておきます。命名規則は次のとおりです。 s3://aws-logs-accountID-region accountID が、AWS アカウント ID であり、リージョンがバケットの AWS リージョンである場 合です。 Note これらの例では、この例のように、バケット内のサブパスを使用します。 s3://aws-logs-123456789012-us-west-2/hive-test 次の手順は、チュートリアルのステップに従ったこと、DynamoDB (ddb_features) でマスターされて いる外部テーブルがあることを前提にしています。 トピック • Hive のデフォルト形式を使用してデータをコピーする (p. 534) • ユーザー指定の形式でのデータのコピー (p. 535) • 列のマッピングなしでのデータのコピー (p. 536) • Amazon S3 のデータを表示する (p. 538) Hive のデフォルト形式を使用してデータをコピーする DynamoDB から Amazon S3 へ INSERT OVERWRITE ステートメントを使用して Amazon S3 に直接書き込みます。 INSERT OVERWRITE DIRECTORY 's3://aws-logs-123456789012-us-west-2/hive-test' API Version 2012-08-10 534 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする SELECT * FROM ddb_features; Amazon S3 のデータファイルは次のようになります。 920709^ASoldiers Farewell Hill^ASummit^ANM^A32.3564729^A-108.33004616135 1178153^AJones Run^AStream^APA^A41.2120086^A-79.25920781260 253838^ASentinel Dome^ASummit^ACA^A37.7229821^A-119.584338133 264054^ANeversweet Gulch^AValley^ACA^A41.6565269^A-122.83614322900 115905^AChacaloochee Bay^ABay^AAL^A30.6979676^A-87.97388530 各フィールドは SOH 文字 (ヘッダーの開始、0x01) で区切ります。ファイルで、SOH は ^A と表示さ れます。 Amazon S3 から DynamoDB へ 1. Amazon S3 の未フォーマットデータをポイントする外部テーブルを作成します。 CREATE EXTERNAL TABLE s3_features_unformatted (feature_id BIGINT, feature_name STRING , feature_class STRING , state_alpha STRING, prim_lat_dec DOUBLE , prim_long_dec DOUBLE , elev_in_ft BIGINT) LOCATION 's3://aws-logs-123456789012-us-west-2/hive-test'; 2. データを DynamoDB にコピーします。 INSERT OVERWRITE TABLE ddb_features SELECT * FROM s3_features_unformatted; ユーザー指定の形式でのデータのコピー 独自のフィールド区切り文字を指定する場合は、Amazon S3 バケットにマッピングされる外部テーブ ルを作成できます。カンマ区切り値 (CSV) を使用したデータファイルを作成するためにこの手法を使 用する場合があります。 DynamoDB から Amazon S3 へ 1. Amazon S3. にマッピングする Hive 外部テーブルを作成します。これを行うとき、データ型 が、DynamoDB 外部テーブルのデータ型に準拠していることを確認します。 CREATE EXTERNAL TABLE s3_features_csv (feature_id BIGINT, feature_name STRING, API Version 2012-08-10 535 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする feature_class STRING, state_alpha STRING, prim_lat_dec DOUBLE, prim_long_dec DOUBLE, elev_in_ft BIGINT) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION 's3://aws-logs-123456789012-us-west-2/hive-test'; 2. DynamoDB からデータをコピーします。 INSERT OVERWRITE TABLE s3_features_csv SELECT * FROM ddb_features; Amazon S3 のデータファイルは次のようになります。 920709,Soldiers Farewell Hill,Summit,NM,32.3564729,-108.3300461,6135 1178153,Jones Run,Stream,PA,41.2120086,-79.2592078,1260 253838,Sentinel Dome,Summit,CA,37.7229821,-119.58433,8133 264054,Neversweet Gulch,Valley,CA,41.6565269,-122.8361432,2900 115905,Chacaloochee Bay,Bay,AL,30.6979676,-87.9738853,0 Amazon S3 から DynamoDB へ 単一の HiveQL ステートメントを使用すると、Amazon S3 からのデータを使用して DynamoDB テー ブルに入力できます。 INSERT OVERWRITE TABLE ddb_features SELECT * FROM s3_features_csv; 列のマッピングなしでのデータのコピー RAW 形式で DynamoDB からデータをコピーし、データ型または列マッピングを指定しないで Amazon S3 に書き込めます。この方法を使用すると、DynamoDB データのアーカイブを作成し て、Amazon S3 に保存できます。 Note DynamoDB テーブルに Map 型、List、Boolean、または Null の属性が含まれる場合、この方 法でのみ Hive を使用してデータを DynamoDB から Amazon S3 へコピーできます。 DynamoDB から Amazon S3 へ 1. DynamoDB テーブルに関連付けられる外部テーブルを作成します。(この HiveQL ステートメント には dynamodb.column.mapping はありません。) API Version 2012-08-10 536 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする CREATE EXTERNAL TABLE ddb_features_no_mapping (item MAP<STRING, STRING>) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES ("dynamodb.table.name" = "Features"); 2. Amazon S3 バケットに関連付けられた別の外部テーブルを作成します。 CREATE EXTERNAL TABLE s3_features_no_mapping (item MAP<STRING, STRING>) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' LOCATION 's3://aws-logs-123456789012-us-west-2/hive-test'; 3. DynamoDB から Amazon S3 へデータをコピーします。 INSERT OVERWRITE TABLE s3_features_no_mapping SELECT * FROM ddb_features_no_mapping; Amazon S3 のデータファイルは次のようになります。 Name^C{"s":"Soldiers Farewell Hill"}^BState^C{"s":"NM"}^BClass^C{"s":"Summit"}^BElevation^C{"n":"6135"}^BLatitude^C{"n":" Name^C{"s":"Jones Run"}^BState^C{"s":"PA"}^BClass^C{"s":"Stream"}^BElevation^C{"n":"1260"}^BLatitude^C{"n":"4 Name^C{"s":"Sentinel Dome"}^BState^C{"s":"CA"}^BClass^C{"s":"Summit"}^BElevation^C{"n":"8133"}^BLatitude^C{"n":" Name^C{"s":"Neversweet Gulch"}^BState^C{"s":"CA"}^BClass^C{"s":"Valley"}^BElevation^C{"n":"2900"}^BLatitude^C{"n": Name^C{"s":"Chacaloochee Bay"}^BState^C{"s":"AL"}^BClass^C{"s":"Bay"}^BElevation^C{"n":"0"}^BLatitude^C{"n":"30.6979 各フィールドは STX 文字 (テキスト開始 0x02) で始まり ETX 文字 (テキスト終了 0x03) で終わりま す。ファイルで、STX は ^B、ETX は ^C と表示されます。 Amazon S3 から DynamoDB へ 単一の HiveQL ステートメントを使用すると、Amazon S3 からのデータを使用して DynamoDB テー ブルに入力できます。 INSERT OVERWRITE TABLE ddb_features_no_mapping SELECT * FROM s3_features_no_mapping; API Version 2012-08-10 537 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする Amazon S3 のデータを表示する SSH を使用してマスターノードに接続する場合、AWS Command Line Interface (AWS CLI) を使用し て、Hive が Amazon S3 に 書き込んだデータにアクセスできます。 次のステップは、このセクションの手順の 1 つを使用して DynamoDB から Amazon S3 にデータをコ ピーしたことを前提にしています。 1. 現在 Hive コマンドプロンプトである場合は、Linux コマンドプロンプトに戻ります。 hive> exit; 2. Amazon S3 バケットで Hive テストディレクトリのコンテンツを一覧表示します。(これは、Hive が DynamoDB からデータをコピーした場所です。) aws s3 ls s3://aws-logs-123456789012-us-west-2/hive-test/ レスポンスは以下のようになります。 2016-11-01 23:19:54 81983 000000_0 ファイル名 (000000_0) は、システムで生成されます。 3. (オプション) Amazon S3 から マスターノードのローカルファイルシステムにデータファイルを コピーできます。その後、ファイルのデータを運用するために Linux 標準コマンドラインユー ティリティを使用できます。 aws s3 cp s3://aws-logs-123456789012-us-west-2/hive-test/000000_0 . レスポンスは以下のようになります。 download: s3://aws-logs-123456789012-us-west-2/hive-test/000000_0 to ./000000_0 Note マスターノードのローカルファイルシステムは容量が限定されています。ローカルファ イルシステムで利用可能なスペースより大きなファイルでこのコマンドを使用しないで ください。 DynamoDB と HDFS 間のデータのコピー DynamoDB テーブルにデータが存在する場合は、Hive を使用して、Hadoop Distributed File System (HDFS) にデータをコピーできます。 DynamoDB からのデータを必要とする MapReduce ジョブを実行しているなら、これを行う場合があ ります。HDFS からのデータを DynamoDB コピーする場合、Hadoop はクラスターで利用可能なすべ てのノードを使用して、並列 Amazon EMR 処理できます。MapReduce ジョブが完了すると、HDFS から DDB に結果を記述できます。 次の例では、Hive は次の HDFS ディレクトリで読み取りと書き込みを行います。/user/hadoop/ hive-test API Version 2012-08-10 538 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする このセクションの例は、チュートリアル: Amazon DynamoDB および Apache Hive の使用 (p. 520) の手順に従ったこと、また DynamoDB (ddb_features) でマスターされている外部テーブルがあること を前提にしています。 トピック • Hive のデフォルト形式を使用してデータをコピーする (p. 539) • ユーザー指定の形式でのデータのコピー (p. 540) • 列のマッピングなしでのデータのコピー (p. 541) • HDFS でデータにアクセスする (p. 542) Hive のデフォルト形式を使用してデータをコピーする DynamoDB から HDFS へ INSERT OVERWRITE ステートメントを使用して HDFS に直接書き込みます。 INSERT OVERWRITE DIRECTORY 'hdfs:///user/hadoop/hive-test' SELECT * FROM ddb_features; HDFS のデータファイルは次のようになります。 920709^ASoldiers Farewell Hill^ASummit^ANM^A32.3564729^A-108.33004616135 1178153^AJones Run^AStream^APA^A41.2120086^A-79.25920781260 253838^ASentinel Dome^ASummit^ACA^A37.7229821^A-119.584338133 264054^ANeversweet Gulch^AValley^ACA^A41.6565269^A-122.83614322900 115905^AChacaloochee Bay^ABay^AAL^A30.6979676^A-87.97388530 各フィールドは SOH 文字 (ヘッダーの開始、0x01) で区切ります。ファイルで、SOH は ^A と表示さ れます。 HDFS から DynamoDB へ 1. HDFS で未フォーマットデータにマッピングされる外部テーブルを作成します。 CREATE EXTERNAL TABLE hdfs_features_unformatted (feature_id BIGINT, feature_name STRING , feature_class STRING , state_alpha STRING, prim_lat_dec DOUBLE , prim_long_dec DOUBLE , elev_in_ft BIGINT) LOCATION 'hdfs:///user/hadoop/hive-test'; 2. データを DynamoDB にコピーします。 API Version 2012-08-10 539 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする INSERT OVERWRITE TABLE ddb_features SELECT * FROM hdfs_features_unformatted; ユーザー指定の形式でのデータのコピー 別のフィールド区切り文字を使用する場合は、HDFS ディレクトリにマッピングされる外部テーブル を作成します。カンマ区切り値 (CSV) を使用したデータファイルを作成するためにこの手法を使用す る場合があります。 DynamoDB から HDFS へ 1. HDFS にマッピングする Hive 外部テーブルを作成します。これを行うとき、データ型 が、DynamoDB 外部テーブルのデータ型に準拠していることを確認します。 CREATE EXTERNAL TABLE hdfs_features_csv (feature_id BIGINT, feature_name STRING , feature_class STRING , state_alpha STRING, prim_lat_dec DOUBLE , prim_long_dec DOUBLE , elev_in_ft BIGINT) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION 'hdfs:///user/hadoop/hive-test'; 2. DynamoDB からデータをコピーします。 INSERT OVERWRITE TABLE hdfs_features_csv SELECT * FROM ddb_features; HDFS のデータファイルは次のようになります。 920709,Soldiers Farewell Hill,Summit,NM,32.3564729,-108.3300461,6135 1178153,Jones Run,Stream,PA,41.2120086,-79.2592078,1260 253838,Sentinel Dome,Summit,CA,37.7229821,-119.58433,8133 264054,Neversweet Gulch,Valley,CA,41.6565269,-122.8361432,2900 115905,Chacaloochee Bay,Bay,AL,30.6979676,-87.9738853,0 HDFS から DynamoDB へ 単一の HiveQL ステートメントを使用すると、HDFS からのデータを DynamoDB テーブルに表示する ことができます。 INSERT OVERWRITE TABLE ddb_features API Version 2012-08-10 540 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする SELECT * FROM hdfs_features_csv; 列のマッピングなしでのデータのコピー RAW 形式で DynamoDB からデータをコピーし、データ型または列マッピングを指定しないで HDFS に書き込めます。この方法を使用すると、DynamoDB データのアーカイブを作成して、HDFS に保存 できます。 Note DynamoDB テーブルにタイプ Map、List、Boolean、または Null の属性が含まれる場合、こ の方法でのみ Hive を使用してデータを DynamoDB から HDFS へコピーできます。 DynamoDB から HDFS へ 1. DynamoDB テーブルに関連付けられる外部テーブルを作成します。(この HiveQL ステートメント には dynamodb.column.mapping はありません。) CREATE EXTERNAL TABLE ddb_features_no_mapping (item MAP<STRING, STRING>) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES ("dynamodb.table.name" = "Features"); 2. HDFS ディレクトリに関連付けられた別の外部テーブルを作成します。 CREATE EXTERNAL TABLE hdfs_features_no_mapping (item MAP<STRING, STRING>) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' LOCATION 'hdfs:///user/hadoop/hive-test'; 3. DynamoDB から HDFS へデータをコピーします。 INSERT OVERWRITE TABLE hdfs_features_no_mapping SELECT * FROM ddb_features_no_mapping; HDFS のデータファイルは次のようになります。 Name^C{"s":"Soldiers Farewell Hill"}^BState^C{"s":"NM"}^BClass^C{"s":"Summit"}^BElevation^C{"n":"6135"}^BLatitude^C{"n":" Name^C{"s":"Jones Run"}^BState^C{"s":"PA"}^BClass^C{"s":"Stream"}^BElevation^C{"n":"1260"}^BLatitude^C{"n":"4 Name^C{"s":"Sentinel Dome"}^BState^C{"s":"CA"}^BClass^C{"s":"Summit"}^BElevation^C{"n":"8133"}^BLatitude^C{"n":" API Version 2012-08-10 541 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする Name^C{"s":"Neversweet Gulch"}^BState^C{"s":"CA"}^BClass^C{"s":"Valley"}^BElevation^C{"n":"2900"}^BLatitude^C{"n": Name^C{"s":"Chacaloochee Bay"}^BState^C{"s":"AL"}^BClass^C{"s":"Bay"}^BElevation^C{"n":"0"}^BLatitude^C{"n":"30.6979 各フィールドは STX 文字 (テキスト開始 0x02) で始まり ETX 文字 (テキスト終了 0x03) で終わりま す。ファイルで、STX は ^B、ETX は ^C と表示されます。 HDFS から DynamoDB へ 単一の HiveQL ステートメントを使用すると、HDFS からのデータを DynamoDB テーブルに表示する ことができます。 INSERT OVERWRITE TABLE ddb_features_no_mapping SELECT * FROM hdfs_features_no_mapping; HDFS でデータにアクセスする HDFS は、Amazon EMR クラスターのすべてのノードにアクセス可能な分散ファイルシステムで す。SSHを使用してマスターノードに接続する場合、コマンドラインツールを使用して、Hive が HDFS に書き込んだデータにアクセスできます。 HDFS は、マスターノードのローカルファイルシステムと同じものではありません。標準 Linux コマ ンド (cat、cp、mv、rm など) を使用して HDFS のファイルとディレクトリで作業することはできま せん。代わりに、hadoop fs コマンドを使用してこれらのタスクを実行します。 次のステップは、このセクションの手順の 1 つを使用して DynamoDB から HDFS にデータをコピー したと想定しています。 1. 現在 Hive コマンドプロンプトである場合は、Linux コマンドプロンプトに戻ります。 hive> exit; 2. /user/hadoop/hive-testディレクトリの内容を HDFS に表示します。(これは、Hive が DynamoDB からデータをコピーした場所です。) hadoop fs -ls /user/hadoop/hive-test レスポンスは以下のようになります。 Found 1 items -rw-r--r-- 1 hadoop hadoop 29504 2016-06-08 23:40 /user/hadoop/hivetest/000000_0 ファイル名 (000000_0) は、システムで生成されます。 3. ファイルのコンテンツを表示します。 hadoop fs -cat /user/hadoop/hive-test/000000_0 API Version 2012-08-10 542 Amazon DynamoDB 開発者ガイド Amazon DynamoDB でデータを出し入れする Note この例では、ファイルは比較的小さくなっています (約29 KB)。大きなファイルまたは 印刷不可の文字を含むファイルでこのコマンドを使用する場合は注意する必要がありま す。 4. (オプション) HDFS から マスターノードのローカルファイルシステムにデータファイルをコピー できます。その後、ファイルのデータを運用するために Linux 標準コマンドラインユーティリ ティを使用できます。 hadoop fs -get /user/hadoop/hive-test/000000_0 このコマンドはファイルを上書きしません。 Note マスターノードのローカルファイルシステムは容量が限定されています。ローカルファ イルシステムで利用可能なスペースより大きなファイルでこのコマンドを使用しないで ください。 データ圧縮の使用 さまざまなデータソース間で Hive を使用してデータをコピーする場合、オンザフライのデータ圧縮を リクエストできます。Hive は複数の圧縮コーデックを提供します。Hive セッション中に 1 つを選択 できます。選択すると、データは指定した形式で圧縮されます。 次の例では、LZO (Lempel-Ziv-Oberhumer) アルゴリズムを使用して、データを圧縮します。 SET hive.exec.compress.output=true; SET io.seqfile.compression.type=BLOCK; SET mapred.output.compression.codec = com.hadoop.compression.lzo.LzopCodec; CREATE EXTERNAL TABLE lzo_compression_table (line STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' LOCATION 's3://bucketname/path/subpath/'; INSERT OVERWRITE TABLE lzo_compression_table SELECT * FROM hiveTableName; Amazon S3 内のファイルにはシステム生成された名前が付けられ、最後に .lzo が付けられます (例: 8d436957-57ba-4af7-840c-96c2fc7bb6f5-000000.lzo)。 以下の圧縮コーデックを利用できます。 • org.apache.hadoop.io.compress.GzipCodec • org.apache.hadoop.io.compress.DefaultCodec • com.hadoop.compression.lzo.LzoCodec • com.hadoop.compression.lzo.LzopCodec • org.apache.hadoop.io.compress.BZip2Codec API Version 2012-08-10 543 Amazon DynamoDB 開発者ガイド パフォーマンスの調節 • org.apache.hadoop.io.compress.SnappyCodec 印刷不可の UTF-8 文字データを読み取る Hive テーブル作成時に STORED AS SEQUENCEFILE 句を使用すると、印刷不可の UTF-8 文字デー タを読み取り、書き込むことができます。SequenceFile は Hadoop バイナリファイル形式です。こ のファイルを読み取るには Hadoop を使用する必要があります。次の例は、DynamoDB のデータを Amazon S3 にエクスポートする方法を示しています。この機能を使用して印刷不可の UTF-8 でエン コードされた文字を処理できます。 CREATE EXTERNAL TABLE s3_export(a_col string, b_col bigint, c_col array<string>) STORED AS SEQUENCEFILE LOCATION 's3://bucketname/path/subpath/'; INSERT OVERWRITE TABLE s3_export SELECT * FROM hiveTableName; パフォーマンスの調節 DynamoDB にマップする Hive の外部テーブルを作成する場合、DynamoDB で読み取り容量または 書き込み容量を消費しません。ただし、Hive テーブルでの読み取りおよび書き込み作業 (INSERT や SELECT など) は、基盤となる DynamoDB テーブルでの読み取りおよび書き込みオペレーションに直 接変換されます。 Amazon EMR の Apache Hive は DynamoDB テーブルの I/O 負荷のバランスを取るために独自のロ ジックを導入し、テーブルのプロビジョンドスループットを超過する可能性を最小限に抑えるよう に努めます。それぞれの Hive クエリの最後に、Amazon EMR はプロビジョンドスループットを超 過した回数など、ランタイムメトリックスを返します。この情報に加えて、DynamoDB テーブルの CloudWatch メトリックスを使用して、続くリクエストのパフォーマンスを向上させることができま す。 Amazon EMR コンソールでは、クラスターの基本モニタリングツールが用意されています。詳細につ いては、Amazon EMR 管理ガイドのクラスターを表示し、モニタリングするを参照してください。 クラスターや Hadoop ジョブは、Hue、Ganglia、Hadoop ウェブインターフェイスなどのウェブベー スのツールでモニタリングできます。詳細については、Amazon EMR 管理ガイドのAmazon EMR ク ラスターでホストされているウェブインターフェイスの表示を参照してください。 このセクションでは、外部 DynamoDB テーブルで Hive オペレーションのパフォーマンス調整を行う ための手順について説明します。 トピック • DynamoDB プロビジョンドスループット (p. 544) • マッパーの調整 (p. 546) • その他のトピック (p. 547) DynamoDB プロビジョンドスループット 外部 DynamoDB テーブルに対して HiveQL ステートメントを発行する と、DynamoDBStorageHandler クラスは適切な低レベル DynamoDB API リクエストを行い、プロ API Version 2012-08-10 544 Amazon DynamoDB 開発者ガイド パフォーマンスの調節 ビジョンドスループットを消費します。DynamoDB テーブルに十分な読み取りまたは書き込み容量が ない場合、リクエストは調整され、HiveQL のパフォーマンスが遅くなります。そのため、テーブルに 十分な容量があることを確認する必要があります。 例えば、DynamoDB テーブルに対して 100 ユニットの読み取りキャパシティーをプロビジョニングし ているとします。この場合、1 秒間に 409,600 バイトの読み取り (100 × 4 KB 読み取り容量ユニット サイズ) を実行できます。ここで、テーブルに 20 GB のデータ (21,474,836,480 バイト) が含まれてお り、HiveQL を使っているすべてのデータを SELECT ステートメントで選択するとします。クエリの 実行時間を次のように推定できます。 21,474,836,480 / 409,600 = 52,429 秒 = 14.56 時間 このシナリオでは、DynamoDB テーブルがボトルネックとなります。Amazon EMR ノードを追 加しても解決にはなりません。Hive スループットは毎秒 409,600バイトに制限されているからで す。SELECT ステートメントに必要な時間を短縮する唯一の方法は、DynamoDB テーブルにプロビ ジョニングされた読み取り容量を増やすことです。 また同様の計算を実行して、DynamoDB テーブルにマップされた Hive 外部テーブルにデータを一括 読み込みするのに必要な時間を推定することもできます。読み込むデータの合計バイト数を特定し て、1 つの DynamoDB 書き込み容量ユニットのサイズ (1 KB) で割ります。これでテーブルを読み込 む秒数が得られます。 テーブルの CloudWatch メトリックスを定期的にモニタリングする必要があります。DynamoDB コン ソールの概要については、テーブルを選択し、[Metrics] タブを選択します。その後、消費された読み 取りおよび書き込み容量ユニット、および調整された読み取りおよび書き込みリクエストを確認でき ます。 読み込みキャパシティー Amazon EMR はテーブルのプロビジョニング済みスループットに基づいて、DynamoDB テーブルに対するリクエスト負荷を管理します。ただし、ジョブ出力に大量の ProvisionedThroughputExceeded メッセージがあることに気付いた場合、デフォルトの読み取り レートを調整することができます。これを行うには、dynamodb.throughput.read.percent 設定 変数を変更します。SET コマンドを使って Hive コマンドプロンプトでこの変数を設定できます: SET dynamodb.throughput.read.percent=1.0; この変数は、現在の Hive セッションでのみ維持されます。Hive を終了して、あとで戻った場 合、dynamodb.throughput.read.percent はデフォルト値に戻ります。 dynamodb.throughput.read.percent の値は 0.1 以上 1.5 以下にできます。0.5 はデフォルト の読み取りレートを示します。つまり、Hive はテーブルの読み取り容量の半分を消費しようと試みま す。値が 0.5 を上回ると、Hive はリクエストレートを増やします。値が 0.5 を下回ると、読み取り リクエストレートを減らします。(実際の読み取りレートは、DynamoDB テーブルに統一キーディス トリビューションがあるかどうかなどの要因によって変わります。) Hive が頻繁にテーブルにプロビジョニングされた読み取り容量を使い切ってい ることに気付いた場合、または読み取りリクエストが過度に調整されている場合 は、dynamodb.throughput.read.percent を 0.5 未満にしてみます。テーブルで十分な読み取り 容量があり、HiveQL オペレーションの応答性を高める場合、0.5 を超える値に設定できます。 書き込みキャパシティー Amazon EMR はテーブルのプロビジョニング済みスループットに基づいて、DynamoDB テーブルに対するリクエスト負荷を管理します。ただし、ジョブ出力に大量の ProvisionedThroughputExceeded メッセージがあることに気付いた場合、デフォルトの書き込み API Version 2012-08-10 545 Amazon DynamoDB 開発者ガイド パフォーマンスの調節 レートを調整することができます。これを行うには、dynamodb.throughput.write.percent 設定 変数を変更します。SET コマンドを使って Hive コマンドプロンプトでこの変数を設定できます: SET dynamodb.throughput.write.percent=1.0; この変数は、現在の Hive セッションでのみ維持されます。Hive を終了して、あとで戻った場 合、dynamodb.throughput.write.percent はデフォルト値に戻ります。 dynamodb.throughput.write.percent の値は 0.1 以上 1.5 以下にできます。0.5 はデフォルト の読み取りレートを示します。つまり、Hive はテーブルの読み取り容量の半分を消費しようと試みま す。値が 0.5 を上回ると、Hive はリクエストレートを増やします。値が 0.5 を下回ると、読み取り リクエストレートを減らします。(実際の読み取りレートは、DynamoDB テーブルに統一キーディス トリビューションがあるかどうかなどの要因によって変わります。) Hive が頻繁にテーブルにプロビジョニングされた書き込み容量を使い切ってい ることに気付いた場合、または書き込みリクエストが過度に調整されている場合 は、dynamodb.throughput.write.percent を 0.5 未満にしてみます。テーブルで十分な書き込 み容量があり、HiveQL オペレーションの応答性を高める場合、0.5 を超える値に設定できます。 Hive を使用してデータを DynamoDB に書き込む場合は、書き込みキャパシティーユニットの数をク ラスター内のマッパーの数より大きくする必要があります。たとえば、10 の m1.xlarge ノードで構成 される Amazon EMR クラスターについて考えます。m1.xlarge ノードタイプは 8 つのマッパータスク が可能なので、クラスターには合計 80 のマッパー (10 × 8) があります。DynamoDB テーブルの書き 込み容量ユニットが 80 未満の場合、Hive 書き込みオペレーションは、テーブルのすべての書き込み スループットを消費する可能性があります。 Amazon EMR ノードタイプのマッパーの数を決定するには、Amazon EMR 開発者ガイドのタスクの 設定を参照してください。 マッパーの詳細については、マッパーの調整 (p. 546)を参照してください。 マッパーの調整 Hive が Hadoop ジョブが起動すると、ジョブは 1 つ以上のマッパータスクによって処理されま す。DynamoDB テーブルに十分なスループット容量があると仮定して、クラスター内のマッパーの数 を調整すると、パフォーマンスが向上する可能性があります。 Note Hadoop ジョブで使用されるマッパーの数は、Hadoop がデータを論理ブロックに分割する入 ロ分割によって左右されます。Hadoop が十分な入力分割を実行しないと、書き込みオペレー ションは DynamoDB テーブルで利用可能なすべての書き込みスループットを処理できない可 能性があります。 マッパーの数を増やす Amazon EMR の各マッパーの最大読み取りレートは毎秒 1 MiB です。クラスターにあるマッパーの数 は、クラスターのノードのサイズによって決まります。(ノードサイズとノードあたりのマッパーの数 については、Amazon EMR 開発者ガイドにあるタスクの設定を参照してください。) DynamoDB テーブルに十分な読み取りスループット容量がある場合、次のいずれかの方法でマッパー の数を増やしてみることができます。 • クラスターのノードのサイズを拡張する。たとえば、クラスターで m1.large ノード (ノードあたり 3 つのマッパー) を使用している場合、m1.xlarge ノード (ノードあたり 8 つのマッパー) にアップグ レードすることを検討できます。 API Version 2012-08-10 546 Amazon DynamoDB 開発者ガイド パフォーマンスの調節 • クラスターのノード数を増やす。たとえば、m1.xlarge ノードの 3 ノードクラスターを使用してい る場合、合計 24 のマッパーがあります。同じタイプのノードでクラスターのサイズを 2 倍にする と、マッパーは 48 になります。 AWS マネジメントコンソール を使用して、lクラスター内のノードの数またはサイズを管理できま す。(変更を有効にするには、場合によってはクラスターを再起動する必要があります。) マッパーの数を増やすもう 1 つの方法は、mapred.tasktracker.map.tasks.maximum Hadoop 設定パラメーターを変更することです。(これは Hadoop パラメーターで、Hive パラ メーターではありません。コマンドプロンプトからインタラクティブに変更することはできませ ん。)mapred.tasktracker.map.tasks.maximum の値を増やすと、ノードのサイズや数を増やさ ずに、マッパーの数を増やすことができます。ただし、値が大きすぎると、クラスターノードのメモ リが不足する可能性があります。 Amazon EMR クラスターを最初に起動するときに mapred.tasktracker.map.tasks.maximum の値をブートストラップアクションとして設定します。詳細については、Amazon EMR 管理ガイ ドの(オプション) 追加のソフトウェアをインストールするためのブートストラップアクションの作 成を参照してください。 マッパーの数を減らす SELECT ステートメントを使用して DynamoDB にマッピングする外部 Hive テーブルからデータを選 択する場合、Hadoop のジョブは、クラスター内のマッパー数の上限まで、必要な数のタスクを使用 できます。このシナリオでは、長時間の Hive クエリが、DynamoDB テーブルにプロビジョニングさ れたすべての読み取り容量を使い切り、他のユーザーにマイナスの影響を与える可能性があります。 dynamodb.max.map.tasks パラメーターを使用して、マップタスクの上限を設定できます。 SET dynamodb.max.map.tasks=1 この値は、1 以上にする必要があります。Hive がクエリを処理すると、Hadoop のジョブで は、DynamoDB テーブルからの読み取りで dynamodb.max.map.tasks より多くは使用しません。 その他のトピック Hive を使って DynamoDB にアクセスするアプリケーションの他の調整方法について取り上げます。 再試行の期間 デフォルトで、Hadoop ジョブが 2 分以内に DynamoDB から結果を返さない場合、Hive はそのジョ ブを再実行します。この間隔は、dynamodb.retry.duration パラメーターを変更して調整できま す。 SET dynamodb.retry.duration=2; 値はゼロ以外の整数にする必要があり、これは再試行間隔の分数を表しま す。dynamodb.retry.duration のデフォルト値は 2 (分) です。 並列データリクエスト 複数のユーザーまたは複数のアプリケーションから単一のテーブルに複数のデータリクエストが行わ れると、プロビジョニング済み読み込みスループットが減少し、パフォーマンス速度が低下します。 API Version 2012-08-10 547 Amazon DynamoDB 開発者ガイド Amazon Data Pipeline との統合 処理間隔 DynamoDB のデータ整合性は、各ノードでの読み書きオペレーションの順序に依存します。Hive ク エリの進行中に、別のアプリケーションが DynamoDB テーブルに新しいデータをロードしたり、既 存のデータの変更や削除を行ったりする場合があります。この場合、クエリの実行中にデータに対し て行われた変更は Hive クエリの結果に反映されないことがあります。 リクエスト時間 DynamoDB テーブルの需要が低いときに DynamoDB テーブルにアクセスする Hive クエリをスケ ジュールすると、パフォーマンスが向上します。例えば、アプリケーションのほとんどのユーザーが サンフランシスコに住んでいる場合、大部分のユーザーが睡眠中で DynamoDB データベースを更新 していない毎朝 4 時 (PST) にデータをエクスポートするように選択することができます。 AWS Data Pipeline を使用して DynamoDB デー タをエクスポートおよびインポートする AWS Data Pipeline を使用して、DynamoDB テーブルから Amazon S3 バケット内のファイルにデー タをエクスポートできます。コンソールを使用して、Amazon S3 から同じまたは異なる AWS リー ジョンにある DynamoDB テーブルにデータをインポートできます。 データのエクスポートおよびインポート機能は多くシナリオで役立ちます。たとえば、テスト目的で 一連のベースラインデータを保守するとします。ベースラインデータを DynamoDB テーブルに入力 し、Amazon S3 にエクスポートできます。続いて、テストデータを変更するアプリケーションを実行 した後、Amazon S3 から DynamoDB テーブルにインポートして戻すことで、ベースラインデータを 「リセット」できます。別の例としては、データの誤った削除や誤った DeleteTable オペレーショ ンもあります。このような場合は、Amazon S3 にある前回のエクスポートファイルからデータを復 元できます。ある AWS リージョン内の DynamoDB テーブルからデータをコピーし、Amazon S3 に 保存し、続いて Amazon S3 から別のリージョン内の同じ DynamoDB テーブルにインポートすること もできます。別のリージョン内のアプリケーションは、最も近い DynamoDB エンドポイントにアク セスし、データの独自のコピーを操作できるため、同時に、ネットワークレイテンシーが短くなりま す。 次の図に、AWS Data Pipeline を使用した DynamoDB データのエクスポートおよびインポートの概要 を示します。 API Version 2012-08-10 548 Amazon DynamoDB 開発者ガイド Amazon Data Pipeline との統合 DynamoDB テーブルをエクスポートするには、AWS Data Pipeline コンソールを使用して新しいパイ プラインを作成します。パイプラインによって、実際のエクスポートを実行する Amazon EMR クラ スターが起動されます。Amazon EMR は、DynamoDB からデータを読み込み、Amazon S3 バケット 内のエクスポートファイルにデータを書き込みます。 このプロセスは、データが Amazon S3 バケットから読み込まれて DynamoDB テーブルに書き込まれ ること以外、インポートでも同様です。 Important DynamoDB データのエクスポートまたはインポート時、基礎となる次の AWS サービスの使 用に対して追加コストが発生します。 • AWS Data Pipeline - インポート/エクスポートのワークフローを管理します。 • Amazon S3 - DynamoDB に対してエクスポートまたはインポートするデータを格納しま す。 API Version 2012-08-10 549 Amazon DynamoDB 開発者ガイド データをエクスポートおよびイン ポートデータするための前提条件 • Amazon EMR - マネージド型 Hadoop クラスターを実行して、Amazon S3 と DynamoDB の間で読み込みと書き込みを行います。 クラスター構成は、1 つの m1.medium インスタン スマスターノードと 1 つの m1.medium インスタンスコアノードです。 詳細については、「AWS Data Pipeline Pricing」、「Amazon EMR Pricing」、「Amazon S3 Pricing」を参照してください。 データをエクスポートおよびインポートデータする ための前提条件 データのエクスポートとインポートに AWS Data Pipeline を使用するときは、パイプラインによっ て実行できるアクションと消費できるリソースを指定する必要があります。許可されるそれらのアク ションとリソースは AWS Identity and Access Management (IAM) ロールを使用して定義します。 また、IAM ポリシーを作成し、IAM ユーザーまたはグループにアタッチすることで、アクセスを制御 できます。これらのポリシーでは、DynamoDB データに対してインポートおよびエクスポートが許可 されるユーザーを指定できます。 Important エクスポートとインポートを実行する IAM ユーザーには、アクティブな AWS アクセスキー ID とシークレットキーが必要です。詳細については、『IAM ユーザーガイド』の「IAM ユー ザーのアクセスキーの管理」を参照してください。 AWS Data Pipeline の IAM ロールを作成する AWS Data Pipeline を使用するには、次の IAM ロールが AWS アカウントにあることが必要です。 • DataPipelineDefaultRole - パイプラインによって自動的に実行されるアクション。 • DataPipelineDefaultResourceRole - パイプラインによって自動的にプロビジョニングされる AWS リソース。DynamoDB データのエクスポートとインポートの場合、これらのリソースには Amazon EMR クラスターと、そのクラスターに関連付けられている Amazon EC2 インスタンスが含まれま す。 これまでに AWS Data Pipeline を使用したことがない場合は、DataPipelineDefaultRole と DataPipelineDefaultResourceRole を自分で作成する必要があります。作成したそれらのロールを使用 して、必要に応じていつでも DynamoDB データをエクスポートしたりインポートしたりできます。 Note 以前に AWS Data Pipeline コンソールを使用してパイプラインを作成した場 合、DataPipelineDefaultRole と DataPipelineDefaultResourceRole はその時点で自動的 に作成されています。これ以上の操作は必要ありません。このセクションをスキップ し、DynamoDB コンソールを使用したパイプラインの作成を開始できます。詳細につい ては、「DynamoDB から Amazon S3 にデータをエクスポートする (p. 554)」および 「Amazon S3 から DynamoDB にデータをインポートする (p. 555)」を参照してください。 1. https://console.aws.amazon.com/iam/ で Identity and Access Management (IAM) コンソールにサ インインします。 2. IAM コンソールダッシュボードで [Roles] をクリックします。 3. [Create New Role] をクリックし、次の操作を実行します。 API Version 2012-08-10 550 Amazon DynamoDB 開発者ガイド データをエクスポートおよびイン ポートデータするための前提条件 4. a. [Role Name] フィールドに「DataPipelineDefaultRole」と入力し、[Next Step] をクリッ クします。 b. [Select Role Type] パネルの [AWS Service Roles] リストで、[AWS Data Pipeline] に移動し、 [Select] をクリックします。 c. [Attach Policy] パネルで [AWSDataPipelineRole] ポリシーの横にあるボックスをクリック し、[Next Step] をクリックします。 d. [Review] パネルで [Create Role] をクリックします。 [Create New Role] をクリックし、次の操作を実行します。 a. [Role Name] フィールドに「DataPipelineDefaultResourceRole」と入力し、[Next Step] をクリックします。 b. [Select Role Type] パネルの [AWS Service Roles] リストで、[Amazon EC2 Role for Data Pipeline] に移動し、[Select] をクリックします。 c. [Attach Policy] パネルで [AmazonEC2RoleforDataPipelineRole] ポリシーの横にあるボックス をクリックし、[Next Step] をクリックします。 d. [Review] パネルで [Create Role] をクリックします。 これらのロールを作成できたので、DynamoDB コンソールを使用したパイプラインの作成を開始でき ます。詳細については、「DynamoDB から Amazon S3 にデータをエクスポートする (p. 554)」お よび「Amazon S3 から DynamoDB にデータをインポートする (p. 555)」を参照してください。 IAM ユーザーおよびグループへのエクスポートおよびイン ポートタスクを実行するためのアクセス権限の付与 他の IAM ユーザーまたはグループにその DynamoDB テーブルのデータのエクスポートとインポート を許可するには、IAM ポリシーを作成し、指定したユーザーまたはグループにアタッチできます。ポ リシーには、これらのタスクを実行するために必要なアクセス権限のみが含まれます。 AWS 管理ポリシーを使用したフルアクセスの付与 次の手順は、AWS 管理ポリシー AmazonDynamoDBFullAccesswithDataPipeline を IAM ユー ザーにアタッチする方法を説明しています。この管理ポリシーは、AWS Data Pipeline および DynamoDB リソースへのフルアクセスを提供します。 1. https://console.aws.amazon.com/iam/ で Identity and Access Management (IAM) コンソールにサ インインします。 2. IAM コンソールダッシュボードで、[Users] をクリックし、変更するユーザーを選択します。 3. [Permissions] タブで [Attach Policy] をクリックします。 4. [Attach Policy] パネルで AmazonDynamoDBFullAccesswithDataPipeline を選択し、[Attach Policy] をクリックします。 Note 同様の手順を使用して、この管理ポリシーをユーザーではなくグループにアタッチできま す。 特定の DynamoDB テーブルへのアクセスの制限 アクセスを制限し、ユーザーがテーブルのサブセットのエクスポートまたはインポートのみできるよ うにするには、カスタマイズした IAM ポリシードキュメントを作成する必要があります。AWS 管理 ポリシー AmazonDynamoDBFullAccesswithDataPipeline をカスタムポリシーの開始点として使 用し、このポリシーを変更して、ユーザーが、指定されたテーブルのみを操作するようにできます。 API Version 2012-08-10 551 Amazon DynamoDB 開発者ガイド データをエクスポートおよびイン ポートデータするための前提条件 たとえば、IAM ユーザーに Forum、Thread、Reply のテーブルに対してのみエクスポートまたはイン ポートを許可するとします。この手順では、ユーザーがそれらテーブルを操作できるが、それ以外は 操作できないようにするカスタムポリシーを作成する方法を示します。 1. https://console.aws.amazon.com/iam/ で Identity and Access Management (IAM) コンソールにサ インインします。 2. IAM コンソールダッシュボードから [Policies] をクリックし、[Create Policy] をクリックします。 3. [Create Policy] パネルで、[Copy an AWS Managed Policy] に移動し、[Select] をクリックしま す。 4. [Copy an AWS Managed Policy] パネルで、AmazonDynamoDBFullAccesswithDataPipeline に移動し、[Select] をクリックします。 5. [Review Policy] パネルで、以下の作業を行います。 a. 自動生成される [Policy Name] および [Description] を確認します。必要に応じて、これらの 値を変更できます。 b. [Policy Document] テキストボックスで、特定のテーブルへのアクセスを制限するポリシー を編集します。デフォルトでは、ポリシーはすべてのテーブルのすべての DynamoDB アク ションを許可します。 { "Version": "2012-10-17", "Statement": [ { "Action": [ "cloudwatch:DeleteAlarms", "cloudwatch:DescribeAlarmHistory", "cloudwatch:DescribeAlarms", "cloudwatch:DescribeAlarmsForMetric", "cloudwatch:GetMetricStatistics", "cloudwatch:ListMetrics", "cloudwatch:PutMetricAlarm", "dynamodb:*", "sns:CreateTopic", "sns:DeleteTopic", "sns:ListSubscriptions", "sns:ListSubscriptionsByTopic", "sns:ListTopics", "sns:Subscribe", "sns:Unsubscribe" ], "Effect": "Allow", "Resource": "*", "Sid": "DDBConsole" }, ...remainder of document omitted... ポリシーを制限するには、最初に次の行を削除します。 "dynamodb:*", 次に、Forum、Thread、および Reply のテーブルのみへのアクセスを許可する新しい Action を作成します。 API Version 2012-08-10 552 Amazon DynamoDB 開発者ガイド データをエクスポートおよびイン ポートデータするための前提条件 { "Action": [ "dynamodb:*" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/Forum", "arn:aws:dynamodb:us-west-2:123456789012:table/Thread", "arn:aws:dynamodb:us-west-2:123456789012:table/Reply" ] }, Note us-west-2 は DynamoDB テーブルがあるリージョンに置き換えてくださ い。123456789012 は AWS アカウント番号に置き換えてください。 最後に、ポリシードキュメントに新しい Action を追加します。 { "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:*" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:us-west-2:123456789012:table/Forum", "arn:aws:dynamodb:us-west-2:123456789012:table/Thread", "arn:aws:dynamodb:us-west-2:123456789012:table/Reply" ] }, { "Action": [ "cloudwatch:DeleteAlarms", "cloudwatch:DescribeAlarmHistory", "cloudwatch:DescribeAlarms", "cloudwatch:DescribeAlarmsForMetric", "cloudwatch:GetMetricStatistics", "cloudwatch:ListMetrics", "cloudwatch:PutMetricAlarm", "sns:CreateTopic", "sns:DeleteTopic", "sns:ListSubscriptions", "sns:ListSubscriptionsByTopic", "sns:ListTopics", "sns:Subscribe", "sns:Unsubscribe" ], "Effect": "Allow", "Resource": "*", "Sid": "DDBConsole" }, API Version 2012-08-10 553 Amazon DynamoDB 開発者ガイド DynamoDB から Amazon S3 に データをエクスポートする ...remainder of document omitted... 6. ポリシーの設定が正しいことを確認したら、[Create Policy] をクリックします。 ポリシーを作成したら、IAM ユーザーにポリシーをアタッチできます。 1. IAM コンソールダッシュボードで、[Users] をクリックし、変更するユーザーを選択します。 2. 3. [Permissions] タブで [Attach Policy] をクリックします。 [Attach Policy] パネルでポリシー名を選択し、[Attach Policy] をクリックします。 Note 同様の手順を使用して、ポリシーをユーザーではなくグループにアタッチできます。 DynamoDB から Amazon S3 にデータをエクスポー トする このセクションでは、1 つ以上の DynamoDB テーブルから Amazon S3 バケットにデータをエクス ポートする方法について説明します。エクスポートを実行する前に、Amazon S3 バケットを作成する 必要があります。 Important これまでに AWS Data Pipeline を使用したことがない場合は、この手順を実行する前に 2 つ の IAM ロールを設定する必要があります。詳細については、「AWS Data Pipeline の IAM ロールを作成する (p. 550)」を参照してください。 1. 2. Sign in to the AWS マネジメントコンソール and open the AWS Data Pipeline console at https:// console.aws.amazon.com/datapipeline/. すでに現在の AWS リージョンにパイプラインがない場合は、[Get started now] を選択します。 3. それ以外の場合、少なくとも 1 つのパイプラインがある場合は、[Create new pipeline] を選択し ます。 [Create Pipeline] ページで、次の操作を実行します。 a. [Name] フィールドで、パイプラインの名前を入力します。例: MyDynamoDBExportPipeline。 b. [Source] パラメーターで、[Build using a template] を選択します。ドロップダウンテンプ レートのリストから、[Export DynamoDB table to S3] を選択します。 c. [Source DynamoDB table name] フィールドに、エクスポートする DynamoDB テーブルの名 前を入力します。 d. [Output S3 Folder] テキストボックスに、エクスポートファイルが書き込まれる Amazon S3 の URI を入力します。以下に例を示します。s3://mybucket/exports この URI の形式は s3://bucketname/folder で、次のような構成になっています。 e. • bucketname は Amazon S3 バケットの名前です。 • folder はそのバケット内のフォルダーの名前です。フォルダーが存在し ない場合は、自動的に作成されます。フォルダーの名前を指定しない場合 は、s3://bucketname/region/tablename という形式で名前が付けられます。 [S3 location for logs] テキストボックスに、エクスポート用のログファイルが書き込まれる Amazon S3 の URI を入力します。以下に例を示します。s3://mybucket/logs/ API Version 2012-08-10 554 Amazon DynamoDB 開発者ガイド Amazon S3 から DynamoDB にデータをインポートする [S3 Log Folder] の URI 形式は [Output S3 Folder] のものと同じです。URI はフォルダに解 決される必要があります。ログファイルを S3 バケットの最上位に書き込むことはできませ ん。 4. すべての設定が正しいことを確認したら、[Activate] をクリックします。 これで、パイプラインが作成されます。このプロセスが完了するまでに数分かかることがありま す。AWS Data Pipeline コンソールで進捗状況をモニターすることができます。 エクスポートが完了したら、Amazon S3 コンソールに移動して、エクスポートファイルを表示できま す。ファイルはテーブルと同じ名前のフォルダーに置かれ、YYYY-MM-DD_HH.MM という形式で名前 が付けられます。このファイルの内部形式については、AWS Data Pipeline 開発者ガイド の「Verify Data Export File」を参照してください。 Amazon S3 から DynamoDB にデータをインポート する このセクションでは、すでに DynamoDB テーブルからデータをエクスポートし、エクスポート ファイルが Amazon S3 バケットに書き込まれているとします。このファイルの内部形式について は、AWS Data Pipeline 開発者ガイド の「Verify Data Export File」を参照してください。これは DynamoDB が AWS Data Pipeline を使用してインポートできる唯一のファイル形式であることに注意 してください。 ソーステーブルという用語は、データのエクスポート元となったテーブルに使用します。インポート 先テーブルという用語は、データのインポート先となるテーブルに使用します。エクスポートファイ ルから Amazon S3 にデータをインポートできます。ただし、次のすべての条件を満たしていること が前提です。 • インポート先テーブルがすでに存在する(インポートプロセスによってテーブルは作成されませ ん) • インポート先テーブルとソーステーブルのキースキーマが同じ インポート先テーブルは空である必要はありません。ただしインポートプロセスでは、インポート先 テーブルのデータ項目のうち、エクスポートファイルの項目とキーが同じものはすべて置き換えら れます。たとえば、Customer テーブルに CustomerId というキーがあり、そのテーブルに 3 つの項 目(CustomerId 1、2、3)のみがあるとします。エクスポートファイルにも CustomerID 1、2、3 の データ項目がある場合、インポート先テーブルの項目はエクスポートファイルのものと置き換えられ ます。エクスポートファイルに CustomerId 4 のデータ項目もある場合、その項目がインポート先テー ブルに追加されます。 インポート先テーブルは異なる AWS リージョンに置くことができます。たとえば、米国西部 (オレ ゴン) リージョンに Customer テーブルがあり、そのデータを Amazon S3 にエクスポートするとしま す。エクスポートしたデータは 欧州 (アイルランド) リージョン内の同じ Customer テーブルにイン ポートできます。これは、クロスリージョンのエクスポートとインポートと呼ばれています。AWS リージョンのリストについては、『AWS General Reference』の「リージョンとエンドポイント」を 参照してください。 AWS マネジメントコンソール では、一度に複数のソーステーブルをエクスポートできます。ただ し、一度にインポートできるのは 1 つのテーブルのみです。 1. Sign in to the AWS マネジメントコンソール and open the AWS Data Pipeline console at https:// console.aws.amazon.com/datapipeline/. 2. (省略可能) クロスリージョンのインポートを実行する場合、ウィンドウの右上隅にあるインポー ト先リージョンを選択します。 3. [Create new pipeline] を選択します。 API Version 2012-08-10 555 Amazon DynamoDB 開発者ガイド トラブルシューティング 4. [Create Pipeline] ページで、次の操作を実行します。 a. [Name] フィールドで、パイプラインの名前を入力します。例: MyDynamoDBImportPipeline。 b. [Source] パラメーターで、[Build using a template] を選択します。ドロップダウンテンプ レートのリストから、[Import DynamoDB backup data from S3] を選択します。 c. [Input S3 Folder] テキストボックスに、エクスポートファイルが見つかる Amazon S3 の URI を入力します。以下に例を示します。s3://mybucket/exports この URI の形式は s3://bucketname/folder で、次のような構成になっています。 • bucketname は Amazon S3 バケットの名前です。 • folder はエクスポートファイルを含むフォルダーの名前です。 インポートジョブでは、指定した Amazon S3 の場所にファイルが見つかることが想定さ れます。このファイルの内部形式については、AWS Data Pipeline 開発者ガイド の「Verify Data Export File」を参照してください。 d. [Target DynamoDB table name] フィールドに、データをインポートする DynamoDB テーブ ルの名前を入力します。 e. [S3 location for logs] テキストボックスに、インポート用のログファイルが書き込まれる Amazon S3 の URI を入力します。以下に例を示します。s3://mybucket/logs/ [S3 Log Folder] の URI 形式は [Output S3 Folder] のものと同じです。URI はフォルダに解 決される必要があります。ログファイルを S3 バケットの最上位に書き込むことはできませ ん。 5. すべての設定が正しいことを確認したら、[Activate] をクリックします。 これで、パイプラインが作成されます。このプロセスが完了するまでに数分かかることがあります。 インポートジョブはパイプラインの作成直後に開始されます。 トラブルシューティング このセクションでは、DynamoDB のエクスポートについていくつかの基本的な障害モードとトラブル シューティングを取り上げます。 エクスポートまたはインポート時にエラーが発生した場合、AWS Data Pipeline コンソールのパイプ ラインステータスは「ERROR」として表示されます。この場合は、エラーの発生したパイプラインの 名前をクリックして、その詳細ページに移動します。これにより、パイプラインのすべてのステップ の詳細と、各ステップのステータスが表示されます。特に、表示される実行スタックトレースを確認 します。 最後に、Amazon S3 バケットに移動し、そこに書き込まれたすべてのエクスポートまたはインポート ログファイルを探します。 次に示しているのは、パイプラインのエラーの原因として考えられるいくつかの一般的な問題とその 対処方法です。パイプラインを診断するには、表示されたエラーと次に示している問題を比較しま す。 • インポートの場合は、インポート先テーブルがすでに存在すること、インポート先テーブルにソー ステーブルと同じキースキーマがあることを確認します。これらの条件が満たされていない場合、 インポートは失敗します。 • 指定した Amazon S3 バケットが作成されていること、そのバケットに対する読み込みと書き込み のアクセス許可があることを確認します。 • パイプラインがその実行タイムアウトを超えている可能性があります(このパラメーターはパイプ ラインの作成時に設定しています)。たとえば、1 時間の実行タイムアウトを設定している場合が API Version 2012-08-10 556 Amazon DynamoDB 開発者ガイド AWS Data Pipeline と DynamoDB 用の定義済みテンプレート ありますが、エクスポートジョブでこれより長い時間が必要だった可能性があります。パイプライ ンを削除して作成し直してみてください。ただし実行タイムアウト間隔は前回よりも長くします。 • エクスポートまたはインポートを実行するための正しいアクセス許可がない可能性があります。詳 細については、「データをエクスポートおよびインポートデータするための前提条件 (p. 550)」を 参照してください。 • AWS アカウントのリソース制限(Amazon EC2 インスタンスの最大数や AWS Data Pipeline パイ プラインの最大数など)に達した可能性があります。これらの上限の増加をリクエストする方法な ど、詳細については、AWS General Reference の「AWS Service Limits」を参照してください。 Tip パイプラインのトラブルシューティングの詳細については、『AWS Data Pipeline 開発者ガイ ド』の「Troubleshooting」を参照してください。 AWS Data Pipeline と DynamoDB 用の定義済みテ ンプレート AWS Data Pipeline のしくみをより深く理解するには、『AWS Data Pipeline 開発者ガイド』を参照 することをお勧めします。このガイドには、パイプラインを作成して操作する手順について説明した チュートリアルが含まれています。これらのチュートリアルは、独自のパイプラインの作成を開始す るときに参考になります。また、DynamoDB のチュートリアルを参照することをお勧めします。この チュートリアルでは、要件に合わせてカスタマイズ可能なインポートおよびエクスポートパイプライ ンを作成する手順について説明しています。『AWS Data Pipeline 開発者ガイド』の「チュートリア ル: AWS Data Pipeline を使用した Amazon DynamoDB のエクスポートとインポート」を参照してく ださい。 AWS Data Pipeline には、パイプラインを作成するためのテンプレートがいくつか用意されていま す。次のテンプレートは DynamoDB に関連しています。 DynamoDB と Amazon S3 の間のデータのエクスポート AWS Data Pipeline コンソールには、DynamoDB と Amazon S3 間でデータをエクスポートするため の定義済みテンプレートが 2 つ用意されています。これらのテンプレートの詳細については、『AWS Data Pipeline 開発者ガイド』の次のセクションを参照してください。 • Export DynamoDB to Amazon S3 • Export Amazon S3 to DynamoDB API Version 2012-08-10 557 Amazon DynamoDB 開発者ガイド キャパシティーユニットとプロ ビジョニングされるスループット DynamoDB での制限 このセクションでは、Amazon DynamoDB 内の現在の制限について説明します (制限がない場合もあ ります)。以下に示す各制限は、指定がない限り、リージョン単位で適用されます。 トピック • キャパシティーユニットとプロビジョニングされるスループット (p. 558) • テーブル (p. 560) • セカンダリインデックス (p. 560) • パーティションキーおよびソートキー (p. 560) • 名前付けルール (p. 561) • データ型 (p. 561) • アイテム (p. 562) • 属性 (p. 562) • 式パラメーター (p. 563) • DynamoDB ストリーム (p. 563) • API 固有の制限 (p. 564) キャパシティーユニットとプロビジョニングされ るスループット キャパシティーユニットサイズ 最大サイズ 4 KB の項目について、1 つの読み込みキャパシティーユニット = 1 秒あたり 1 回の強力な 整合性のある読み込み、あるいは 1 秒あたり 2 回の結果整合性のある読み込み。 最大サイズ 1 KB の項目について、1 つの書き込みキャパシティーユニット = 1 秒あたり 1 回の書き込 み API Version 2012-08-10 558 Amazon DynamoDB 開発者ガイド プロビジョニングされたスループットの最小値と最大値 プロビジョニングされたスループットの最小値と最 大値 テーブルまたはグローバルセカンダリインデックスについて、プロビジョニングされるスループット の最小設定は 1 つの読み込みキャパシティーユニットと 1 つの書き込みキャパシティーユニットで す。 AWS アカウントでは、プロビジョニングできるスループットについて、いくつかの初期的な最大制限 があります。 • 米国東部(バージニア北部) リージョン: • テーブル単位 – 読み込みキャパシティーユニット数 40,000 および書き込みキャパシティーユ ニット数 40,000 • アカウント単位 – 読み込みキャパシティーユニット数 80,000 および書き込みキャパシティーユ ニット数 80,000 • その他すべてのリージョン: • テーブル単位 – 読み込みキャパシティーユニット数 10,000 および書き込みキャパシティーユ ニット数 10,000 • アカウント単位 – 読み込みキャパシティーユニット数 20,000 および書き込みキャパシティーユ ニット数 20,000 プロビジョニングされたスループット制限には、すべてのグローバルセカンダリインデックスの容量 とともに、テーブルの容量の合計が含まれます。 これらの制限はリクエストによって増加させることができます。詳細については、https:// aws.amazon.com/ サポートを参照してください。 AWS マネジメントコンソールでは、特定のリージョンでプロビジョニングされた現在の容量を 表示し、制限に近づきすぎていないことを確認できます。デフォルトの制限を増加させた場合 は、DescribeLimits オペレーションを使用して現在の制限値を確認できます。 プロビジョニングされるスループットを増やす AWS マネジメントコンソール または UpdateTable オペレーションを使用して、必要な回数だけ ReadCapacityUnits または WriteCapacityUnits を増やすことができます。1 回の呼び出し で、テーブル、そのテーブルの任意の グローバルセカンダリインデックス、またはこれらの任意の 組み合わせに対して、プロビジョニングされるスループットを増やすことができます。新しい設定 は、UpdateTable オペレーションが完了するまでは有効になりません。 プロビジョニングされた容量を追加する場合、アカウントごとの制限を超えることはできません。ま た、DynamoDB では、プロビジョニングされた容量を急速に増やすことはできません。これらの制 限とは別に、テーブルにプロビジョニングされた容量はどれだけでも増やすことができます。アカウ ントごとの制限の詳細については、前述の「プロビジョニングされたスループットの最小値と最大 値 (p. 559)」セクションを参照してください。 プロビジョニングされるスループットを減らす テーブルの ReadCapacityUnits または WriteCapacityUnits 設定を減らすことができますが、1 UTC 暦日にテーブルあたり 4 回 以上減らすことはできません。1 回のオペレーションで、テーブル、 そのテーブルの任意のグローバルセカンダリインデックス、またはテーブルとグローバルセカンダリ インデックスの任意の組み合わせに対して、プロビジョニングされるスループットを減らすことがで きます。 API Version 2012-08-10 559 Amazon DynamoDB 開発者ガイド テーブル UpdateTable オペレーションのすべてのテーブルと グローバルセカンダリインデックス につい て、ReadCapacityUnits または WriteCapacityUnits(あるいはその両方)を減らすことができ ます。新しい設定は、UpdateTable オペレーションが完了するまでは有効になりません。 テーブル テーブルのサイズ テーブルのサイズには実用的な制限はありません。テーブルは項目数やバイト数について制限があり ません。 アカウントあたりのテーブル数 AWS アカウントについては、リージョンごとに 256 個のテーブルという初期制限があります。 この制限の増加をリクエストすることができます。詳細については、「https://aws.amazon.com/サ ポート」を参照してください。 セカンダリインデックス テーブルごとのセカンダリインデックス 1 つのテーブルで、最大 5 のlocal secondary indexと 5 のグローバルセカンダリインデックスを定義 できます。 テーブルあたりの射影されたセカンダリインデック ス属性 1 つのテーブルのすべてのローカルおよびグローバル セカンダリインデックス に対して、合計で最大 20 個の属性を射影することができます。これは、ユーザー指定の射影された属性だけに適用されま す。 CreateTable オペレーションでは、ProjectionType として INCLUDE を指定した場合に は、NonKeyAttributes で指定した属性の数をすべての セカンダリインデックス で集計した合計値 が 20 を超えてはいけません。同じ属性名を 2 つの異なるインデックスに射影した場合には、合計を 計算する際に 2 つの異なる属性として計算されます。 この制限は、ProjectionType が KEYS_ONLY または ALL である セカンダリインデックス には適用 されません。 パーティションキーおよびソートキー パーティションキーの長さ パーティションキーと値の最小長は 1 バイトです。最大長は 2048 バイト です。 パーティションキーの値 テーブルまたはセカンダリインデックスについて、パーティションキー値の明確な数に関する実質的 な制限はありません。 API Version 2012-08-10 560 Amazon DynamoDB 開発者ガイド ソートキーの長さ ソートキーの長さ ソートキーと値の最小長は 1 バイトです。最大長は 1024 バイト です。 ソートキー値 一般的に、パーティションキーの値ごとのソートキーの値の数について、実質的に制限はありませ ん。 テーブルの例外はlocal secondary indexです。local secondary indexでは、項目コレクションのサイズ に制限があります。異なるパーティションキーの値について、すべてのテーブルおよびインデックス 項目の合計サイズは、10 GB を超えることはできません。これにより、パーティションキー値あたり のソートキーの数が制約を受ける可能性があります。詳細については、「項目コレクションのサイズ 制限 (p. 393)」を参照してください。 名前付けルール テーブル名およびセカンダリインデックス名 テーブルとセカンダリインデックスの名前は、3 文字以上、255 文字以下である必要があります。使 用できる文字は次のとおりです。 • A-Z • a-z • 0-9 • _ (下線) • - (ハイフン) • . (ドット) 属性名 一般的に、属性名は 1 文字以上、64 KB 以下である必要があります。 例外は次のとおりです。これらの属性名は 255 文字以下である必要があります。 • Secondary indexパーティションキー名。 • Secondary indexソートキー名。 • ユーザー指定の射影された属性の名前(local secondary index のみに適用)。CreateTable オペ レーションでは、ProjectionType を INCLUDE に指定した場合には、NonKeyAttributes パラ メータの属性名の長さが制限されます。射影タイプ KEYS_ONLY および ALL には影響しません。 これらの属性名は UTF-8 を使用してエンコードする必要があり、それぞれの名前の合計サイズが (エ ンコード後に) 255 バイトを超えることはできません。 データ型 文字列 文字列の長さは、最大項目サイズ 400 KB によって制限されます。 API Version 2012-08-10 561 Amazon DynamoDB 開発者ガイド 数値 文字列は、UTF-8 バイナリエンコードの Unicode です。UTF-8 は可変幅のエンコードであるた め、DynamoDB により、UTF-8 バイトを使用して文字列の長さが決まります。 数値 数値は、最大 38 桁の精度であり、正、負、または 0 のいずれかです。 • 正の範囲: 1E-130~9.9999999999999999999999999999999999999E+125 • 負の範囲: -9.9999999999999999999999999999999999999E+125~-1E-130 DynamoDB は JSON 文字列を使用してリクエストと返信の数値データを表します。詳細については、 「DynamoDB 低レベル API (p. 68)」を参照してください。 数値の精度が重要な場合は、数値型から変換する文字列を使用して、DynamoDB に数値を渡します。 バイナリ バイナリの長さは、最大項目サイズ 400 KB によって制限されます。 バイナリ属性を操作するアプリケーションは、データを DynamoDB に送信する前に、それを Base64 形式でエンコードする必要があります。DynamoDB は、受信したデータを署名なしバイト配列にデ コードし、それを属性の長さとして使用します。 アイテム 項目のサイズ DynamoDB の最大項目のサイズ 400 KB で、属性名バイナリの長さ (UTF-8 長) と属性値の長さ (これ もバイナリ長) を含みます。属性名はサイズ制限に反映されます。 たとえば、2 つの属性を持つ項目があり、1 つの属性は名前が "shirt-color" で値が "R"、別の属性は名 前が "shirt-size" で値が "M" であるとします。この項目の合計サイズは 23 バイトです。 ローカルセカンダリインデックスを持つテーブルの 項目サイズ テーブルの local secondary index ごとに、以下を合計したサイズに関して 400 KB の制限がありま す。 • テーブルの項目データのサイズ。 • その項目に対応する local secondary index エントリのサイズ。キーの値と射影された属性を含みま す。 属性 項目あたりの属性名と値のペア 項目あたりの属性の累積サイズは、DynamoDB の最大項目サイズ (400 KB) 内である必要がありま す。 API Version 2012-08-10 562 Amazon DynamoDB 開発者ガイド リスト、マップ、またはセットの値の最大数 リスト、マップ、またはセットの値の最大数 値を含む項目が 400 KB のサイズ制限内である限り、リスト、マップ、またはセットの値の最大数の 制限はありません。 属性値 属性値は空の文字列または空のセット (文字列セット、数値セット、またはバイナリセット) にするこ とはできません。ただし、空のリストおよびマップは許可されます。 入れ子の属性の深さ DynamoDB は深さが最大 32 レベルの入れ子の属性をサポートします。 式パラメーター 式パラメーターには、ProjectionExpression、ConditionExpression、UpdateExpression、 および FilterExpression があります。 長さ 任意の式の最大長は 4 KB です。たとえば、ConditionExpression a=b のサイズは 3 バイトです。 1 つの式属性名または式属性値の最大長は 255 バイトです。たとえば、#name は 5 バイト、:val は 4 バイトです。 式のすべての置換変数の最大長は 2 MBです。これはすべての ExpressionAttributeNames および ExpressionAttributeValues の長さの合計です。 演算子およびオペランド UpdateExpression で許容される演算子または関数の最大数は 300 です。たとえ ば、UpdateExpression SET a = :val1 + :val2 + :val3 は 2 つの "+" 演算子を含みます。 IN コンパレータのオペランドの最大数は 100 です。 予約語 DynamoDB に、予約語と競合する名前の使用を防止する機構はありません (詳細な一覧については、 「DynamoDB の予約語 (p. 668)」を参照してください)。 ただし、式パラメーターで予約語を使用する場合は、ExpressionAttributeNames も指定する必要 があります。詳細については、「属性の名前および値でのプレースホルダーの使用 (p. 213)」を参照 してください。 DynamoDB ストリーム DynamoDB ストリーム のシャードの同時リーダー 同じ DynamoDB ストリーム シャードから同時に複数のプロセスの読み取りを許可しないでくださ い。この制限を超えると、リクエストのスロットリングが発生する場合があります。 API Version 2012-08-10 563 Amazon DynamoDB 開発者ガイド ストリームが有効なテーブル の最大書き込みキャパシティー ストリームが有効なテーブルの最大書き込みキャパ シティー 次の書き込みキャパシティーの制限が、DynamoDB ストリームを有効にしたテーブルに適用されま す。 • 米国東部 (バージニア北部) リージョン: • テーブル単位 – 40,000 書き込みキャパシティーユニット • アカウント単位– 80,000 書き込みキャパシティーユニット • その他すべてのリージョン: • テーブル単位 – 10,000 書き込みキャパシティーユニット • アカウント単位– 20,000 書き込みキャパシティーユニット API 固有の制限 CreateTable/UpdateTable/DeleteTable 一般的に、最大 10 の CreateTable、UpdateTable、および、 DeleteTable リクエストを同 時に実行できます (任意の組み合わせ)。つまり、CREATING、UPDATING、または DELETING の状 態のテーブルの合計数が 10 を超えることはできません。 唯一の例外は、1 つ以上の セカンダリインデックス を持つテーブルを作成する場合です。そのよ うなリクエストは一度に 5 件まで実行できます。ただしテーブルまたはインデックスの仕様が複 雑な場合は、DynamoDB によって同時リクエスト数が一時的に 5 件未満に減らされることがあり ます。 BatchGetItem 1 回の BatchGetItem オペレーションで、最大 100 項目を取得できます。取得するすべての項目 の合計サイズは 16 MB を超えることはできません。 BatchWriteItem 単一の BatchWriteItem オペレーションは、最大 25 の PutItem または DeleteItem リクエス トを含むことができます。書き込むすべての項目の合計サイズは 16 MB を超えることはできませ ん。 DescribeLimits DescribeLimits は定期的に呼び出すのみにする必要があります。1 分以内に複数回呼び出す と、スロットリングエラーが発生する可能性があります。 Query Query の結果セットは、呼び出しあたり 1 MB に制限されます。クエリ応答から LastEvaluatedKey を使用して、結果をさらに取り出すこともできます。 Scan Scan の結果セットは、呼び出しあたり 1 MB に制限されます。スキャン応答から LastEvaluatedKey を使用して、結果をさらに取り出すこともできます。 API Version 2012-08-10 564 Amazon DynamoDB 開発者ガイド テーブルのベストプラクティス DynamoDB のベストプラクティス このセクションを使用して、パフォーマンスを最大にしてスループットコストを最小にするための推 奨事項をすばやく見つけてください。 テーブルのベストプラクティス DynamoDB テーブルは複数のパーティションに分散されています。最良の結果を得るには、パフォー マンスを低下させる可能性がある I/O の「ホットスポット」を発生させないために、読み込みおよび 書き込みアクティビティがテーブル内のすべての項目に均一に分散されるように、テーブルとアプリ ケーションを設計します。 • テーブル内のすべての項目に対して均一なデータアクセスを実現する設計 (p. 567) • パーティションの動作について (p. 569) • 急激に増大するキャパシティーは控えめに使用する (p. 573) • データアップロード時に書き込みアクティビティを分散する (p. 573) • 時系列データへのアクセスパターンを理解する (p. 574) • 人気の高い項目をキャッシュに格納する (p. 575) • プロビジョニングされたスループットを調整するときにワークロードの均一性を考慮する (p. 575) • 大規模環境でのアプリケーションのテスト (p. 576) 項目のベストプラクティス DynamoDB 項目はサイズが限定されています(「DynamoDB での制限 (p. 558)」を参照)。ただし、 テーブル内の項目数に制限はありません。大きなデータ属性値を項目内に格納する代わりに、ここに 示すアプリケーション設計方法を検討してください。 • 大規模な設定属性の代わりに 1 対多のテーブルを使用する (p. 577) • 複数テーブルの使用による多様なアクセスパターンのサポート (p. 578) • 大量の属性値を圧縮する (p. 579) • Amazon S3 に大量の属性値を格納する (p. 580) API Version 2012-08-10 565 Amazon DynamoDB 開発者ガイド クエリとスキャンのベストプラクティス • 大量の属性を複数の項目に分割する (p. 580) クエリとスキャンのベストプラクティス 予期しない突然の読み込みアクティビティがあると、テーブルやグローバルセカンダリインデックス のプロビジョニングされている読み込みキャパシティーが急速に消費されます。またそのようなアク ティビティは、複数のテーブルパーティションに均一に分散されていないと、効率が低下する可能性 があります。 • 読み込みアクティビティの急激な増大の回避 (p. 581) • 並列スキャンの利用 (p. 583) ローカルセカンダリインデックス のベストプラク ティス local secondary indexでは、データ用の代替ソートキーを定義することができます。テーブルのクエリ と同じ方法でlocal secondary indexのクエリを実行できます。local secondary index を使用する前に、 プロビジョニングされたスループットコスト、ストレージコスト、クエリの効率性について、固有の トレードオフがあることを認識する必要があります。 • インデックスの使用は控えめにする (p. 584) • 射影を慎重に選択する (p. 584) • フェッチを回避するための頻繁なクエリの最適化 (p. 585) • スパースなインデックスの利用 (p. 585) • 項目コレクションの拡張の監視 (p. 586) グローバルセカンダリインデックス のベストプラ クティス グローバルセカンダリインデックスでは、データ用の代替パーティションキーとソートキーの属性を 定義することができます。これらの属性は、テーブルパーティションのキーおよびソートキーと同じ である必要はありません。テーブルのクエリと同じ方法でグローバルセカンダリインデックスのクエ リを実行できます。local secondary index と同様、グローバルセカンダリインデックス にも、アプリ ケーションを設計するときに考慮する必要があるトレードオフがあります。 • ワークロードが均一になるようにキーを選択する (p. 586) • スパースなインデックスの利用 (p. 587) • グローバルセカンダリインデックス を使用したすばやい検索 (p. 587) • 結果整合性のある読み込みレプリカを作成する (p. 587) テーブルの操作のガイドライン トピック • テーブル内のすべての項目に対して均一なデータアクセスを実現する設計 (p. 567) • パーティションの動作について (p. 569) • 急激に増大するキャパシティーは控えめに使用する (p. 573) API Version 2012-08-10 566 Amazon DynamoDB 開発者ガイド テーブル内のすべての項目に対して 均一なデータアクセスを実現する設計 • データアップロード時に書き込みアクティビティを分散する (p. 573) • 時系列データへのアクセスパターンを理解する (p. 574) • 人気の高い項目をキャッシュに格納する (p. 575) • プロビジョニングされたスループットを調整するときにワークロードの均一性を考慮す る (p. 575) • 大規模環境でのアプリケーションのテスト (p. 576) このセクションでは、模範的なテーブルの操作方法について説明します。 テーブル内のすべての項目に対して均一なデータア クセスを実現する設計 テーブルのプロビジョニングされたスループットを最適に使用するには、次の要因が影響します。 • プライマリキーの選択 • 個々の項目に対するワークロードパターン プライマリキーは、テーブルの各項目を一意に識別します。プライマリキーはシンプル (パーティショ ンキー) または複合 (パーティションキーとソートキー) とすることができます。 データを保存するとき、DynamoDB はテーブルの項目を複数のパーティションに分割し、主にパー ティションキー値に基づいて、データを分散します。そのため、テーブルにプロビジョニング済みの 十分な量のリクエストスループットを得るには、ワークロードをパーティションキー値全体に均一に 分散します。パーティションキー値全体にリクエストを分散すると、パーティション全体にリクエス トが分散されます。 たとえば、1 つのテーブルに、頻繁にアクセスされるパーティションキー値がごく少数含まれる場合 (非常に頻繁に使用されるパーティションキー値が 1 つだけの場合もあります)、少数のパーティショ ン (場合によっては 1 つのパーティションだけ) にリクエストトラフィックが集中します。1 つまたは 一部のパーティションに偏ってしまうなど、ワークロードのバランスが極端に悪いと、リクエストで は、プロビジョニングされたスループットの全体的なレベルが達成されません。DynamoDB のスルー プットを最大限に活用するには、テーブルを作成するときに、パーティションキーに個別の値が多数 含まれ、できるだけランダムかつ均一に値がリクエストされるようにします。 この操作によって、スループットレベルを達成するために、すべてのパーティションキー値にアクセ スする必要があるというわけではありません。また、アクセスされるパーティションキー値の割合を 高くする必要があるというわけでもありません。ただし、より明確に区別できるパーティションキー 値にワークロードがアクセスするとき、それらのリクエストは、割り当てられたスループットレベ ルを十分に活用する方法で、分割されたスペース全体に展開されることに注意してください。一般的 に、テーブルのパーティションキー値の合計数に対する、アクセスされたパーティションキー値の割 合が大きくなるほど、スループットをより効率的に活用することができます。 パーティションキーの選択 一般的なパーティションキースキーマをいくつか比較し、プロビジョニングされたスループットの効 率について次の表に示します。 パーティションキーの値 均一性 ユーザー ID(アプリケーションに多くのユー ザーがある場合) 良い ステータスコード(可能性のあるステータス コードが少しだけある場合) 不良 API Version 2012-08-10 567 Amazon DynamoDB 開発者ガイド テーブル内のすべての項目に対して 均一なデータアクセスを実現する設計 パーティションキーの値 均一性 項目の作成日(直近の期間(日、時、分など) に切り上げられます) 不良 デバイス ID(各デバイスが比較的類似した間隔 でデータにアクセスする場合) 良い デバイス ID(追跡中のデバイスが大量にある場 不良 合でも、1 つのデバイスが他のすべてのデバイス よりもずっと人気がある場合) 単一のテーブル内にあるパーティションキー値の数が非常に少ない場合は、より明確に区別できる パーティションキー値全体を対象として、書き込みオペレーションを分散するように検討してくださ い。つまり、"ホット" パーティションキー値 (何度もリクエストされるパーティションキー値) を回避 するように、プライマリキー要素を構築してください。このようなパーティションキー値が原因で、 全体のパフォーマンス速度が低下する場合があります。 たとえば、複合プライマリキーを持つテーブルがあるとします。パーティションキーは項目の作成 日を表します (直近の日付に切り上げられます)。ソートキーは項目の識別子を表します。特定の日付 (2014-07-09 など) で、すべての新しい項目が同じパーティションキー値として書き込まれます。 テーブル全体が単一のパーティションに収まり(時間の経過に伴うデータの増加を考慮します)、ア プリケーションで必要となる読み込みスループットと書き込みスループットが単一のパーティション における読み込みと書き込みの容量を超過しない場合は、パーティション分割をしても、アプリケー ションが予想外の制限を受けることはありません。 ただし、テーブル全体が単一のパーティションには収まらないことが予想される場合は、テーブルの 完全にプロビジョニングされたスループットをより多く使用できるように、アプリケーションを設計 する必要があります。 複数のパーティションキー値を対象としたランダム化 アプリケーションの書き込みスループットを向上させる方法の 1 つとして、複数のパーティション キー値を対象とした書き込みをランダム化する方法があります。固定された数値のセット(たとえ ば、1~200)からランダムな数値を選択し、その数値をサフィックスとして日付に連結します。これ により、2014-07-09.1、2014-07-09.2 などのパーティションキー値が生成されます。この場合、 最大のパーティションキー値は 2014-07-09.200 になります。パーティションキーをランダム化す るため、毎日行われるテーブルへの書き込みは、すべてのパーティションキー値に均一に分散されま す。これにより、並列処理が向上し、全体的なスループットが高まります。 特定の日付についてすべての項目を読み込むには、各サフィックスのすべての項目を取得する必要が あります。たとえば、最初にパーティションキー値 2014-07-09.1 に対する Query リクエストを発 行し、次に 2014-07-09.2 に対する Query を発行します。この処理を 2014-07-09.200 まで繰り 返します。最終的には、アプリケーションですべての Query リクエストの結果をマージする必要があ ります。 算出された値の使用 ランダム化の方法によって、書き込みスループットを大幅に向上させることができます。ただし、特 定の項目を読み込むことは難しくなります。これは、項目を書き込むときにどのサフィックスが使用 されたかを把握できないためです。個々の項目を簡単に読み込むことができるようにするには、別の 方法を使用します。ランダムな数値を使用して項目をパーティションに分散するのではなく、項目が 持つ固有の情報に基づいて算出できる数値を使用します。 これまでの例を引き続き使用します。ここでは、各項目に OrderId があるとします。アプリケー ションで項目をテーブルに書き込む前に、この OrderId に基づいてパーティションキーのサフィック スを計算します。この計算では、1~200 の範囲の数値が算出される必要があります。これらの各数値 は、指定の名前のセット(またはユーザー ID のセット)を対象として、完全に均一に分散されます。 API Version 2012-08-10 568 Amazon DynamoDB 開発者ガイド パーティションの動作について この計算はシンプルな計算で十分です (OrderId の各文字の UTF-8 コードポイント値を乗算して、そ れを 200 + 1 で割った余りなど)。 パーティションキー値は、日付に計算結果がサフィックスとして連 結された値になります。この方法を使用すると、書き込みがパーティションキー値全体に均一に分散 され、パーティション全体にも均一に分散されます。これで、GetItem オペレーションを実行して、 特定の項目を簡単に読み込むことができます。これは、特定の OrderId 値を取得するときに、必要 となるパーティションキー値を計算できるためです。 特定の日付についてすべての項目を読み込むには、2014-07-09.N キー(N は 1~200 の数値)に対 する Query を発行し、アプリケーションですべての結果をマージする必要があります。ただし、すべ てのワークロードを利用する単一の "ホット" パーティションキー値の使用は回避してください。 パーティションの動作について DynamoDB によって自動的にテーブルパーティションが管理され、必要に応じて新しいパーティショ ンが追加されます。また、パーティション間で均等にプロビジョンドスループット性能が分散されま す。 テーブルに対して DynamoDB で最初に割り当てられるパーティションの数を予測することができま す。また、その予測と、使用する規模およびアクセスパターンを比較することもできます。また、増 えたストレージまたはプロビジョニングされたスループット要件に応じて、DynamoDB で割り当て られる追加のパーティションの数を見積もることもできます。これらの予測は、アプリケーションの ニーズに最適なテーブル設計を決める場合に役立ちます。 Note パーティションサイズとスループットに関する以下の詳細は、変更される場合があります。 パーティションの最初の割り当て 新しいテーブルを作成するときに、DynamoDB は指定のプロビジョニングされたスループット設定に 従ってテーブルのパーティションを割り当てます。 1 つのパーティションは、最大 3,000 個の読み込みキャパシティーユニットまたは 1,000 個の書き込 みキャパシティーユニットをサポートできます。新しいテーブルを作成するときに、パーティション の初期値は次のように表すことができます。 ( readCapacityUnits / 3,000 ) + ( writeCapacityUnits / 1,000 ) = initialPartitions (rounded up) たとえば、1,000 個の読み込みキャパシティーユニットと 500 個の書き込みキャパシティーユニット を使用してテーブルを作成したとします。この場合、パーティションの初期数は次のようになりま す。 ( 1,000 / 3,000 ) + ( 500 / 1,000 ) = 0.8333 --> 1 このため、単一のパーティションで、テーブルのすべてのプロビジョニングされたスループット要件 に対応できます。 ただし、1,000 個の読み込みユニットと 1,000 個の書き込みユニットがあるテーブルを作成した場 合、1 つのパーティションは指定されたスループット容量をサポートすることができません。 ( 1,000 / 3,000 ) + ( 1,000 / 1,000 ) = 1.333 --> 2 この場合、テーブルでは 2 つのパーティションが必要になり、各パーティションは 500 個の読み込み キャパシティーユニットと 500 個の書き込みキャパシティーユニットを保持します。 API Version 2012-08-10 569 Amazon DynamoDB 開発者ガイド パーティションの動作について パーティションのその後の割り当て 1 つのパーティションに約 10 GB 個のデータを保持でき、最大 3,000 個の読み込みキャパシティーユ ニットまたは 1,000 個の書き込みキャパシティーユニット数をサポートできます。 DynamoDB は、必要に応じて既存のパーティションを分割することによって、テーブルに追加のパー ティションを割り当てることができます。テーブルのパーティションの 1 つ (P) が、ストレージの制 限 (10 GB) を超えたとします。この場合、DynamoDB は次のようにパーティションを分割します。 1. 2 つの新しいパーティション (P1 および P2) を割り当てます。 2. P からのデータを P1 と P2 の間で均等に分散します。 3. テーブルから P を割り当て解除します。 次の図は、DynamoDB がパーティション分割を実行する方法を示しています。大きな四角形はパー ティションを示し、小さい四角形はテーブルのデータ項目を表します。 パーティションの分割中に、DynamoDB は古いパーティションからのデータを 2 つの新しいパーティ ションに均等に分散します (他のパーティションのデータは影響を受けません)。古いパーティション のプロビジョンドスループット性能は二つの新しいパーティション間で、均等に分散されます (パー ティションあたりのスループット容量 (p. 572) を参照)。 DynamoDB はバックグラウンドでパーティションの分割を自動的に実行することに注意してくださ い。テーブルは、指定されたスループットレベルで、読み込みおよび書き込みアクティビティに対し て完全に使用可能な状態のままになります。 パーティション分割は、以下に応じて発生します。 • プロビジョニングされたスループット設定の引き上げ • ストレージ要件の引き上げ プロビジョニングされたスループット設定の引き上げ テーブルのプロビジョンドされたスループットを引き上げ、テーブルの現在のパーティショニングス キームが新しい要件に対応できない場合、DynamoDB はパーティションの現在の数を 2 倍にします。 たとえば、5,000 個の読み込みキャパシティーユニットと 2,000 個の書き込みキャパシティーユニッ トを使用して新しいテーブルを作成したとします。パーティションの最初の割り当て (p. 569) の情 報を使用して、この新しいテーブルで 4 つのパーティションを必要とすることを決定できます。 ( 5,000 / 3,000 ) + ( 2,000 / 1,000 ) = 3.6667 --> 4 API Version 2012-08-10 570 Amazon DynamoDB 開発者ガイド パーティションの動作について 4 つの各パーティションは、1 秒あたり 1,250 個の読み込み (5,000 読み込みキャパティシーユニッ ト / 4 パーティション) および 1 秒あたり 500 個の書き込み (2,000 書き込みキャパティシーユニット / 4 パーティション) に対応できます。 ここで、テーブルの読み込みキャパシティーユニットを 5,000 から 8,000 に引き上げたとします。既 存の 4 つのパーティションは、この要件をサポートできません。応答 (「パーティションのその後の 割り当て (p. 570)」を参照) で、DynamoDB はパーティション数を 2 倍の 8 にします (4 * 2 = 8)。結 果の各パーティションは、1 秒あたり 1,000 個の読み込み (8,000 読み込みキャパティシーユニット / 8 パーティション) および 1 秒あたり 250 個の書き込み (2,000 書き込みキャパティシーユニット / 8 パーティション) に対応できます。 次の図は、テーブルの元の 4 つのパーティションと、DynamoDB によってパーティション数が 2 倍に なった後のパーティションスキームを示します。大きな四角形はパーティションを示し、小さい四角 形はテーブルのデータ項目を表します。 ストレージ要件の引き上げ 既存のパーティションがデータでいっぱいになると、DynamoDB によってそのパーティションが分割 されます。結果は 2 つのパーティションになり、古いパーティションからのデータは新しいパーティ ション間で均等に分割されます。 「プロビジョニングされたスループット設定の引き上げ (p. 570)」で説明するテーブルには 8 個の パーティションがあるため、最大容量は、次に示すように約 80 GB になります。 8 partitions * 10 GB = 80 GB これらのパーティションで容量がいっぱいになる場合、DynamoDB によってそのパーティションが分 割されます。その結果、次に示すように合計 9 個のパーティションになり、容量全体は 90 GB になり ます。 API Version 2012-08-10 571 Amazon DynamoDB 開発者ガイド パーティションの動作について 9 partitions * 10 GB = 90 GB 次の図は、容量がいっぱいになった元のパーティションの 1 つと、DynamoDB によってそのパーティ ションが分割された後のパーティションスキームを示します。大きな四角形はパーティションを示 し、小さい四角形はテーブルのデータ項目を表します。 パーティションあたりのスループット容量 テーブルのパーティション数を予測すると、パーティションごとの概算のスループット容量を判断 することができます。5,000 個の読み込みキャパシティーユニットと 2,000 個の書き込みキャパシ ティーユニットを使用してテーブルを作成するとします。DynamoDB により、新しいテーブルに 4 個 のパーティションが割り当てられます。 ( 5,000 / 3,000 ) + ( 2,000 / 1,000 ) = 3.6667 --> 4 次のようにして、パーティションごとの読み込みキャパシティーと書き込みキャパシティーの量を判 断できます。 5,000 read capacity units / 4 partitions = 1,250 read capacity units per partition 2,000 write capacity units / 4 partitions = 500 write capacity units per partition ここで、これら 4 つのパーティションの 1 つの容量がいっぱいになるとします。DynamoDB はその パーティションを分割し、それによりテーブルに 5 つのパーティションが割り当てられます。次に、 API Version 2012-08-10 572 Amazon DynamoDB 開発者ガイド 急激に増大するキャパシティーは控えめに使用する パーティションごとの読み込みキャパシティーと書き込みキャパシティーは次のように分散されま す。 1,250 read capacity units / 2 partitions = 625 read capacity units per child partition 500 write capacity units / 2 partitions = 250 write capacity units per child partition 上の結果 : • 5 つのパーティションのうち 3 つは、それぞれ読み込み容量 1,250 ユニットと書き込み容量 500 ユ ニットとなります。 • 残りの 2 つのパーティションは、それぞれ読み込み容量 625 ユニットと書き込み容量 250 ユニット となります。 テーブルのパーティションの数が増えると、各パーティションで利用できる読み込みキャパシティー と書き込みキャパシティーユニットの数が減ります。ただし、テーブルのプロビジョニングされたス ループットの合計は同じままです。 急激に増大するキャパシティーは控えめに使用する DynamoDB によって、パーティションごとのスループットを柔軟にプロビジョニングすることがで きます。 パーティションのスループットを十分に活用していない場合、後でスループットの利用率 が急激に増加した場合に備えて、DynamoDB では未使用のキャパシティーの一部を保持します。現在 DynamoDB は、未使用の読み込みおよび書き込みキャパシティーについて、最大 5 分 (300 秒) を保 持します。読み込みや書き込みのアクティビティの急激な増加が頻繁に発生しないときは、これらの 追加のキャパシティーユニットはすぐに消費されます (テーブルに対して定義した 1 秒あたりのプロ ビジョンドスループット性能よりも速く消費されます)。ただし、急激に増大するキャパシティーが常 に使用可能であることを前提としてアプリケーションを設計しないでください。DynamoDB は、急激 に増大するキャパシティーをバックグラウンドでのメンテナンスや他のタスクで使用します。このと き、事前の通知はありません。 Note 今後、急激に増大するキャパシティーに関する上記の仕様は、変更される可能性がありま す。 データアップロード時に書き込みアクティビティを 分散する 他のデータソースから DynamoDB にデータをロードする場合があります。一般に、DynamoDB は テーブルデータを複数のサーバーに分配します。データをテーブルにアップロードする場合は、配分 されたサーバーすべてに同時にデータをアップロードすると、パフォーマンスが向上します。たとえ ば、ユーザーメッセージを DynamoDB テーブルにアップロードするとします。UserID がパーティ ションキーで、MessageID がソートキーである複合プライマリキーを使用するテーブルを設計すると します。ソースからのデータをアップロードするときは、特定のユーザーのすべてのメッセージ項目 を読み込み、DynamoDB にアップロードしてしまいがちです。以下のテーブルのシーケンスを参照し てください。 UserId MessageID U1 1 U1 2 API Version 2012-08-10 573 Amazon DynamoDB 開発者ガイド 時系列データへのアクセスパターンを理解する UserId MessageID U1 ... U1 ... 最大 100 U2 1 U2 2 U2 ... U2 ... 最大 200 この場合の問題は、DynamoDB への書き込みリクエストをパーティションキー値全体に分散して いないことです。一度に 1 つのパーティションキー値を使用し、そのすべての項目をアップロー ドしてから、次のパーティションキー値に移動し、同じ処理を実行します。バックグラウンドで は、DynamoDB によって複数のサーバーのテーブルにデータが分配されています。テーブル用にプロ ビジョニングされたすべてのスループット容量を十分に活用するには、パーティションキー値全体に ワークロードを分散する必要があります。この場合、不均一のアップロード作業量が、同じパーティ ションキー値を持つ項目に向けられています。このため、DynamoDB によってテーブル用にプロビ ジョニングされたリソースすべてを十分に活用できない可能性があります。アップロード作業は、最 初に各パーティションキーの値から 1 つの項目をアップロードすることで分散できます。次に、以下 のテーブルのアップロードシーケンスの例に示すすべてのデータをアップロードするまで、すべての 項目について、次のセットのソートキー値に対応するパターンを繰り返します。 UserId MessageID U1 1 U2 1 U3 1 ... .... U1 2 U2 2 U3 2 ... ... このシーケンスのすべてのアップロードでは、異なるパーティションキー値が使用され、より多くの DynamoDB サーバーが同時にビジー状態になり、スループットパフォーマンスが向上します。 時系列データへのアクセスパターンを理解する 作成する各テーブルに対して、スループット要件を指定します。DynamoDB はリソースの割り当てを 行い、持続性のある低レイテンシーを実現することで、スループット要件に対応します。 アプリケー ションおよびテーブルの設計時には、テーブルのリソースを最も効率よく活用するためにアプリケー ションのアクセスパターンを考慮する必要があります。 拠点での顧客の行動(URL のクリックなど)を追跡するテーブルを設計するとします。Customer ID をパーティションキー、日付/時刻をソートキーとして構成される複合プライマリキーを持つテーブ ルを設計するとします。このアプリケーションでは、顧客データが時間とともに無制限に大きくなり ます。ただし、アプリケーションは、テーブル内のすべての項目にわたって不均一のアクセスパター API Version 2012-08-10 574 Amazon DynamoDB 開発者ガイド 人気の高い項目をキャッシュに格納する ンを示す可能性があります。この場合、最新の顧客データのほうが適切であり、アプリケーションは 最新の項目に頻繁にアクセスできます。時間の経過とともに、これらの項目へのアクセスは減少し、 結果的に古い項目はほとんどアクセスされなくなります。これが既知のアクセスパターンである場合 は、テーブルスキーマの設計時に考慮することができます。すべての項目を単一のテーブルに格納す る代わりに、複数のテーブルに格納できます。たとえば、月単位のデータまたは週単位のデータを格 納するテーブルを作成できます。最新の月または週のデータを格納するテーブルの場合、データアク セス率は高く、より高いスループットが要求されます。これに対し、古いデータを格納するテーブル については、スループットの調整が可能であり、リソースを節約できます。 "ホット" な項目を高いスループットが設定された 1 つのテーブルに格納し、"コールド" な項目を低 いスループットが設定された他のテーブルに格納することによって、リソースを節約できます。古い 項目を削除するには、単純にテーブルを削除します。これらのテーブルは、Amazon Simple Storage Service(Amazon S3)など、他のストレージオプションに任意にバックアップできます。テーブル 全体を削除するほうが、項目を 1 つずつ削除するよりもはるかに効率的です。これにより、削除オペ レーションを置換オペレーションと同じくらいの回数実行するときに、書き込みスループットは基本 的に 2 倍になります。 人気の高い項目をキャッシュに格納する テーブル内の一部の項目が他の項目よりも人気が高い場合があります。たとえば、「テーブルの作成 とサンプルデータのロード (p. 166)」で説明している ProductCatalog テーブルの場合を考えます。こ のテーブルに数百万点のさまざまな商品が格納されているとします。一部の商品が顧客の間で非常に 人気が高い場合があり、したがってそれらの項目は他の項目よりも一貫してアクセス数が多くなりま す。その結果、ProductCatalog に対する読み込みアクティビティの分布は、これらの人気の高い項目 に大きく偏ったものになります。 1 つの解決策は、アプリケーション層でこれらの読み込みをキャッシュに格納することです。キャッ シュはスループットの高い多くのアプリケーションに使用されている手法であり、アクセス数の多い 項目に対する読み込みアクティビティをデータベースではなくキャッシュにオフロードします。アプ リケーションはメモリ内の最も人気の高い項目をキャッシュに格納できます。または、同様の処理に ElastiCache のような製品を使用できます。 引き続き ProductCatalog の例で、顧客がそのテーブルに項目をリクエストすると、アプリケーショ ンはまずキャッシュに問い合わせて、キャッシュにその項目のコピーが存在するかどうかを確認しま す。存在する場合は、キャッシュヒットです。それ以外の場合は、キャッシュミスです。キャッシュ ミスがあると、アプリケーションは DynamoDB から項目を読み込み、その項目のコピーをキャッ シュに格納する必要があります。時間の経過と共に、キャッシュが人気の高い項目で満たされるた め、キャッシュミスは減ります。つまり、アプリケーションはこれらの項目に探して DynamoDB に アクセスする必要はなくなります。 キャッシュによる解決策により、読み込みアクティビティの分布で人気の高い項目への偏りを小さ くできます。さらに、テーブルに対する読み込みアクティビティの量が減るため、キャッシュは DynamoDB 使用の全体的なコストを削減するために役立ちます。 プロビジョニングされたスループットを調整すると きにワークロードの均一性を考慮する テーブルのデータ量が増加したり、追加の読み込みおよび書き込みキャパシティーをプロビジョニン グしたりするときに、DynamoDB によって、データが複数のパーティション全体に自動的に分散さ れます。アプリケーションでそれほど多くのスループットを必要としない場合、UpdateTable オペ レーションを使用してスループットを減らし、プロビジョニングしたスループットに対してのみお支 払いいただくことができます。 均一なワークロードで使用するように設計されたアプリケーションでは、DynamoDB のパーティショ ン割り当てアクティビティによる目立った効果を確認することはできません。通常、ワークロードの 一時的な不均一性は、「急激に増大するキャパシティーは控えめに使用する (p. 573)」で説明され ているように、急激に増大するキャパシティーに対応した機能によって緩和されます。ただし、アプ リケーションで不均一なワークロードに定期的に対応する必要がある場合、DynamoDB でのパーティ API Version 2012-08-10 575 Amazon DynamoDB 開発者ガイド 大規模環境でのアプリケーションのテスト ション分割の動作(「パーティションの動作について (p. 569)」を参照)を考慮して、テーブルを設 計してください。また、そのテーブルに対してプロビジョニングされるスループットを増減させるタ イミングにも留意してください。 テーブルのプロビジョニングされたスループットの量を減らしても、DynamoDB はパーティション の数を減らしません。アプリケーションで実際に必要となるよりも多くのプロビジョニングされたス ループットを使用して、テーブルを作成し、その後で、プロビジョニングされたスループットの量を 減らしたとします。このシナリオでは、パーティションごとのプロビジョニングされたスループット の量は、初めから少ない量のスループットを使用してテーブルを作成した場合のパーティションごと のスループットの量と比べると、少なくなります。 たとえば、2,000 万個の項目を DynamoDB テーブルにバルクロードする必要がある状況を考えてみ ましょう。各項目のサイズを 1 KB と仮定した場合、このバルクロードにおけるデータのサイズは 20 GB になります。このバルクロードタスクでは、合計 2,000 万個の書き込みキャパシティーユニット が必要になります。このデータロードを 30 分以内に実行するには、テーブルのプロビジョニングさ れた書き込みスループットを 11,000 個の書き込みキャパシティーユニットに設定する必要がありま す。 パーティションの最大書き込みスループットは、1,000 個の書き込みキャパシティーユニットになり ます(「パーティションの動作について (p. 569)」を参照)。このため、DynamoDB では 11 個の パーティションが作成され、各パーティションには 1,000 個のプロビジョニングされた書き込みキャ パシティーユニットが割り当てられます。 データをバルクロードした後、安定した状態の書き込みスループットの要件では、書き込みキャパシ ティーユニットの量はかなり少なくなります。たとえば、アプリケーションで 1 秒あたり 200 回の書 き込みが必要になるとします。テーブルのプロビジョニングされたスループットをこのレベルに減ら す場合、11 個のパーティションそれぞれについて、1 秒あたり約 20 個のキャパティーユニットがプ ロビジョニングされます。パーティションごとのプロビジョニングされたスループットがこのレベル に減少しても、DynamoDB の急激に増大するキャパシティーに対応した動作と組み合わされて、アプ リケーションに十分に対応したスループットとなります。 ただし、アプリケーションで、パーティションごとに 1 秒あたり 20 回の書き込みを超える持続的な 書き込みスループットが必要になる場合、次のいずれかを行う必要があります。(a) パーティション キー値ごとの 1 秒あたりの書き込み数がより少なくても対応できるスキーマを設計します。(b) より 遅いペースで実行され、初期スループット要件が少なくなるようにデータのバルクロードを設計しま す。たとえば、30 分ちょうどではなく3 時間を超える一括インポートの実行が許可されていたとしま す。このシナリオでは、11,000 個ではなく、1 秒あたり 1,900 個の書き込みキャパシティーユニット のみをプロビジョニングする必要があります。その結果、DynamoDB ではテーブルに対して 2 つの パーティションのみが作成されます。 大規模環境でのアプリケーションのテスト 多くのテーブルでは、最初に格納されているデータ量は少量です。その後、アプリケーションでの書 き込みアクティビティの実行に伴って、データ量は多くなっていきます。このデータ量の増加は段階 的に発生する場合があり、テーブルに対して定義したプロビジョニングされたスループット設定を超 えることはありません。テーブルが大きくなると、DynamoDB では、より多くのパーティションに データを分散することで、テーブルを自動的に拡張します。こうした処理が実行されると、作成され る各パーティションに割り当てられるプロビジョニングされたスループットは、元のパーティション に割り当てられるスループットよりも少なくなります。 アプリケーションでは、すべてのパーティションキー値に分散されているテーブルのデータにアクセ スするが、不均一な方法でアクセスするとします (少数のパーティションキー値にのみ頻繁にアクセ スする)。テーブルに十分な量のデータがなくても、アプリケーションは適切に動作する場合がありま す。ただし、テーブルが大きくなると、パーティションが増加し、パーティションごとのスループッ トは減少します。過去に動作したものと同じ不均一なアクセスパターンがアプリケーションで使用さ れると、アプリケーションが制限されることに気付くことがあります。 テーブルが大きくなった場合の "ホット" なキーに関連する問題を回避するには、大規模環境でアプリ ケーション設計をテストしてください。大規模環境で実行する場合のスループットに対するストレー API Version 2012-08-10 576 Amazon DynamoDB 開発者ガイド 項目の操作のガイドライン ジの比率、および DynamoDB でパーティションをテーブルに割り当てる方法を検討します。(詳し くは、パーティションの動作について (p. 569) を参照してください)。 大量のテストデータを生成できない場合は、非常に高いスループット設定にプロビジョニングされた テーブルを作成できます。これにより、多くのパーティションを持つテーブルが作成されます。そ の後で、UpdateTable を使用して設定値を減らすことができます。ただし、大規模環境でアプリケー ションを実行する場合に決定した、スループットに対するストレージの比率は維持してください。こ れで、テーブルの拡張後に必要となるパーティションごとのスループットの割合を備えたテーブルが 作成されます。実際のワークロードを使用し、このテーブルに対してアプリケーションをテストして ください。 時系列データが格納されるテーブルは、際限なく大きくなる可能性があります。このようなテーブル が原因となって、アプリケーションのパフォーマンスが時間の経過に伴って低下する場合がありま す。時系列データを使用する場合、通常、アプリケーションはテーブルに格納されている以前の項 目よりも最新の項目を頻繁に読み書きします。リアルタイムテーブルから以前の時系列データを削除 し、そのデータを他の場所にアーカイブできる場合は、パーティションごとのスループットの割合を 高い値に維持できます。 時系列データを使用したベストプラクティスについては、「時系列データへのアクセスパターンを理 解する (p. 574)」を参照してください。 項目の操作のガイドライン トピック • 大規模な設定属性の代わりに 1 対多のテーブルを使用する (p. 577) • 複数テーブルの使用による多様なアクセスパターンのサポート (p. 578) • 大量の属性値を圧縮する (p. 579) • Amazon S3 に大量の属性値を格納する (p. 580) • 大量の属性を複数の項目に分割する (p. 580) DynamoDB 内の項目を操作するときは、最高のパフォーマンスを得る方法、プロビジョニングされた スループットのコストを削減する方法、読み込みと書き込みのキャパシティーユニット内にとどまる ことによる調整を回避する方法を検討する必要があります。処理中の項目が最大の項目サイズを超え るようであれば(「DynamoDB での制限 (p. 558)」参照)、この状況にどのように対処するかを検討 する必要があります。このセクションでは、このような問題に対処する最善の方法を示します。 大規模な設定属性の代わりに 1 対多のテーブルを使 用する テーブルに大規模な設定タイプ属性(数字セットや文字列セットなど)を格納する項目がある場合 は、属性を削除し、テーブルを 2 つに分割することを検討してください。これらのテーブル間に 1 対 多の関係を形成するには、プライマリキーを使用します。 「テーブルの作成とサンプルデータのロード (p. 166)」セクションに記載の Forum、Thread、Reply の各テーブルは、この 1 対多の関係を示す良い例です。たとえば、Thread テーブルには、各フォーラ ムのスレッドに対応する項目が 1 つあり、Reply テーブルには、各スレッドに対応する 1 つまたは複 数の応答が格納されています。 別々のテーブルに項目として応答を格納する代わりに、スレッドと応答の両方を同じテーブルに格納 できます。各スレッドについて、文字列セットタイプの 1 つの属性にすべての応答を格納できます。 ただし、スレッドと応答データを別々のテーブルに保持することは、いくつかの点で有益です。 • 応答をテーブル内の項目として格納する場合、任意の数の応答を格納できます。DynamoDB のテー ブルには任意の数の項目を格納できるためです。 API Version 2012-08-10 577 Amazon DynamoDB 開発者ガイド 複数テーブルの使用による多様 なアクセスパターンのサポート 応答を Thread テーブル内の属性値として格納する場合は、最大項目サイズの制約を受けるため、 格納可能な応答数が制限されます(「DynamoDB での制限 (p. 558)」参照)。 • Thread 項目を取り出す場合、取り出す対象がスレッドデータとそのスレッドに対応する一部の応答 に限られるため、プロビジョニングされたスループットに対する支払額が少なくなります。 • クエリを使用すると、一部の項目のみをテーブルから取り出せます。応答を別々の Reply テーブル に格納することで、一部の応答のみを取り出せます。たとえば、Reply テーブルをクエリして、特 定の日付範囲内の応答を取り出せます。 応答を設定タイプの属性値として格納する場合、すべての応答を常に取り出す必要があります。こ の結果、必要でない可能性のあるデータに対して、プロビジョニングされたスループットの消費量 が多くなります。 • 新しい応答をスレッドに追加するときは、項目のみを Reply テーブルに追加します。この結果、そ の単一の Reply 項目に対してのみ、プロビジョニングされたスループットの費用が発生します。 応答を Thread テーブルに格納する場合は、単一のユーザー応答をスレッドに追加するたびに、お 客様が全 Thread 項目(すべての応答を含む)の書き込みにかかる総費用を負担することになりま す。 複数テーブルの使用による多様なアクセスパターン のサポート DynamoDB テーブル内のサイズの大きい項目に頻繁にアクセスしており、項目の大きめの属性を常に すべて使用するのでなければ、小さめで、より頻繁にアクセスする属性を別のテーブルの別の項目と して格納します。これにより、効率を改善し、ワークロードをさらに均一化することができます。 たとえば、ProductCatalog テーブル(「テーブルの作成とサンプルデータのロード (p. 166)」セク ション参照)を検討してください。このテーブルの項目には、製品の名前や説明など、製品の基本情 報が含まれています。この情報はめったに変更されませんが、アプリケーションによって製品が表示 されるたびに使用されます。 変化の激しい製品属性(価格や可用性など)の追跡情報をアプリケーションで保持する必要もある場 合は、この情報を ProductAvailability という別のテーブルに格納できます。この手法によって、更新 時のスループットにかかる費用が最小限に抑えられます。説明のため、ProductCatalog 項目のサイズ を 3 KB、この項目に対応する価格および可用性の属性を 300 バイトと仮定します。この場合、この ような変化の激しい属性を更新すると、費用は 3 になります。これは、他の製品属性を更新する場合 と同額の費用です。ここで、その代わりに、価格と可用性の情報が ProductAvailability テーブルに格 納されているとします。この場合、情報を更新すると、書き込みキャパシティーユニット 1 つにのみ かかる費用と同額になります。 Note キャパシティーユニットの説明については、「プロビジョニングされたスループッ ト (p. 16)」を参照してください。 表示頻度の低い製品データをアプリケーションで格納する必要もある場合は、この情報を ExtendedProductCatalog という別のテーブルに格納できます。このようなデータには、製品寸法、音 楽アルバムの曲名リスト、基本的な製品データほど頻繁にはアクセスされないその他の属性が含まれ る可能性があります。このようにして、アプリケーションは、基本的な製品情報を表示するときにの みスループットを消費します。また、追加のスループットについては、ユーザーが広範囲に及ぶ製品 詳細をリクエストする場合にのみ消費します。 前述のテーブルインスタンスの例を以下に示します。すべてのテーブルには、プライマリキーとして Id 属性があります。 ProductCatalog API Version 2012-08-10 578 Amazon DynamoDB 開発者ガイド 大量の属性値を圧縮する ID 役職 説明 21 "有名な書籍" "去年のベストセラーリストか ら..." 302 "赤い自転車" "赤いクラシック自転車..." 58 "音楽アルバム" "今週の人気ニューアルバム..." ID 価格 QuantityOnHand 21 "5.00 USD" 3750 302 "125.00 USD" 8 58 "5.00 USD" "無限(デジタル項目)" ID AverageCustomerRating TrackListing 21 5 302 3.5 58 4 {"Track1#3:59", "Track2#2:34", "Track3#5:21", ...} ProductAvailability ExtendedProductCatalog 1 つの項目の属性を別のテーブル内の複数の項目に分割する場合には、以下のように、メリットと問 題点がいくつかあります。 • これらの属性の読み込みまたは書き込みにかかるスループット費用が削減されます。項目の単一 の属性を更新する場合にかかる費用は、項目の実際のサイズに基づいています。項目が少量の場合 は、各項目にアクセスするとスループットが低下します。 • 頻繁にアクセスする項目を少量に維持すれば、I/O ワークロードはより均一に分散されます。大量の 項目を取り出すと、テーブルの同一のパーティションから一度に大量の読み込みキャパシティーが 消費されます。この結果、ワークロードは不均一になり、調整が発生する可能性があります。詳細 については、「読み込みアクティビティの急激な増大の回避 (p. 581)」を参照してください。 • 単一項目の読み込みオペレーション(GetItem など)の場合、スループットの計算値は、次の 4 KB 境界に切り上げられます。項目のサイズが 4 KB よりも小さく、プライマリキーのみで項目を 取り出す場合、項目の属性を別項目として格納すると、スループットの低下を避けることができま す。それでも、Query や Scan などのオペレーションのスループット費用は、別々に計算されま す。返されたすべての項目のサイズが合計され、その総計は次の 4 KB 境界に切り上げられます。 これらのオペレーションの場合は、大量の属性を別項目に移動することによってスループット費用 を削減できます。詳細については、「キャパシティーユニットの計算 (p. 181)」を参照してくださ い。 大量の属性値を圧縮する 大量の属性値は、DynamoDB に格納する前に圧縮できます。圧縮することで、このようなデータを格 納および取り出す費用を削減できます。圧縮アルゴリズム(GZIP、LZO など)により、バイナリ出力 が生成されます。この結果、この出力をバイナリ属性タイプで格納できます。 API Version 2012-08-10 579 Amazon DynamoDB 開発者ガイド Amazon S3 に大量の属性値を格納する たとえば、「テーブルの作成とサンプルデータのロード (p. 166)」セクションの Reply テーブルに、 フォーラムユーザーの書いたメッセージが格納されます。これらのユーザー応答は、非常に長い文字 列で構成される場合があるため、圧縮の立派な候補になります。 DynamoDB での長いメッセージの圧縮方法を示すコード例については、次の場所を参照してくださ い。 • 例: AWS SDK for Java ドキュメント API を使用したバイナリタイプ属性の処理 (p. 247) • 例: AWS SDK for .NET の低レベル API を使用した、バイナリタイプ属性の処理 (p. 271) Amazon S3 に大量の属性値を格納する DynamoDB は、現在、テーブルに格納する項目のサイズを制限しています。詳細については、 「DynamoDB での制限 (p. 558)」を参照してください。ただし、アプリケーションは、DynamoDB の サイズ制限で許可されているよりも多くのデータを 1 つの項目に格納しなければならない場合もあり ます。この問題を回避するために、大量の属性を Amazon Simple Storage Service(Amazon S3)の オブジェクトとして格納し、項目にオブジェクト ID を格納できます。Amazon S3 のオブジェクトメ タデータのサポートを利用して、対応する項目のプライマリキー値を Amazon S3 オブジェクトのメ タデータとして格納できます。メタデータの使用は、Amazon S3 オブジェクトを将来的にメンテナン スする際に役立ちます。 たとえば、ProductCatalog テーブル(「テーブルの作成とサンプルデータのロード (p. 166)」セク ション参照)を検討してください。ProductCatalog テーブル内の項目は、項目の価格、説明、書籍の 著者、その他の製品の寸法に関する情報を格納します。各製品の画像を格納する場合は、対象の画像 を拡大できます。画像は DynamoDB ではなく Amazon S3 に格納するのが賢明です。 この手法には重要な考慮事項があります。 • DynamoDB は Amazon S3 と DynamoDB 間のトランザクションをサポートしていません。このた め、失敗が発生する状況や、親のない Amazon S3 オブジェクトの削除に、アプリケーションで対 処する必要があります。 • Amazon S3 では、オブジェクト ID の長さを制限しています。このため、データをまとめる際 には、この制限および Amazon S3 の他の制約を考慮する必要があります。詳細については、 「Amazon Simple Storage Service 開発者ガイド」を参照してください。 大量の属性を複数の項目に分割する DynamoDB での許容量を超えるデータを単一の項目に格納する必要がある場合は、そのデータをより 大きな「仮想項目」のチャンクとして、複数の項目に格納できます。最良の結果を得るには、シンプ ルなプライマリキー (パーティションキー) がある別のテーブルにチャンクを保存し、バッチオペレー ション (BatchGetItem および BatchWriteItem) を使用してチャンクの読み取りと書き込みを行い ます。この手法は、ワークロードをテーブルパーティションの全体に均一に分散するときに役立ちま す。 たとえば、「テーブルの作成とサンプルデータのロード (p. 166)」セクションで説明した Forum、Thread、Reply の各テーブルを検討します。Reply テーブル内の項目には、フォーラムユー ザーの書いたフォーラムメッセージが格納されています。DynamoDB では 400 KB の項目サイズ制限 があるため、各応答の長さも制限されます。大量の応答の場合は、1 つの項目を Reply テーブルに保 存するのではなく、応答メッセージを複数のチャンクに分割します。続いて各チャンクを、シンプル なプライマリキー (パーティションキー) がある新しい ReplyChunks テーブルに、各チャンク専用の 独立した項目として書き込みます。 各チャンクのプライマリキーは、「親」応答項目、バージョン番号、およびシーケンス番号のプライ マリキーを連結したものになります。シーケンス番号によってチャンクの順序が決定します。バー ジョン番号によって、大量の応答が後で更新される場合に、確実にアトミックに更新されます。さら に、更新前に作成されたチャンクは、更新後に作成されたチャンクと混合されることはありません。 API Version 2012-08-10 580 Amazon DynamoDB 開発者ガイド クエリおよびスキャンのガイドライン また、「親」応答項目をチャンクの数で更新する必要もあります。このため、応答のすべてのチャン クを取り出す必要がある場合に、検索するチャンクの数がわかります。 以下に、これらの項目が Reply テーブルおよび ReplyChunks テーブルにどのように現れるかを示しま す。 Reply ID ReplyDateTime メッセージ ChunkCount ChunkVersion "DynamoDB#Thread1" "2012-03-15T20:42:54.023Z" 3 1 "DynamoDB#Thread2" "2012-03-21T20:41:23.192Z" "短いメッセージ" ReplyChunks ID メッセージ "DynamoDB#Thread1#2012-03-15T20:42:54.023Z#1#1" "長いメッセージテキストの最初の部分..." "DynamoDB#Thread1#2012-03-15T20:42:54.023Z#1#3" "長いメッセージテキストの 3 番目の部分..." "DynamoDB#Thread1#2012-03-15T20:42:54.023Z#1#2" "長いメッセージテキストの 2 番目の部分..." この手法には重要な考慮事項があります。 • DynamoDB は項目間のトランザクションをサポートしていないため、複数項目の書き込みが失敗す る状況や、複数項目の読み込み時に発生する項目間の不一致に、アプリケーションで対処する必要 があります。 • アプリケーションが一度に大量のデータを取り出すと、不均一のワークロードが生成され、その結 果、予想外の調整が発生する可能性があります。このことは、特にパーティションキーの値を共有 する項目を取り出す場合に当てはまります。 シンプルなプライマリキー (パーティションキー) がある別々のテーブルを使用して大量のデータ項目 をチャンクに分割することで、この問題が回避されます。このため、大量の各チャンクがテーブル全 体に分散されます。 有力なソリューション (最善ではありませんが) は、複合キーのあるテーブルや、「親」項目のプライ マリキーとなっているパーティションキーのあるテーブルに各チャンクを保存することです。この設 計上の選択により、同じ「親」項目のチャンクすべてを取り出すアプリケーションによって不均一な ワークロードが生成され、パーティション全体での I/O の量が不均一になります。 クエリおよびスキャンのガイドライン このセクションでは、クエリおよびスキャンオペレーションのベストプラクティスを示します。 読み込みアクティビティの急激な増大の回避 テーブルを作成する場合には、読み込みおよび書き込みキャパシティーユニット要件を設定します。 読み込みの場合、キャパシティーユニットは、強力な整合性のある 1 秒あたり 4 KB のデータ読み込 みリクエスト数として表されます。結果整合性のある読み込みの場合、読み込みキャパシティーユ ニットは、1 秒あたり 2 回の 4 KB の読み込みリクエストになります。Scan オペレーションでは結果 整合性のある読み込みがデフォルトで実行され、最大 1 MB(1 ページ)のデータが返されます。した がって、1 回の Scan リクエストでは、(1 MB のページサイズ/ 4 KB の項目サイズ)/ 2(結果整合性 API Version 2012-08-10 581 Amazon DynamoDB 開発者ガイド 読み込みアクティビティの急激な増大の回避 のある読み込み)= 128 の読み込みオペレーションが実行されます。もし、代わりに強い整合性のあ る読み込みをリクエストすると、Scan オペレーションはプロビジョニングされたスループットを 2 倍消費します(256 の読み込みオペレーション)。 これはテーブルに設定済みの読み込みキャパシティーに比べて、使用量が急激に増大することを意味 します。このようにスキャンが使用するキャパシティーユニットが増大すると、同じテーブルに対す るその他の重要なリクエストがキャパシティーユニットを使用する妨げになります。その結果、それ らのリクエストについて ProvisionedThroughputExceeded 例外が発生する可能性があります。 問題なのは、Scan が使用するキャパシティーユニットの急激な増大だけではありません。スキャンで はパーティション内で隣接する読み込み項目がリクエストされるため、スキャンによって、同じパー ティションのキャパシティーユニットがすべて消費される可能性があります。つまり同じパーティ ションがリクエストの対象になるため、キャパシティーユニットがすべて消費され、そのパーティ ションに対する他のリクエストが制限されることになります。データ読み込みのリクエストを複数の パーティションに分散させれば、オペレーションによって特定のパーティションが制限されることは ありません。 次の図は、Query および Scan オペレーションによるキャパシティーユニットの使用量の急激な増大 の影響と、同じテーブルに対する他のリクエストに及ぼす影響を示しています。 大がかりな Scan オペレーションの代わりに次の手法を使用すれば、テーブルのプロビジョニングさ れたスループットに対するスキャンの影響を最小限に抑えることができます。 API Version 2012-08-10 582 Amazon DynamoDB 開発者ガイド 並列スキャンの利用 • ページサイズを小さくする スキャンオペレーションではページ全体(デフォルトでは 1 MB)を読み込むため、設定するペー ジサイズを小さくすることで、スキャンの影響を軽減させることができます。Scan オペレーショ ンには、リクエストのページサイズの設定に使用できる Limit パラメータがあります。Scan または Query リクエストのページサイズが小さい場合は、読み込みオペレーションの数が少なくなり、各 リクエストの間に間隔ができます。たとえば、各項目が 4 KB で、ページサイズを 40 項目に設定し た場合に Query リクエストで使用されるのは、40 回の強力な整合性のある読み込みオペレーショ ン、または 20 回の結果整合性のある読み込みオペレーションです。Scan または Query オペレー ションのサイズが小さくなって回数が増えれば、他の重要なリクエストが制限されることなく実行 されるようになります。 • スキャンオペレーションを分離する DynamoDB は容易に拡張できるように設計されています。そのため、アプリケーションでは明確な 目的でテーブルを作成できます。コンテンツを複数のテーブルに複製することも可能です。「ミッ ションクリティカル」なトラフィックを扱わないテーブルに対するスキャンを実行するとします。 アプリケーションによっては、(重要なトラフィック用と記録用の)2 つのテーブル間で 1 時間ご とにトラフィックを分担することで、この負荷が処理されます。また別のアプリケーションでは、 すべての書き込みを 2 つのテーブル(「ミッションクリティカル」なテーブルと「シャドウ」テー ブル)に対して行うことで処理されます。 アプリケーションのリクエストに対しプロビジョニングされたスループットを超えたことを示す応答 コードが返された場合にはそのリクエストを再試行するか、UpdateTable オペレーションを使用し てテーブルにプロビジョニングされたスループットを増やすようにアプリケーションを設定します。 ワークロードが一時的に急増して、プロビジョニングされたレベルをスループットが超えることがあ る場合には、エクスポネンシャルパックオフによってリクエストを再試行します。エクスポネンシャ ルパックオフの実装の詳細については、「エラーの再試行とエクスポネンシャルバックオフ (p. 76)」 を参照してください。 並列スキャンの利用 多くのアプリケーションでは、シーケンシャルスキャンよりも並列 Scan オペレーションのほうが有 効です。たとえば、サイズの大きい履歴データテーブルを処理するアプリケーションでは、シーケン シャルスキャンよりも並列スキャンのほうが大幅に速く実行できます。バックグラウンドの "スイー パー" プロセスで複数のワーカースレッドを使用することで、プロダクショントラフィックに影響す ることなく、低いプライオリティでテーブルをスキャンできます。これらの例では、他のアプリケー ションが使用するプロビジョニングされたスループットリソースが枯渇しないように、並列 Scan が 使用されています。 並列スキャンは有益ですが、プロビジョニングされたスループットが多量に消費される可能性があり ます。並列スキャンでは、複数のワーカーがアプリケーションを使用して Scan オペレーションを同 時に実行するため、テーブルにプロビジョニングされた読み込みキャパシティーが急速に消費されま す。その場合は、テーブルにアクセスする必要がある他のアプリケーションが制限される可能性があ ります。 並列スキャンが適しているのは、次の条件に当てはまる場合です。 • テーブルのサイズが 20 GB 以上である。 • テーブルにプロビジョニングされている読み込みスループットが完全に使用されていない。 • シーケンシャル Scan オペレーションでは遅すぎる。 TotalSegments の選択 TotalSegments の最適な設定は、使用するデータ、テーブルにプロビジョニングされるスループッ ト設定、パフォーマンス要件によって異なります。最適な設定は実験を通じて明らかになる場合もあ ります。2 GB のデータにつき 1 セグメントなど、単純な比率から始めることをお勧めします。たと えば 30 GB のテーブルでは、TotalSegments を 15(30 GB / 2 GB)に設定できます。アプリケー API Version 2012-08-10 583 Amazon DynamoDB 開発者ガイド ローカルセカンダリインデックス のガイドライン ションでは 15 のワーカーを使用して、各ワーカーが異なるセグメントをスキャンするようにしま す。 TotalSegments の値は、クライアントのリソースに基づいて選択することもできま す。TotalSegments を 1~1000000 の範囲の任意の数値に設定すると、DynamoDB ではその数のセ グメントをスキャンできます。たとえば、クライアントで同時に実行できるスレッド数が制限されて いる場合には、アプリケーションで Scan のパフォーマンスが最高になるまで、TotalSegments を 徐々に増やすことができます。 プロビジョニングされたスループットの使用率を最適にするには、並列スキャンをモニタリングする とともに、他のアプリケーションが使用するリソースが枯渇しないようにする必要があります。プ ロビジョニングされたスループットをすべて消費しないうちに Scan リクエストが制限される場合に は、TotalSegments の値を増やします。Scan リクエストによって、プロビジョニングされたスルー プットが必要以上に消費される場合には、TotalSegments の値を減らします。 ローカルセカンダリインデックス のガイドライン トピック • インデックスの使用は控えめにする (p. 584) • 射影を慎重に選択する (p. 584) • フェッチを回避するための頻繁なクエリの最適化 (p. 585) • スパースなインデックスの利用 (p. 585) • 項目コレクションの拡張の監視 (p. 586) このセクションでは、local secondary index についていくつかのベストプラクティスを示します。 インデックスの使用は控えめにする 頻繁にクエリを行わない属性では、local secondary index を作成しないようにします。頻繁に更新さ れず、多数の異なる基準を使用してクエリが行われるテーブルは、複数のインデックスを作成して維 持するのに適しています。ただし使用されていないインデックスは、ストレージおよび I/O のコスト 増大の一因になり、アプリケーションのパフォーマンスには効果がありません。 データキャプチャアプリケーションで使用するテーブルのように、多量の書き込みアクティビティが 発生するテーブルには、インデックスを設定しないようにしてください。インデックスを維持するた めに必要な I/O オペレーションのコストが多大になる可能性があります。そのようなテーブルでデー タにインデックスを設定する必要がある場合は、データを別のテーブルにコピーして必要なインデッ クスを設定し、そこでクエリを行います。 射影を慎重に選択する local secondary index はストレージとプロビジョニング済みのスループットを消費するため、イン デックスのサイズは可能な限り小さくすべきです。またインデックスが小さいほど、テーブル全体に 対してクエリを行うのに比べてパフォーマンスが向上します。使用するクエリが属性の一部しか返さ ないことが多く、それらの属性のサイズを合計しても項目全体より大幅に小さい場合には、頻繁にリ クエストを行う属性だけを射影するようにします。 テーブルでの書き込みアクティビティが読み込みに比べて多くなることが予想される場合には、次の ようにします。 • 射影される属性が少なくなるようにします。インデックスに書き込まれる項目のサイズが最小にな ります。ただしこれらの項目が 1 つの書き込みキャパシティーユニット(1 KB)よりも小さい場合 は、書き込みキャパシティーユニットに関する節約効果はありません。たとえば、インデックスエ API Version 2012-08-10 584 Amazon DynamoDB 開発者ガイド フェッチを回避するための頻繁なクエリの最適化 ントリのサイズが 200 バイトである場合、DynamoDB ではこれが 1 KB に切り上げられます。 言い 換えれば、インデックス項目のサイズが小さい間は、追加コストが発生することなく、より多くの 属性を射影することができます。 • そのテーブルの属性の一部に、クエリでほとんど使用されない属性があることがわかっている場合 は、それらの属性を射影する理由はありません。その後インデックス内にない属性を更新しても、 インデックス更新による追加コストは発生しません。クエリでは射影されない属性を取り出すこと はできますが、プロビジョニングされるスループットのコストは増加します。 ALL は、クエリによってテーブル項目全体が返されるとともに、異なるソートキーによってテーブル を並べ替えるようにする場合のみ指定します。すべての属性にインデックスを付けることでテーブル フェッチの必要がなくなりますが、ほとんどの場合、ストレージおよび書き込みアクティビティに要 するコストが倍加します。 フェッチを回避するための頻繁なクエリの最適化 レイテンシーを可能な限り小さくしてクエリを最速にするには、クエリによって返されるようにする すべての属性を射影します。インデックスのクエリを行った場合に、リクエストした属性が射影され ていないと、DynamoDB はリクエストされた属性をテーブルからフェッチします。その場合、テーブ ルから項目全体を読み込む必要があるため、レイテンシーが発生し、I/O オペレーションが増加しま す。 特定のクエリを臨時的に実行するだけで、リクエストされたすべての属性を射影する必要がない場 合、そのような「臨時的な」クエリが「不可欠な」クエリに変わることがよくあるので注意が必要で す。それらの属性の射影を行うべきだったと後で気づく可能性もあります。 テーブルのフェッチの詳細については、「プロビジョニングされたスループットに関する考慮事項 (ローカルセカンダリインデックス) (p. 389)」を参照してください。 スパースなインデックスの利用 テーブル内の項目について、DynamoDB は項目内にインデックスソートキーの値がある場合のみ、対 応するインデックスエントリを書き込みます。ソートキーが必ずしもすべてのテーブル項目に現れな い場合、そのインデックスはスパースであるといえます。 スパースなインデックスは、ほとんどのテーブル項目に現れない属性のクエリに役立ちます。たとえ ば、すべての注文を格納する CustomerOrders というテーブルがあるとします。このテーブルのキー 属性は次のようになります。 • パーティションキー: CustomerId • ソートキー: OrderId オープンな注文だけを追跡する場合は、IsOpen という属性を指定できます。注文の受信を待機して いる場合、アプリケーションでは、テーブル内の特定の項目について「X」(またはその他の任意の 値)と書き込むことで、IsOpen を定義できます。注文を受信すると、アプリケーションでは IsOpen 属性を削除して、注文が履行されたことを示します。 オープンな注文を追跡するために、CustomerId (パーティションキー) および IsOpen (ソートキー) に インデックスを作成できます。インデックスに現れるのは、IsOpen が定義されたテーブルの注文だ けです。アプリケーションでは、インデックスのクエリを実行することで、オープンになっている 注文をすばやく効率的に検索することができます。膨大な注文があって、そのうちオープンになっ ているのが少数だけである場合、アプリケーションでインデックスに対するクエリを実行し、オー プンになっている各注文の OrderId を返すことができます。アプリケーションが実行する読み込み は、CustomerOrders テーブル全体をスキャンする場合に比べて大幅に少なくなります。 IsOpen 属性に任意の値を書き込む代わりに、別の属性を使用して、インデックス内に使いやすい並 べ替え順序を持つことも可能です。その場合は、OrderOpenDate 属性を作成して注文が行われた日 API Version 2012-08-10 585 Amazon DynamoDB 開発者ガイド 項目コレクションの拡張の監視 付に設定し (注文が処理された時点で属性を削除)、スキーマの CustomerId (パーティションキー) と OrderOpenDate (ソートキー) と合わせて OpenOrders インデックスを作成します。それによって、 インデックスのクエリを行ったときに、より使いやすい並べ替え順序で項目が返されるようになりま す。 項目コレクションの拡張の監視 項目コレクションとは、テーブルとそのインデックス内で、同じパーティションキーを持つすべての 項目を意味します。項目コレクションは 10 GB を超えることができないため、パーティションキー値 によってはスペースが不足する可能性があります。 テーブル項目を追加または更新すると、DynamoDB は影響を受ける local secondary index を更新しま す。テーブル内でインデックスが付けられた属性が定義されている場合は、テーブルの拡張とともに インデックスも増加します。 インデックスを作成する場合は、インデックスに書き込まれるデータの量と、そのうちパーティショ ンキー値が同じデータがどの程度になるかを考慮します。特定のパーティションキー値に対するテー ブルおよびインデックス項目の合計が 10 GB を超えると予想される場合は、そのインデックスの作成 を回避できないかどうかを検討すべきです。 インデックスの作成を回避できない場合は、項目コレクションのサイズ制限を超える前に対処する必 要があります。制限の範囲内での作業と是正措置のための戦略については、「項目コレクションのサ イズ制限 (p. 393)」を参照してください。 グローバルセカンダリインデックス のガイドライ ン トピック • ワークロードが均一になるようにキーを選択する (p. 586) • スパースなインデックスの利用 (p. 587) • グローバルセカンダリインデックス を使用したすばやい検索 (p. 587) • 結果整合性のある読み込みレプリカを作成する (p. 587) このセクションでは、グローバルセカンダリインデックス についていくつかのベストプラクティスを 示します。 ワークロードが均一になるようにキーを選択する DynamoDB テーブルを作成するとき、読み込みアクティビティと書き込みアクティビティをテーブル 全体に均一に分散することが重要です。これを行うには、データが複数のパーティションに均一に分 かれるように、プライマリキーの属性を選択します。 このガイダンスは グローバルセカンダリインデックス にも当てはまります。インデックスの項目数 に比べて、値の数が多いパーティションキーとソートキーを選択します。また、グローバルセカンダ リインデックス は一意であることを強制しないので、キー属性の濃度について理解する必要がありま す。濃度とは、項目の数を基準とした、特定の属性にある値の個別の数のことです。 たとえば、Employee というテーブルに、Name、Title、Address、PhoneNumber、Salary、PayLevel などの属性があるとします。PayLevel をパーティションキーに指定した、PayLevelIndex という名前 のグローバルセカンダリインデックスがあるとします。多くの企業では、給与コードの数は非常に少 なく、通常、従業員数が百人単位または千人単位の企業でも、10 個未満です。このようなインデック スがアプリケーションにもたらすメリットは、あまりありません。 API Version 2012-08-10 586 Amazon DynamoDB 開発者ガイド スパースなインデックスの利用 PayLevelIndex には、個別の値の分散が均一でないという別の問題もあります。たとえば、最高経営 幹部は数人で、時給労働者が非常に多い場合があります。PayLevelIndex に対してクエリを実行する と、読み込みアクティビティがパーティション全体に均一に分散されないので、あまり効率的ではあ りません。 スパースなインデックスの利用 テーブル内の項目について、DynamoDB は項目内にインデックスキー値がある場合のみ、対応するエ ントリを グローバルセカンダリインデックス に書き込みます。グローバルセカンダリインデックス の場合、これは、インデックスパーティションキーとそのソートキー (存在する場合) です。インデッ クスキー値が一部のテーブル項目に存在しない場合、そのインデックスは、スパースであるといえま す。 スパースな グローバルセカンダリインデックス を使用すると、一般的でない属性を持つテーブル 項目を効率的に見つけることができます。これを行うには、グローバルセカンダリインデックス 属 性が存在しないテーブル項目には、まったくインデックスが付けられないという点を利用します。 たとえば、GameScores テーブルで、あるプレーヤーは、ゲームで "チャンピオン (Champ)" などの 特別な成績を収め、ほとんどのプレーヤーは収めていない場合があります。チャンピオンについて GameScores テーブル全体をスキャンするのではなく、パーティションキーに Champ、ソートキーに UserId を指定したグローバルセカンダリインデックスを作成します。こうすることで、テーブルをス キャンするのではなくインデックスに対してクエリを実行し、すべてのチャンピオンを簡単に見つけ ることができます。 インデックス内の項目数は、テーブル内の項目数よりも大幅に少ないので、このようなクエリは非常 に効率的です。さらに、インデックスに射影するテーブル属性の数が少ないほど、インデックスから 消費する読み込みキャパシティーユニットも少なくなります。 グローバルセカンダリインデックス を使用したすば やい検索 任意のテーブル属性をインデックスパーティションキーとソートキーに使用してグローバルセカンダ リインデックスを作成できます。テーブルとまったく同じキー属性を持つインデックスを作成して、 非キー属性のサブセットだけを射影できます。 まったく同じキースキーマを持つ グローバルセカンダリインデックス のユースケースとして、最小限 のプロビジョニングされたスループットでテーブルデータをすばやく検索することが挙げられます。 テーブルに多数の属性があり、その属性自体が大きい場合、そのテーブルに対する各クエリによっ て、大量の読み込みキャパシティーが消費される可能性があります。ほとんどのクエリで、返される データのほとんどが必要ない場合は、最小限の射影された属性を使用して、つまり、テーブルのキー 以外は射影された属性をまったく含まない グローバルセカンダリインデックス を作成できます。これ により、非常に小さい グローバルセカンダリインデックス に対してクエリを実行できます。追加の属 性が本当に必要な場合に、同じキー値を使用してテーブルに対してクエリを実行できます。 結果整合性のある読み込みレプリカを作成する テーブルと同じキースキーマがある グローバルセカンダリインデックス を作成して、テーブルからイ ンデックスに一部(またはすべて)の非キー属性を射影できます。アプリケーションでは、一部(ま たすべて)の読み込みアクティビティをテーブルではなくこのインデックスに振り分けることができ ます。これにより、テーブルに対するプロビジョンド読み込みキャパシティーを、読み込みアクティ ビティの増加に応じて変更せずに済みます。テーブルに書き込んでからそのデータがインデックスに 反映されるまでの間に短い伝達遅延があることに注意してください。この場合、アプリケーションで は結果整合性を想定する必要があります。 アプリケーションの特性をサポートするために複数のグローバルセカンダリインデックスを作成でき ます。2 つアプリケーション間で読み込み特性が大きく異なるとします。たとえば、最高レベルの読 み込みパフォーマンスが必要な優先度の高いアプリケーションと、読み込みアクティビティの臨時 API Version 2012-08-10 587 Amazon DynamoDB 開発者ガイド 結果整合性のある読み込みレプリカを作成する の調整を許容できる優先度の低いアプリケーションの場合です。これらのアプリケーションの両方が 同じテーブルから読み込む場合は、互いに干渉する可能性があります。優先度の低いアプリケーショ ンからの高い読み込み負荷によって、テーブルの使用可能なすべての読み込みキャパシティーが消費 される可能性があります。その場合、結果的に優先度の高いアプリケーションの読み込みアクティビ ティが制限されることになります。2 つの グローバルセカンダリインデックス を作成する場合、つ まり、1 つは高い読み込みスループット設定にプロビジョニングし、もう 1 つは低い読み込みスルー プット設定にプロビジョニングする場合、これらのワークロードの格差は、各アプリケーションから の読み込みアクティビティをそれぞれのインデックスに振り分けることで効果的に縮小できます。こ の方法では、プロビジョンド読み込みスループットの量を、各アプリケーションの読み込み特性に合 わせて調整できます。 状況によっては、テーブルから読み込むことができるアプリケーションを制限することもできます。 たとえば、あるアプリケーションがウェブサイトからのクリックストリームアクティビティをキャ プチャし、DynamoDB テーブルに頻繁に書き込んでいるとします。このテーブルへの大部分のア プリケーションからの読み込みアクセスを禁止することで、このテーブルを分離する場合がありま す。(詳細については、「詳細に設定されたアクセスコントロールのための IAM ポリシー条件の使 用 (p. 477)」を参照してください)。ただし、他のアプリケーションでデータに対してアドホックク エリを実行する必要がある場合は、その目的で 1 つ以上の グローバルセカンダリインデックス を作 成できます。このようなインデックスを作成するときは、必ずアプリケーションで実際に必要にな る属性のみを射影するようにしてください。アプリケーションでは、読み込めるデータが増える一 方で、消費するプロビジョンド読み込みキャパシティーは減ります。テーブルからサイズの大きい項 目を読み込まずに済むためです。その結果、時間の経過と共に大幅なコスト削減になることがありま す。 API Version 2012-08-10 588 Amazon DynamoDB 開発者ガイド サンプルテーブルとデータ DynamoDB 付録 トピック • サンプルテーブルとデータ (p. 589) • サンプルテーブルの作成とデータのアップロード (p. 599) • AWS SDK for Python (Boto) を使用した DynamoDB サンプルアプリケーション: Tic-TacToe (p. 626) • DynamoDB 用の追加のツールとリソース (p. 644) • DynamoDB の予約語 (p. 668) • レガシー条件パラメータ (p. 678) • 現在の低レベル API バージョン (2012-08-10) (p. 696) • 前バージョンの低レベル API (2011-12-05) (p. 697) サンプルテーブルとデータ 『Amazon DynamoDB 開発者ガイド』では、サンプルテーブルを使用して DynamoDB のさまざまな 側面を示します。 テーブル名 プライマリキー ProductCatalog シンプルなプライマリキー: • Id (数値) フォーラム シンプルなプライマリキー: • Name (文字列) スレッド 複合プライマリキー: • ForumName (文字列) • Subject (文字列) Reply 複合プライマリキー: • Id (文字列) • ReplyDateTime (文字列) [Reply] テーブルには、PostedBy-Message-Index という名前のグローバルセカンダリインデックスが あります。このインデックスでは、Reply テーブルの 2 つの非キー属性でのクエリを容易にします。 API Version 2012-08-10 589 Amazon DynamoDB 開発者ガイド サンプルデータファイル インデックス名 プライマリキー PostedBy-Message-Index 複合プライマリキー: • PostedBy (文字列) • Message (文字列) これらのテーブルの詳細については、「ユースケース 1: 製品カタログ (p. 166)」および「ユースケー ス 2: フォーラムアプリケーション (p. 166)」を参照してください。 サンプルデータファイル トピック • ProductCatalog のサンプルデータ (p. 590) • Forum のサンプルデータ (p. 595) • Thread のサンプルデータ (p. 596) • Reply サンプルデータ (p. 598) 以下のセクションでは、ProductCatalog、Forum、Thread、および Reply の各テーブルの読み込みに 使用されるサンプルデータファイルを示します。 各データファイルには複数の PutRequest 要素が含まれ、それぞれに 1 つの項目が含まれます。これ らの PutRequest 要素は、AWS Command Line Interface (AWS CLI) を使用して BatchWriteItem オペレーションへの入力として使用されます。 詳細については、「テーブルの作成とサンプルデータのロード (p. 166)」の「ステップ 2: データを テーブルにロードする (p. 168)」を参照してください。 ProductCatalog のサンプルデータ { "ProductCatalog": [ { "PutRequest": { "Item": { "Id": { "N": "101" }, "Title": { "S": "Book 101 Title" }, "ISBN": { "S": "111-1111111111" }, "Authors": { "L": [ { "S": "Author1" } ] }, "Price": { "N": "2" }, "Dimensions": { API Version 2012-08-10 590 Amazon DynamoDB 開発者ガイド サンプルデータファイル "S": "8.5 x 11.0 x 0.5" }, "PageCount": { "N": "500" }, "InPublication": { "BOOL": true }, "ProductCategory": { "S": "Book" } } } }, { "PutRequest": { "Item": { "Id": { "N": "102" }, "Title": { "S": "Book 102 Title" }, "ISBN": { "S": "222-2222222222" }, "Authors": { "L": [ { "S": "Author1" }, { "S": "Author2" } ] }, "Price": { "N": "20" }, "Dimensions": { "S": "8.5 x 11.0 x 0.8" }, "PageCount": { "N": "600" }, "InPublication": { "BOOL": true }, "ProductCategory": { "S": "Book" } } } }, { "PutRequest": { "Item": { "Id": { "N": "103" API Version 2012-08-10 591 Amazon DynamoDB 開発者ガイド サンプルデータファイル }, "Title": { "S": "Book 103 Title" }, "ISBN": { "S": "333-3333333333" }, "Authors": { "L": [ { "S": "Author1" }, { "S": "Author2" } ] }, "Price": { "N": "2000" }, "Dimensions": { "S": "8.5 x 11.0 x 1.5" }, "PageCount": { "N": "600" }, "InPublication": { "BOOL": false }, "ProductCategory": { "S": "Book" } } } }, { "PutRequest": { "Item": { "Id": { "N": "201" }, "Title": { "S": "18-Bike-201" }, "Description": { "S": "201 Description" }, "BicycleType": { "S": "Road" }, "Brand": { "S": "Mountain A" }, "Price": { "N": "100" }, "Color": { "L": [ { API Version 2012-08-10 592 Amazon DynamoDB 開発者ガイド サンプルデータファイル "S": "Red" }, { "S": "Black" } ] }, "ProductCategory": { "S": "Bicycle" } } } }, { "PutRequest": { "Item": { "Id": { "N": "202" }, "Title": { "S": "21-Bike-202" }, "Description": { "S": "202 Description" }, "BicycleType": { "S": "Road" }, "Brand": { "S": "Brand-Company A" }, "Price": { "N": "200" }, "Color": { "L": [ { "S": "Green" }, { "S": "Black" } ] }, "ProductCategory": { "S": "Bicycle" } } } }, { "PutRequest": { "Item": { "Id": { "N": "203" }, "Title": { "S": "19-Bike-203" }, API Version 2012-08-10 593 Amazon DynamoDB 開発者ガイド サンプルデータファイル "Description": { "S": "203 Description" }, "BicycleType": { "S": "Road" }, "Brand": { "S": "Brand-Company B" }, "Price": { "N": "300" }, "Color": { "L": [ { "S": "Red" }, { "S": "Green" }, { "S": "Black" } ] }, "ProductCategory": { "S": "Bicycle" } } } }, { "PutRequest": { "Item": { "Id": { "N": "204" }, "Title": { "S": "18-Bike-204" }, "Description": { "S": "204 Description" }, "BicycleType": { "S": "Mountain" }, "Brand": { "S": "Brand-Company B" }, "Price": { "N": "400" }, "Color": { "L": [ { "S": "Red" } ] }, API Version 2012-08-10 594 Amazon DynamoDB 開発者ガイド サンプルデータファイル "ProductCategory": { "S": "Bicycle" } } } }, { "PutRequest": { "Item": { "Id": { "N": "205" }, "Title": { "S": "18-Bike-204" }, "Description": { "S": "205 Description" }, "BicycleType": { "S": "Hybrid" }, "Brand": { "S": "Brand-Company C" }, "Price": { "N": "500" }, "Color": { "L": [ { "S": "Red" }, { "S": "Black" } ] }, "ProductCategory": { "S": "Bicycle" } } } } ] } Forum のサンプルデータ { "Forum": [ { "PutRequest": { "Item": { "Name": {"S":"Amazon DynamoDB"}, "Category": {"S":"Amazon Web Services"}, "Threads": {"N":"2"}, "Messages": {"N":"4"}, "Views": {"N":"1000"} API Version 2012-08-10 595 Amazon DynamoDB 開発者ガイド サンプルデータファイル } } }, { "PutRequest": { "Item": { "Name": {"S":"Amazon S3"}, "Category": {"S":"Amazon Web Services"} } } } ] } Thread のサンプルデータ { "Thread": [ { "PutRequest": { "Item": { "ForumName": { "S": "Amazon DynamoDB" }, "Subject": { "S": "DynamoDB Thread 1" }, "Message": { "S": "DynamoDB thread 1 message" }, "LastPostedBy": { "S": "User A" }, "LastPostedDateTime": { "S": "2015-09-22T19:58:22.514Z" }, "Views": { "N": "0" }, "Replies": { "N": "0" }, "Answered": { "N": "0" }, "Tags": { "L": [ { "S": "index" }, { "S": "primarykey" }, { "S": "table" } ] } API Version 2012-08-10 596 Amazon DynamoDB 開発者ガイド サンプルデータファイル } } }, { "PutRequest": { "Item": { "ForumName": { "S": "Amazon DynamoDB" }, "Subject": { "S": "DynamoDB Thread 2" }, "Message": { "S": "DynamoDB thread 2 message" }, "LastPostedBy": { "S": "User A" }, "LastPostedDateTime": { "S": "2015-09-15T19:58:22.514Z" }, "Views": { "N": "3" }, "Replies": { "N": "0" }, "Answered": { "N": "0" }, "Tags": { "L": [ { "S": "items" }, { "S": "attributes" }, { "S": "throughput" } ] } } } }, { "PutRequest": { "Item": { "ForumName": { "S": "Amazon S3" }, "Subject": { "S": "S3 Thread 1" }, "Message": { "S": "S3 thread 1 message" }, "LastPostedBy": { API Version 2012-08-10 597 Amazon DynamoDB 開発者ガイド サンプルデータファイル "S": "User A" }, "LastPostedDateTime": { "S": "2015-09-29T19:58:22.514Z" }, "Views": { "N": "0" }, "Replies": { "N": "0" }, "Answered": { "N": "0" }, "Tags": { "L": [ { "S": "largeobjects" }, { "S": "multipart upload" } ] } } } } ] } Reply サンプルデータ { "Reply": [ { "PutRequest": { "Item": { "Id": { "S": "Amazon DynamoDB#DynamoDB Thread 1" }, "ReplyDateTime": { "S": "2015-09-15T19:58:22.947Z" }, "Message": { "S": "DynamoDB Thread 1 Reply 1 text" }, "PostedBy": { "S": "User A" } } } }, { "PutRequest": { "Item": { "Id": { "S": "Amazon DynamoDB#DynamoDB Thread 1" }, API Version 2012-08-10 598 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード "ReplyDateTime": { "S": "2015-09-22T19:58:22.947Z" }, "Message": { "S": "DynamoDB Thread 1 Reply 2 text" }, "PostedBy": { "S": "User B" } } } }, { "PutRequest": { "Item": { "Id": { "S": "Amazon DynamoDB#DynamoDB Thread 2" }, "ReplyDateTime": { "S": "2015-09-29T19:58:22.947Z" }, "Message": { "S": "DynamoDB Thread 2 Reply 1 text" }, "PostedBy": { "S": "User A" } } } }, { "PutRequest": { "Item": { "Id": { "S": "Amazon DynamoDB#DynamoDB Thread 2" }, "ReplyDateTime": { "S": "2015-10-05T19:58:22.947Z" }, "Message": { "S": "DynamoDB Thread 2 Reply 2 text" }, "PostedBy": { "S": "User A" } } } } ] } サンプルテーブルの作成とデータのアップロード トピック • AWS SDK for Java を使用した、サンプルテーブルの作成とデータのアップロード (p. 600) • AWS SDK for .NET を使用した、サンプルテーブルの作成とデータのアップロード (p. 608) API Version 2012-08-10 599 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – Java • AWS SDK for PHP を使用した、サンプルテーブルの作成とデータのアップロード (p. 617) 「テーブルの作成とサンプルデータのロード (p. 166)」では、最初に DynamoDB コンソールを使用し てテーブルを作成し、AWS CLI を使用してデータをテーブルに追加します。この付録では、テーブル の作成とデータの追加の両方をプログラムによって実行するためのコードを示します。 AWS SDK for Java を使用した、サンプルテーブル の作成とデータのアップロード 次の Java コードの例では、テーブルを作成して、そのテーブルにデータをアップロードしてい ます。結果として得られるテーブル構造とデータを「テーブルの作成とサンプルデータのロー ド (p. 166)」に示します。このコードを Eclipse を使用して実行するための詳しい手順については、 「Java コードサンプル (p. 171)」を参照してください。 // Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. package com.amazonaws.codesamples; import import import import import import java.text.SimpleDateFormat; java.util.ArrayList; java.util.Arrays; java.util.Date; java.util.HashSet; java.util.TimeZone; import import import import import import import import import import import import import com.amazonaws.auth.profile.ProfileCredentialsProvider; com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; com.amazonaws.services.dynamodbv2.document.DynamoDB; com.amazonaws.services.dynamodbv2.document.Item; com.amazonaws.services.dynamodbv2.document.Table; com.amazonaws.services.dynamodbv2.model.AttributeDefinition; com.amazonaws.services.dynamodbv2.model.CreateTableRequest; com.amazonaws.services.dynamodbv2.model.KeySchemaElement; com.amazonaws.services.dynamodbv2.model.KeyType; com.amazonaws.services.dynamodbv2.model.LocalSecondaryIndex; com.amazonaws.services.dynamodbv2.model.Projection; com.amazonaws.services.dynamodbv2.model.ProjectionType; com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; public class CreateTablesLoadData { static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( new ProfileCredentialsProvider())); static SimpleDateFormat dateFormatter = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); static static static static String String String String productCatalogTableName = "ProductCatalog"; forumTableName = "Forum"; threadTableName = "Thread"; replyTableName = "Reply"; public static void main(String[] args) throws Exception { try { API Version 2012-08-10 600 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – Java deleteTable(productCatalogTableName); deleteTable(forumTableName); deleteTable(threadTableName); deleteTable(replyTableName); // Parameter1: table name // Parameter2: reads per second // // Parameter3: writes per second // Parameter4/5: partition key and data type // Parameter6/7: sort key and data type (if applicable) createTable(productCatalogTableName, 10L, 5L, "Id", "N"); createTable(forumTableName, 10L, 5L, "Name", "S"); createTable(threadTableName, 10L, 5L, "ForumName", "S", "Subject", "S"); createTable(replyTableName, 10L, 5L, "Id", "S", "ReplyDateTime", "S"); loadSampleProducts(productCatalogTableName); loadSampleForums(forumTableName); loadSampleThreads(threadTableName); loadSampleReplies(replyTableName); } catch (Exception e) { System.err.println("Program failed:"); System.err.println(e.getMessage()); } System.out.println("Success."); } private static void deleteTable(String tableName) { Table table = dynamoDB.getTable(tableName); try { System.out.println("Issuing DeleteTable request for " + tableName); table.delete(); System.out.println("Waiting for " + tableName + " to be deleted...this may take a while..."); table.waitForDelete(); } catch (Exception e) { System.err.println("DeleteTable request failed for " + tableName); System.err.println(e.getMessage()); } } private static void createTable( String tableName, long readCapacityUnits, long writeCapacityUnits, String partitionKeyName, String partitionKeyType) { createTable(tableName, readCapacityUnits, writeCapacityUnits, partitionKeyName, partitionKeyType, null, null); } private static void createTable( String tableName, long readCapacityUnits, long writeCapacityUnits, String partitionKeyName, String partitionKeyType, String sortKeyName, String sortKeyType) { API Version 2012-08-10 601 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – Java try { ArrayList<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>(); keySchema.add(new KeySchemaElement() .withAttributeName(partitionKeyName) .withKeyType(KeyType.HASH)); //Partition key ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition() .withAttributeName(partitionKeyName) .withAttributeType(partitionKeyType)); if (sortKeyName != null) { keySchema.add(new KeySchemaElement() .withAttributeName(sortKeyName) .withKeyType(KeyType.RANGE)); //Sort key attributeDefinitions.add(new AttributeDefinition() .withAttributeName(sortKeyName) .withAttributeType(sortKeyType)); } CreateTableRequest request = new CreateTableRequest() .withTableName(tableName) .withKeySchema(keySchema) .withProvisionedThroughput( new ProvisionedThroughput() .withReadCapacityUnits(readCapacityUnits) .withWriteCapacityUnits(writeCapacityUnits)); // If this is the Reply table, define a local secondary index if (replyTableName.equals(tableName)) { attributeDefinitions.add(new AttributeDefinition() .withAttributeName("PostedBy") .withAttributeType("S")); ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new ArrayList<LocalSecondaryIndex>(); localSecondaryIndexes.add(new LocalSecondaryIndex() .withIndexName("PostedBy-Index") .withKeySchema( new KeySchemaElement().withAttributeName(partitionKeyName).withKeyType(KeyType.HASH), //Partition key new KeySchemaElement() .withAttributeName("PostedBy") .withKeyType(KeyType.RANGE)) //Sort key .withProjection(new Projection() .withProjectionType(ProjectionType.KEYS_ONLY))); request.setLocalSecondaryIndexes(localSecondaryIndexes); } request.setAttributeDefinitions(attributeDefinitions); System.out.println("Issuing CreateTable request for " + tableName); API Version 2012-08-10 602 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – Java Table table = dynamoDB.createTable(request); System.out.println("Waiting for " + tableName + " to be created...this may take a while..."); table.waitForActive(); } catch (Exception e) { System.err.println("CreateTable request failed for " + tableName); System.err.println(e.getMessage()); } } private static void loadSampleProducts(String tableName) { Table table = dynamoDB.getTable(tableName); try { System.out.println("Adding data to " + tableName); Item item = new Item() .withPrimaryKey("Id", 101) .withString("Title", "Book 101 Title") .withString("ISBN", "111-1111111111") .withStringSet("Authors", new HashSet<String>( Arrays.asList("Author1"))) .withNumber("Price", 2) .withString("Dimensions", "8.5 x 11.0 x 0.5") .withNumber("PageCount", 500) .withBoolean("InPublication", true) .withString("ProductCategory", "Book"); table.putItem(item); item = new Item() .withPrimaryKey("Id", 102) .withString("Title", "Book 102 Title") .withString("ISBN", "222-2222222222") .withStringSet( "Authors", new HashSet<String>( Arrays.asList("Author1", "Author2"))) .withNumber("Price", 20) .withString("Dimensions", "8.5 x 11.0 x 0.8") .withNumber("PageCount", 600) .withBoolean("InPublication", true) .withString("ProductCategory", "Book"); table.putItem(item); item = new Item() .withPrimaryKey("Id", 103) .withString("Title", "Book 103 Title") .withString("ISBN", "333-3333333333") .withStringSet( "Authors", new HashSet<String>( Arrays.asList("Author1", "Author2"))) // Intentional. Later we'll run Scan to find price error. Find // items > 1000 in price. .withNumber("Price", 2000) .withString("Dimensions", "8.5 x 11.0 x 1.5") .withNumber("PageCount", 600) .withBoolean("InPublication", false) API Version 2012-08-10 603 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – Java .withString("ProductCategory", "Book"); table.putItem(item); // Add bikes. item = new Item() .withPrimaryKey("Id", 201) .withString("Title", "18-Bike-201") // Size, followed by some title. .withString("Description", "201 Description") .withString("BicycleType", "Road") .withString("Brand", "Mountain A") // Trek, Specialized. .withNumber("Price", 100) .withStringSet("Color", new HashSet<String>( Arrays.asList("Red", "Black"))) .withString("ProductCategory", "Bicycle"); table.putItem(item); item = new Item() .withPrimaryKey("Id", 202) .withString("Title", "21-Bike-202") .withString("Description", "202 Description") .withString("BicycleType", "Road") .withString("Brand", "Brand-Company A") .withNumber("Price", 200) .withStringSet( "Color", new HashSet<String>( Arrays.asList("Green", "Black"))) .withString("ProductCategory", "Bicycle"); table.putItem(item); item = new Item() .withPrimaryKey("Id", 203) .withString("Title", "19-Bike-203") .withString("Description", "203 Description") .withString("BicycleType", "Road") .withString("Brand", "Brand-Company B") .withNumber("Price", 300) .withStringSet( "Color", new HashSet<String>( Arrays.asList("Red", "Green", "Black"))) .withString("ProductCategory", "Bicycle"); table.putItem(item); item = new Item() .withPrimaryKey("Id", 204) .withString("Title", "18-Bike-204") .withString("Description", "204 Description") .withString("BicycleType", "Mountain") .withString("Brand", "Brand-Company B") .withNumber("Price", 400) .withStringSet("Color", new HashSet<String>( Arrays.asList("Red"))) .withString("ProductCategory", "Bicycle"); table.putItem(item); item = new Item() .withPrimaryKey("Id", 205) .withString("Title", "20-Bike-205") .withString("Description", "205 Description") API Version 2012-08-10 604 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – Java .withString("BicycleType", "Hybrid") .withString("Brand", "Brand-Company C") .withNumber("Price", 500) .withStringSet("Color", new HashSet<String>( Arrays.asList("Red", "Black"))) .withString("ProductCategory", "Bicycle"); table.putItem(item); } catch (Exception e) { System.err.println("Failed to create item in " + tableName); System.err.println(e.getMessage()); } } private static void loadSampleForums(String tableName) { Table table = dynamoDB.getTable(tableName); try { System.out.println("Adding data to " + tableName); Item item = new Item().withPrimaryKey("Name", "Amazon DynamoDB") .withString("Category", "Amazon Web Services") .withNumber("Threads", 2).withNumber("Messages", 4) .withNumber("Views", 1000); table.putItem(item); item = new Item().withPrimaryKey("Name", "Amazon S3") .withString("Category", "Amazon Web Services") .withNumber("Threads", 0); table.putItem(item); } catch (Exception e) { System.err.println("Failed to create item in " + tableName); System.err.println(e.getMessage()); } } private static void loadSampleThreads(String tableName) { try { long time1 = (new Date()).getTime() - (7 * 24 * 60 * 60 * 1000); // 7 // days // ago long time2 = (new Date()).getTime() - (14 * 24 * 60 * 60 * 1000); // 14 // days // ago long time3 = (new Date()).getTime() - (21 * 24 * 60 * 60 * 1000); // 21 // days // ago Date date1 = new Date(); date1.setTime(time1); Date date2 = new Date(); API Version 2012-08-10 605 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – Java date2.setTime(time2); Date date3 = new Date(); date3.setTime(time3); dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); Table table = dynamoDB.getTable(tableName); System.out.println("Adding data to " + tableName); Item item = new Item() .withPrimaryKey("ForumName", "Amazon DynamoDB") .withString("Subject", "DynamoDB Thread 1") .withString("Message", "DynamoDB thread 1 message") .withString("LastPostedBy", "User A") .withString("LastPostedDateTime", dateFormatter.format(date2)) .withNumber("Views", 0) .withNumber("Replies", 0) .withNumber("Answered", 0) .withStringSet( "Tags", new HashSet<String>( Arrays.asList("index", "primarykey", "table"))); table.putItem(item); item = new Item() .withPrimaryKey("ForumName", "Amazon DynamoDB") .withString("Subject", "DynamoDB Thread 2") .withString("Message", "DynamoDB thread 2 message") .withString("LastPostedBy", "User A") .withString("LastPostedDateTime", dateFormatter.format(date3)) .withNumber("Views", 0) .withNumber("Replies", 0) .withNumber("Answered", 0) .withStringSet( "Tags", new HashSet<String>( Arrays.asList("index", "partitionkey", "sortkey"))); table.putItem(item); item = new Item() .withPrimaryKey("ForumName", "Amazon S3") .withString("Subject", "S3 Thread 1") .withString("Message", "S3 Thread 3 message") .withString("LastPostedBy", "User A") .withString("LastPostedDateTime", dateFormatter.format(date1)) .withNumber("Views", 0) .withNumber("Replies", 0) .withNumber("Answered", 0) .withStringSet( "Tags", new HashSet<String>( Arrays.asList("largeobjects", "multipart upload"))); table.putItem(item); } catch (Exception e) { System.err.println("Failed to create item in " + tableName); System.err.println(e.getMessage()); } } API Version 2012-08-10 606 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – Java private static void loadSampleReplies(String tableName) { try { // 1 day ago long time0 = (new Date()).getTime() - (1 * 24 * 60 * 60 * 1000); // 7 days ago long time1 = (new Date()).getTime() - (7 * 24 * 60 * 60 * 1000); // 14 days ago long time2 = (new Date()).getTime() - (14 * 24 * 60 * 60 * 1000); // 21 days ago long time3 = (new Date()).getTime() - (21 * 24 * 60 * 60 * 1000); Date date0 = new Date(); date0.setTime(time0); Date date1 = new Date(); date1.setTime(time1); Date date2 = new Date(); date2.setTime(time2); Date date3 = new Date(); date3.setTime(time3); dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); Table table = dynamoDB.getTable(tableName); System.out.println("Adding data to " + tableName); // Add threads. Item item = new Item() .withPrimaryKey("Id", "Amazon DynamoDB#DynamoDB Thread 1") .withString("ReplyDateTime", (dateFormatter.format(date3))) .withString("Message", "DynamoDB Thread 1 Reply 1 text") .withString("PostedBy", "User A"); table.putItem(item); item = new Item() .withPrimaryKey("Id", "Amazon DynamoDB#DynamoDB Thread 1") .withString("ReplyDateTime", dateFormatter.format(date2)) .withString("Message", "DynamoDB Thread 1 Reply 2 text") .withString("PostedBy", "User B"); table.putItem(item); item = new Item() .withPrimaryKey("Id", "Amazon DynamoDB#DynamoDB Thread 2") .withString("ReplyDateTime", dateFormatter.format(date1)) .withString("Message", "DynamoDB Thread 2 Reply 1 text") .withString("PostedBy", "User A"); table.putItem(item); item = new Item() .withPrimaryKey("Id", "Amazon DynamoDB#DynamoDB Thread 2") .withString("ReplyDateTime", dateFormatter.format(date0)) .withString("Message", "DynamoDB Thread 2 Reply 2 text") .withString("PostedBy", "User A"); API Version 2012-08-10 607 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – .NET table.putItem(item); } catch (Exception e) { System.err.println("Failed to create item in " + tableName); System.err.println(e.getMessage()); } } } AWS SDK for .NET を使用した、サンプルテーブル の作成とデータのアップロード 次の C# コードの例では、テーブルを作成して、そのテーブルにデータをアップロードしています。 結果として得られるテーブル構造とデータを「テーブルの作成とサンプルデータのロード (p. 166)」 に示します。このコードを Visual Studio を使用して実行するための詳しい手順については、「.NET コードサンプル (p. 173)」を参照してください。 using using using using using using using System; System.Collections.Generic; Amazon.DynamoDBv2; Amazon.DynamoDBv2.DocumentModel; Amazon.DynamoDBv2.Model; Amazon.Runtime; Amazon.SecurityToken; namespace com.amazonaws.codesamples { class CreateTablesLoadData { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { //DeleteAllTables(client); DeleteTable("ProductCatalog"); DeleteTable("Forum"); DeleteTable("Thread"); DeleteTable("Reply"); // Create tables (using the AWS SDK for .NET low-level API). CreateTableProductCatalog(); CreateTableForum(); CreateTableThread(); // ForumTitle, Subject */ CreateTableReply(); // Load data (using the .NET SDK document API) LoadSampleProducts(); LoadSampleForums(); LoadSampleThreads(); LoadSampleReplies(); Console.WriteLine("Sample complete!"); Console.WriteLine("Press ENTER to continue"); API Version 2012-08-10 608 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – .NET Console.ReadLine(); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } } private static void DeleteTable(string tableName) { try { var deleteTableResponse = client.DeleteTable(new DeleteTableRequest() { TableName = tableName }); WaitTillTableDeleted(client, tableName, deleteTableResponse); } catch (ResourceNotFoundException) { // There is no such table. } } private static void CreateTableProductCatalog() { string tableName = "ProductCatalog"; var response = client.CreateTable(new CreateTableRequest { TableName = tableName, AttributeDefinitions = new List<AttributeDefinition>() { new AttributeDefinition { AttributeName = "Id", AttributeType = "N" } }, KeySchema = new List<KeySchemaElement>() { new KeySchemaElement { AttributeName = "Id", KeyType = "HASH" } }, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 10, WriteCapacityUnits = 5 } }); WaitTillTableCreated(client, tableName, response); } private static void CreateTableForum() { string tableName = "Forum"; API Version 2012-08-10 609 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – .NET var response = client.CreateTable(new CreateTableRequest { TableName = tableName, AttributeDefinitions = new List<AttributeDefinition>() { new AttributeDefinition { AttributeName = "Name", AttributeType = "S" } }, KeySchema = new List<KeySchemaElement>() { new KeySchemaElement { AttributeName = "Name", // forum Title KeyType = "HASH" } }, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 10, WriteCapacityUnits = 5 } }); WaitTillTableCreated(client, tableName, response); } private static void CreateTableThread() { string tableName = "Thread"; var response = client.CreateTable(new CreateTableRequest { TableName = tableName, AttributeDefinitions = new List<AttributeDefinition>() { new AttributeDefinition { AttributeName = "ForumName", // Hash attribute AttributeType = "S" }, new AttributeDefinition { AttributeName = "Subject", AttributeType = "S" } }, KeySchema = new List<KeySchemaElement>() { new KeySchemaElement { AttributeName = "ForumName", // Hash attribute KeyType = "HASH" }, new KeySchemaElement { AttributeName = "Subject", // Range attribute API Version 2012-08-10 610 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – .NET KeyType = "RANGE" } }, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 10, WriteCapacityUnits = 5 } }); WaitTillTableCreated(client, tableName, response); } private static void CreateTableReply() { string tableName = "Reply"; var response = client.CreateTable(new CreateTableRequest { TableName = tableName, AttributeDefinitions = new List<AttributeDefinition>() { new AttributeDefinition { AttributeName = "Id", AttributeType = "S" }, new AttributeDefinition { AttributeName = "ReplyDateTime", AttributeType = "S" }, new AttributeDefinition { AttributeName = "PostedBy", AttributeType = "S" } }, KeySchema = new List<KeySchemaElement>() { new KeySchemaElement() { AttributeName = "Id", KeyType = "HASH" }, new KeySchemaElement() { AttributeName = "ReplyDateTime", KeyType = "RANGE" } }, LocalSecondaryIndexes = new List<LocalSecondaryIndex>() { new LocalSecondaryIndex() { IndexName = "PostedBy_index", KeySchema = new List<KeySchemaElement>() { API Version 2012-08-10 611 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – .NET new KeySchemaElement() {AttributeName = "Id", KeyType = "HASH"}, new KeySchemaElement() {AttributeName = "PostedBy", KeyType = "RANGE"} }, Projection = new Projection() {ProjectionType = ProjectionType.KEYS_ONLY} } }, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 10, WriteCapacityUnits = 5 } }); WaitTillTableCreated(client, tableName, response); } private static void WaitTillTableCreated(AmazonDynamoDBClient client, string tableName, CreateTableResponse response) { var tableDescription = response.TableDescription; string status = tableDescription.TableStatus; Console.WriteLine(tableName + " - " + status); // Let us wait until table is created. Call DescribeTable. while (status != "ACTIVE") { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); status = res.Table.TableStatus; } // Try-catch to handle potential eventual-consistency issue. catch (ResourceNotFoundException) { } } } private static void WaitTillTableDeleted(AmazonDynamoDBClient client, string tableName, DeleteTableResponse response) { var tableDescription = response.TableDescription; API Version 2012-08-10 612 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – .NET string status = tableDescription.TableStatus; Console.WriteLine(tableName + " - " + status); // Let us wait until table is created. Call DescribeTable try { while (status == "DELETING") { System.Threading.Thread.Sleep(5000); // wait 5 seconds var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); status = res.Table.TableStatus; } } catch (ResourceNotFoundException) { // Table deleted. } } private static void LoadSampleProducts() { Table productCatalogTable = Table.LoadTable(client, "ProductCatalog"); // ********** Add Books ********************* var book1 = new Document(); book1["Id"] = 101; book1["Title"] = "Book 101 Title"; book1["ISBN"] = "111-1111111111"; book1["Authors"] = new List<string> { "Author 1" }; book1["Price"] = -2; // *** Intentional value. Later used to illustrate scan. book1["Dimensions"] = "8.5 x 11.0 x 0.5"; book1["PageCount"] = 500; book1["InPublication"] = true; book1["ProductCategory"] = "Book"; productCatalogTable.PutItem(book1); var book2 = new Document(); book2["Id"] = 102; book2["Title"] = "Book 102 Title"; book2["ISBN"] = "222-2222222222"; book2["Authors"] = new List<string> { "Author 1", "Author 2" }; ; book2["Price"] = 20; book2["Dimensions"] = "8.5 x 11.0 x 0.8"; book2["PageCount"] = 600; book2["InPublication"] = true; book2["ProductCategory"] = "Book"; API Version 2012-08-10 613 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – .NET productCatalogTable.PutItem(book2); var book3 = new Document(); book3["Id"] = 103; book3["Title"] = "Book 103 Title"; book3["ISBN"] = "333-3333333333"; book3["Authors"] = new List<string> { "Author 1", "Author2", "Author 3" }; ; book3["Price"] = 2000; book3["Dimensions"] = "8.5 x 11.0 x 1.5"; book3["PageCount"] = 700; book3["InPublication"] = false; book3["ProductCategory"] = "Book"; productCatalogTable.PutItem(book3); // ************ Add bikes. ******************* var bicycle1 = new Document(); bicycle1["Id"] = 201; bicycle1["Title"] = "18-Bike 201"; // size, followed by some title. bicycle1["Description"] = "201 description"; bicycle1["BicycleType"] = "Road"; bicycle1["Brand"] = "Brand-Company A"; // Trek, Specialized. bicycle1["Price"] = 100; bicycle1["Color"] = new List<string> { "Red", "Black" }; bicycle1["ProductCategory"] = "Bike"; productCatalogTable.PutItem(bicycle1); var bicycle2 = new Document(); bicycle2["Id"] = 202; bicycle2["Title"] = "21-Bike 202Brand-Company A"; bicycle2["Description"] = "202 description"; bicycle2["BicycleType"] = "Road"; bicycle2["Brand"] = ""; bicycle2["Price"] = 200; bicycle2["Color"] = new List<string> { "Green", "Black" }; bicycle2["ProductCategory"] = "Bicycle"; productCatalogTable.PutItem(bicycle2); var bicycle3 = new Document(); bicycle3["Id"] = 203; bicycle3["Title"] = "19-Bike 203"; bicycle3["Description"] = "203 description"; bicycle3["BicycleType"] = "Road"; bicycle3["Brand"] = "Brand-Company B"; bicycle3["Price"] = 300; bicycle3["Color"] = new List<string> { "Red", "Green", "Black" }; bicycle3["ProductCategory"] = "Bike"; productCatalogTable.PutItem(bicycle3); var bicycle4 = new Document(); bicycle4["Id"] = 204; bicycle4["Title"] = "18-Bike 204"; bicycle4["Description"] = "204 description"; bicycle4["BicycleType"] = "Mountain"; bicycle4["Brand"] = "Brand-Company B"; bicycle4["Price"] = 400; bicycle4["Color"] = new List<string> { "Red" }; API Version 2012-08-10 614 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – .NET bicycle4["ProductCategory"] = "Bike"; productCatalogTable.PutItem(bicycle4); var bicycle5 = new Document(); bicycle5["Id"] = 205; bicycle5["Title"] = "20-Title 205"; bicycle4["Description"] = "205 description"; bicycle5["BicycleType"] = "Hybrid"; bicycle5["Brand"] = "Brand-Company C"; bicycle5["Price"] = 500; bicycle5["Color"] = new List<string> { "Red", "Black" }; bicycle5["ProductCategory"] = "Bike"; productCatalogTable.PutItem(bicycle5); } private static void LoadSampleForums() { Table forumTable = Table.LoadTable(client, "Forum"); var forum1 = new Document(); forum1["Name"] = "Amazon DynamoDB"; // PK forum1["Category"] = "Amazon Web Services"; forum1["Threads"] = 2; forum1["Messages"] = 4; forum1["Views"] = 1000; forumTable.PutItem(forum1); var forum2 = new Document(); forum2["Name"] = "Amazon S3"; // PK forum2["Category"] = "Amazon Web Services"; forum2["Threads"] = 1; forumTable.PutItem(forum2); } private static void LoadSampleThreads() { Table threadTable = Table.LoadTable(client, "Thread"); // Thread 1. var thread1 = new Document(); thread1["ForumName"] = "Amazon DynamoDB"; // Hash attribute. thread1["Subject"] = "DynamoDB Thread 1"; // Range attribute. thread1["Message"] = "DynamoDB thread 1 message text"; thread1["LastPostedBy"] = "User A"; thread1["LastPostedDateTime"] = DateTime.UtcNow.Subtract(new TimeSpan(14, 0, 0, 0)); thread1["Views"] = 0; thread1["Replies"] = 0; thread1["Answered"] = false; thread1["Tags"] = new List<string> { "index", "primarykey", "table" }; threadTable.PutItem(thread1); // Thread 2. var thread2 = new Document(); thread2["ForumName"] = "Amazon DynamoDB"; // Hash attribute. API Version 2012-08-10 615 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – .NET thread2["Subject"] = "DynamoDB Thread 2"; // Range attribute. thread2["Message"] = "DynamoDB thread 2 message text"; thread2["LastPostedBy"] = "User A"; thread2["LastPostedDateTime"] = DateTime.UtcNow.Subtract(new TimeSpan(21, 0, 0, 0)); thread2["Views"] = 0; thread2["Replies"] = 0; thread2["Answered"] = false; thread2["Tags"] = new List<string> { "index", "primarykey", "rangekey" }; threadTable.PutItem(thread2); // Thread 3. var thread3 = new Document(); thread3["ForumName"] = "Amazon S3"; // Hash attribute. thread3["Subject"] = "S3 Thread 1"; // Range attribute. thread3["Message"] = "S3 thread 3 message text"; thread3["LastPostedBy"] = "User A"; thread3["LastPostedDateTime"] = DateTime.UtcNow.Subtract(new TimeSpan(7, 0, 0, 0)); thread3["Views"] = 0; thread3["Replies"] = 0; thread3["Answered"] = false; thread3["Tags"] = new List<string> { "largeobjects", "multipart upload" }; threadTable.PutItem(thread3); } private static void LoadSampleReplies() { Table replyTable = Table.LoadTable(client, "Reply"); // Reply 1 - thread 1. var thread1Reply1 = new Document(); thread1Reply1["Id"] = "Amazon DynamoDB#DynamoDB Thread 1"; // Hash attribute. thread1Reply1["ReplyDateTime"] = DateTime.UtcNow.Subtract(new TimeSpan(21, 0, 0, 0)); // Range attribute. thread1Reply1["Message"] = "DynamoDB Thread 1 Reply 1 text"; thread1Reply1["PostedBy"] = "User A"; replyTable.PutItem(thread1Reply1); // Reply 2 - thread 1. var thread1reply2 = new Document(); thread1reply2["Id"] = "Amazon DynamoDB#DynamoDB Thread 1"; // Hash attribute. thread1reply2["ReplyDateTime"] = DateTime.UtcNow.Subtract(new TimeSpan(14, 0, 0, 0)); // Range attribute. thread1reply2["Message"] = "DynamoDB Thread 1 Reply 2 text"; thread1reply2["PostedBy"] = "User B"; replyTable.PutItem(thread1reply2); // Reply 3 - thread 1. var thread1Reply3 = new Document(); thread1Reply3["Id"] = "Amazon DynamoDB#DynamoDB Thread 1"; // Hash attribute. API Version 2012-08-10 616 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – PHP thread1Reply3["ReplyDateTime"] = DateTime.UtcNow.Subtract(new TimeSpan(7, 0, 0, 0)); // Range attribute. thread1Reply3["Message"] = "DynamoDB Thread 1 Reply 3 text"; thread1Reply3["PostedBy"] = "User B"; replyTable.PutItem(thread1Reply3); // Reply 1 - thread 2. var thread2Reply1 = new Document(); thread2Reply1["Id"] = "Amazon DynamoDB#DynamoDB Thread 2"; // Hash attribute. thread2Reply1["ReplyDateTime"] = DateTime.UtcNow.Subtract(new TimeSpan(7, 0, 0, 0)); // Range attribute. thread2Reply1["Message"] = "DynamoDB Thread 2 Reply 1 text"; thread2Reply1["PostedBy"] = "User A"; replyTable.PutItem(thread2Reply1); // Reply 2 - thread 2. var thread2Reply2 = new Document(); thread2Reply2["Id"] = "Amazon DynamoDB#DynamoDB Thread 2"; // Hash attribute. thread2Reply2["ReplyDateTime"] = DateTime.UtcNow.Subtract(new TimeSpan(1, 0, 0, 0)); // Range attribute. thread2Reply2["Message"] = "DynamoDB Thread 2 Reply 2 text"; thread2Reply2["PostedBy"] = "User A"; replyTable.PutItem(thread2Reply2); } } } AWS SDK for PHP を使用した、サンプルテーブル の作成とデータのアップロード 次の PHP コードの例では、テーブルを作成しています。結果として得られるテーブル構造とデータを 「テーブルの作成とサンプルデータのロード (p. 166)」に示します。このコードを実行するための詳 しい手順については、「PHP コードサンプル (p. 175)」を参照してください。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); $tableName = 'ProductCatalog'; echo "Creating table $tableName..."; API Version 2012-08-10 617 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – PHP try { $response = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'Id', 'AttributeType' => 'N' ] ], 'KeySchema' => [ [ 'AttributeName' => 'Id', 'KeyType' => 'HASH' //Partition key ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 10, 'WriteCapacityUnits' => 5 ] ]); echo "CreateTable request was successful.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to create table $tableName\n"); } $tableName = 'Forum'; echo "Creating table $tableName..."; try { $response = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'Name', 'AttributeType' => 'S' ] ], 'KeySchema' => [ [ 'AttributeName' => 'Name', 'KeyType' => 'HASH' //Partition key ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 10, 'WriteCapacityUnits' => 5 ] ]); echo "CreateTable request was successful.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to create table $tableName\n"); } $tableName = 'Thread'; echo "Creating table $tableName..."; API Version 2012-08-10 618 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – PHP try { $response = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'ForumName', 'AttributeType' => 'S' ], [ 'AttributeName' => 'Subject', 'AttributeType' => 'S' ] ], 'KeySchema' => [ [ 'AttributeName' => 'ForumName', 'KeyType' => 'HASH' //Partition key ], [ 'AttributeName' => 'Subject', 'KeyType' => 'RANGE' //Sort key ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 10, 'WriteCapacityUnits' => 5 ] ]); echo "CreateTable request was successful.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to create table $tableName\n"); } $tableName = 'Reply'; echo "Creating table $tableName..."; try { $response = $dynamodb->createTable([ 'TableName' => $tableName, 'AttributeDefinitions' => [ [ 'AttributeName' => 'Id', 'AttributeType' => 'S' ], [ 'AttributeName' => 'ReplyDateTime', 'AttributeType' => 'S' ], [ 'AttributeName' => 'PostedBy', 'AttributeType' => 'S' ] ], 'LocalSecondaryIndexes' => [ [ 'IndexName' => 'PostedBy-index', 'KeySchema' => [ API Version 2012-08-10 619 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – PHP [ 'AttributeName' => 'Id', 'KeyType' => 'HASH' //Partition key ], [ 'AttributeName' => 'PostedBy', 'KeyType' => 'RANGE' //Sort key ], ], 'Projection' => [ 'ProjectionType' => 'KEYS_ONLY', ], ], ], 'KeySchema' => [ [ 'AttributeName' => 'Id', 'KeyType' => 'HASH' //Partition key ], [ 'AttributeName' => 'ReplyDateTime', 'KeyType' => 'RANGE' //Sort key ] ], 'ProvisionedThroughput' => [ 'ReadCapacityUnits' => 10, 'WriteCapacityUnits' => 5 ] ]); echo "CreateTable request was successful.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to create table $tableName\n"); } ?> 次の PHP コードの例では、テーブルにデータをアップロードしています。結果として得られるテーブ ル構造とデータを「テーブルの作成とサンプルデータのロード (p. 166)」に示します。 <?php require 'vendor/autoload.php'; date_default_timezone_set('UTC'); use Aws\DynamoDb\Exception\DynamoDbException; $sdk = new Aws\Sdk([ 'region' => 'us-west-2', 'version' => 'latest' ]); $dynamodb = $sdk->createDynamoDb(); # Setup some local variables for dates $oneDayAgo = date('Y-m-d H:i:s', strtotime('-1 days')); $sevenDaysAgo = date('Y-m-d H:i:s', strtotime('-7 days')); API Version 2012-08-10 620 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – PHP $fourteenDaysAgo = date('Y-m-d H:i:s', strtotime('-14 days')); $twentyOneDaysAgo = date('Y-m-d H:i:s', strtotime('-21 days')); $tableName = 'ProductCatalog'; echo "Adding data to the $tableName table...\n"; try { $response = $dynamodb->batchWriteItem([ 'RequestItems' => [ $tableName => [ [ 'PutRequest' => [ 'Item' => [ 'Id' 'Title' 'ISBN' 'Authors' 'Price' 'Dimensions' => => => => => => ['N' => '1101'], ['S' => 'Book 101 Title'], ['S' => '111-1111111111'], ['SS' => ['Author1']], ['N' => '2'], ['S' => '8.5 x 11.0 x 0.5'], 'PageCount' => ['N' => '500'], 'InPublication' => ['N' => '1'], 'ProductCategory' => ['S' => 'Book'] ] ], ], [ 'PutRequest' => [ 'Item' => [ 'Id' 'Title' 'ISBN' 'Authors' => => => => ['N' => '102'], ['S' => 'Book 102 Title'], ['S' => '222-2222222222'], ['SS' => ['Author1', 'Author2']], 'Price' 'Dimensions' => ['N' => '20'], => ['S' => '8.5 x 11.0 x 0.8'], 'PageCount' => ['N' => '600'], 'InPublication' => ['N' => '1'], 'ProductCategory' => ['S' => 'Book'] ] ], ], [ 'PutRequest' => [ 'Item' => [ 'Id' 'Title' 'ISBN' 'Authors' => => => => ['N' => '103'], ['S' => 'Book 103 Title'], ['S' => '333-3333333333'], ['SS' => ['Author1', 'Author2']], 'Price' 'Dimensions' => ['N' => '2000'], => ['S' => '8.5 x 11.0 x 1.5'], 'PageCount' => ['N' => '600'], 'InPublication' => ['N' => '0'], 'ProductCategory' => ['S' => 'Book'] API Version 2012-08-10 621 Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – PHP ] ], ], [ 'PutRequest' => [ 'Item' => [ 'Id' 'Title' 'Description' 'BicycleType' 'Brand' 'Price' 'Color' 'ProductCategory' => => => => => => => => ['N' => '201'], ['S' => '18-Bike-201'], ['S' => '201 Description'], ['S' => 'Road'], ['S' => 'Mountain A'], ['N' => '100'], ['SS' => ['Red', 'Black']], ['S' => 'Bicycle'] => => => => => => => ['N' => '202'], ['S' => '21-Bike-202'], ['S' => '202 Description'], ['S' => 'Road'], ['S' => 'Brand-Company A'], ['N' => '200'], ['SS' => ['Green', ] ], ], [ 'PutRequest' => [ 'Item' => [ 'Id' 'Title' 'Description' 'BicycleType' 'Brand' 'Price' 'Color' 'Black']], 'ProductCategory' => ['S' => 'Bicycle'] ] ], ], [ 'PutRequest' => [ 'Item' => [ 'Id' 'Title' 'Description' 'BicycleType' 'Brand' 'Price' 'Color' => => => => => => => ['N' => '203'], ['S' => '19-Bike-203'], ['S' => '203 Description'], ['S' => 'Road'], ['S' => 'Brand-Company B'], ['N' => '300'], ['SS' => ['Red', 'Green', 'Black']], 'ProductCategory' => ['S' => 'Bicycle'] ] ], ], [ 'PutRequest' => [ 'Item' => [ 'Id' 'Title' 'Description' 'BicycleType' 'Brand' 'Price' 'Color' API Version 2012-08-10 622 => => => => => => => ['N' => '204'], ['S' => '18-Bike-204'], ['S' => '204 Description'], ['S' => 'Mountain'], ['S' => 'Brand-Company B'], ['N' => '400'], ['SS' => ['Red']], Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – PHP 'ProductCategory' => ['S' => 'Bicycle'] ] ], ], [ 'PutRequest' => [ 'Item' => [ 'Id' 'Title' 'Description' 'BicycleType' 'Brand' 'Price' 'Color' 'ProductCategory' => => => => => => => => ['N' => '205'], ['S' => '20-Bike-205'], ['S' => '205 Description'], ['S' => 'Hybrid'], ['S' => 'Brand-Company C'], ['N' => '500'], ['SS' => ['Red', 'Black']], ['S' => 'Bicycle'] ] ] ] ], ], ]); echo "done.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to load data into $tableName\n"); } $tableName = 'Forum'; echo "Adding data to the $tableName table...\n"; try { $response = $dynamodb->batchWriteItem([ 'RequestItems' => [ $tableName => [ [ 'PutRequest' => [ 'Item' => [ 'Name' => ['S' 'Category' => ['S' 'Threads' => ['N' 'Messages' => ['N' 'Views' => ['N' ] ] ], [ 'PutRequest' => [ 'Item' => [ 'Name' => ['S' 'Category' => ['S' 'Threads' => ['N' ] ] ], ] API Version 2012-08-10 623 => => => => => 'Amazon DynamoDB'], 'Amazon Web Services'], '0'], '0'], '1000'] => 'Amazon S3'], => 'Amazon Web Services'], => '0'] Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – PHP ] ]); echo "done.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to load data into $tableName\n"); } $tableName = 'Thread'; echo "Adding data to the $tableName table...\n"; try { $response = $dynamodb->batchWriteItem([ 'RequestItems' => [ $tableName => [ [ 'PutRequest' => [ 'Item' => [ 'ForumName' 'Subject' 1'], 'Message' message'], 'LastPostedBy' 'LastPostedDateTime' 'Views' 'Replies' 'Answered' 'Tags' 'primarykey', 'table']] ] ], 'PutRequest' => [ 'Item' => [ 'ForumName' 'Subject' 2'], 'Message' message'], 'LastPostedBy' 'LastPostedDateTime' 'Views' 'Replies' 'Answered' 'Tags' 'partitionkey', 'sortkey']] ] ], 'PutRequest' => [ 'Item' => [ 'ForumName' 'Subject' 'Message' message'], 'LastPostedBy' 'LastPostedDateTime' 'Views' 'Replies' API Version 2012-08-10 624 => ['S'=>'Amazon DynamoDB'], => ['S'=> 'DynamoDB Thread => ['S'=>'DynamoDB thread 1 => => => => => => ['S'=>'User A'], ['S'=>$fourteenDaysAgo], ['N'=>'0'], ['N'=>'0'], ['N'=>'0'], ['SS' => ['index', => ['S'=>'Amazon DynamoDB'], => ['S'=> 'DynamoDB Thread => ['S'=>'DynamoDB thread 2 => => => => => => ['S'=>'User A'], ['S'=>$twentyOneDaysAgo], ['N'=>'0'], ['N'=>'0'], ['N'=>'0'], ['SS' => ['index', => ['S'=>'Amazon S3'], => ['S'=> 'S3 Thread 1'], => ['S'=>'S3 Thread 3 => => => => ['S'=>'User A'], ['S'=>$sevenDaysAgo], ['N'=>'0'], ['N'=>'0'], Amazon DynamoDB 開発者ガイド サンプルテーブルの作成とデータのアップロード – PHP 'Answered' 'Tags' => ['N'=>'0'], => ['SS' => ['largeobjects', 'multipart upload']] ] ] ] ] ] ]); echo "done.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to load data into $tableName\n"); } $tableName = 'Reply'; echo "Adding data to the $tableName table...\n"; try { $response = $dynamodb->batchWriteItem([ 'RequestItems' => [ $tableName => [ [ 'PutRequest' => [ 'Item' => [ 'Id' DynamoDB#DynamoDB Thread 1'], 'ReplyDateTime' 'Message' Reply 2 text'], 'PostedBy' ] ] ], [ 'PutRequest' => [ 'Item' => [ 'Id' DynamoDB#DynamoDB Thread 2'], 'ReplyDateTime' 'Message' Reply 3 text'], 'PostedBy' ] ] ], [ 'PutRequest' => [ 'Item' => [ 'Id' DynamoDB#DynamoDB Thread 2'], 'ReplyDateTime' 'Message' Reply 2 text'], 'PostedBy' ] ] ], API Version 2012-08-10 625 => ['S' => 'Amazon => ['S' => $fourteenDaysAgo], => ['S' => 'DynamoDB Thread 1 => ['S' => 'User B'] => ['S' => 'Amazon => ['S' => $twentyOneDaysAgo], => ['S' => 'DynamoDB Thread 2 => ['S' => 'User B'] => ['S' => 'Amazon => ['S' => $sevenDaysAgo], => ['S' => 'DynamoDB Thread 2 => ['S' => 'User A'] Amazon DynamoDB 開発者ガイド AWS SDK for Python(Boto)を使 用したサンプルアプリケーション [ 'PutRequest' => [ 'Item' => [ 'Id' => ['S' => DynamoDB#DynamoDB Thread 2'], 'ReplyDateTime' => ['S' => 'Message' => ['S' => Reply 1 text'], 'PostedBy' => ['S' => ] ] ] ], ] ]); 'Amazon $oneDayAgo], 'DynamoDB Thread 2 'User A'] echo "done.\n"; } catch (DynamoDbException $e) { echo $e->getMessage() . "\n"; exit ("Unable to load data into $tableName\n"); } ?> AWS SDK for Python (Boto) を使用した DynamoDB サンプルアプリケーション: Tic-TacToe トピック • ステップ 1: ローカルにデプロイおよびテストを実行する (p. 627) • ステップ 2: データモデルと実装の詳細を調べる (p. 630) • ステップ 3: DynamoDB サービスを使用して本稼働環境でデプロイする (p. 637) • ステップ 4: リソースをクリーンアップする (p. 644) Tic-Tac-Toe ゲームは、Amazon DynamoDB 上に構築されたサンプルウェブアプリケーションです。 このアプリケーションは AWS SDK for Python (Boto) を使用して、DynamoDB テーブルにゲームデー タを格納するために必要な DynamoDB 呼び出しを行い、Python ウェブフレームワーク Flask を使用 して、データのモデル化の方法を含む DynamoDB でのアプリケーション開発のすべてを示します。 また、DynamoDB でのデータのモデル化に関するベストプラクティスを示します。これには、ゲーム アプリケーション用に作成するテーブル、ユーザーが定義するプライマリキー、クエリ要件に基づい て必要になる追加のインデックス、および連結された属性値の使用が含まれます。 Tic-Tac-Toe アプリケーションは、次のようにしてウェブ上でプレイします。 1. アプリケーションのホームページにログインします。 2. 次に、他のユーザーを対戦相手としてゲームに招待します。 他のユーザーが招待を受け入れるまで、ゲームのステータスは PENDING となります。対戦相手が 招待を受け入れると、ステータスは IN_PROGRESS に変わります。 3. ゲームは、対戦相手がログインして招待を受け入れてから開始されます。 4. アプリケーションはゲームのすべての動きやステータス情報を DynamoDB テーブルに格納しま す。 API Version 2012-08-10 626 Amazon DynamoDB 開発者ガイド ステップ 1: ローカルにデプロイおよびテストを実行する 5. ゲームは優勝または引き分けで終わり、これによりゲームのステータスは FINISHED に設定されま す。 アプリケーション構築についてすべて網羅した演習を各ステップで示します。 • ステップ 1: ローカルにデプロイおよびテストを実行する (p. 627) - このセクションでは、アプリ ケーションをローカルコンピュータにダウンロード、デプロイ、およびテストします。DynamoDB のダウンロード可能バージョンで、必要なテーブルを作成します。 • ステップ 2: データモデルと実装の詳細を調べる (p. 630) - このセクションでは、最初にインデッ クスと連結属性値の使用を含めて、データモデルについて詳細に説明します。次に、アプリケー ションの動作について説明します。 • ステップ 3: DynamoDB サービスを使用して本稼働環境でデプロイする (p. 637) – このセクショ ンでは、本稼働環境でのデプロイの考慮事項について説明します。このステップでは、Amazon DynamoDB サービスを使用してテーブルを作成し、AWS Elastic Beanstalk を使用してアプリケー ションをデプロイします。本稼働環境にアプリケーションがある場合は、アプリケーションが DynamoDB テーブルにアクセスできるように、適切なアクセス許可を付与します。このセクション の手順では、本稼働デプロイについて詳細に説明します。 • ステップ 4: リソースをクリーンアップする (p. 644) – このセクションでは、この例で説明されて いない分野を取り上げます。また、料金が発生しないようにするため、前のステップで作成した AWS リソースを削除するためのステップについても説明します。 ステップ 1: ローカルにデプロイおよびテストを実 行する トピック • 1.1: 必要なパッケージのダウンロードとインストール (p. 627) • 1.2: ゲームアプリケーションをテストする (p. 628) このステップでは、Tic-Tac-Toe ゲームアプリケーションをローカルコンピュータにダウンロー ド、デプロイ、およびテストします。Amazon DynamoDB ウェブサービスを使用する代わり に、DynamoDB をコンピュータにダウンロードして必要なテーブルを作成します。 1.1: 必要なパッケージのダウンロードとインストール このアプリケーションをローカルでテストするには、次のものが必要です。 • Python • Flask(Python 用のマイクロフレームワーク) • AWS SDK for Python(Boto) • コンピュータ上で実行される DynamoDB • Git これらのツールを入手するには、以下の作業を実行します。 1. Python をインストールします。詳しい手順については、「Python のダウンロード」を参照してく ださい。 Tic-Tac-Toe アプリケーションは、Python バージョン 2.7 を使用してテスト済みです。 2. Python パッケージインストーラ(PIP)を使用して Flask および AWS SDK for Python(Boto)を インストールします。 • PIP をインストールします。 API Version 2012-08-10 627 Amazon DynamoDB 開発者ガイド ステップ 1: ローカルにデプロイおよびテストを実行する 手順については、「PIP のインストール」を参照してください。インストールページで、[getpip.py] リンクを選択して、ファイルを保存します。次に、管理者としてコマンドターミナルを開 き、コマンドプロンプトで以下のように入力します。 python.exe get-pip.py Linux では、.exe 拡張子を指定しません。python get-pip.py のみを指定します。 • PIP で、次に示すコードを使用して Flask と Boto パッケージをインストールします。 pip install Flask pip install boto pip install configparser 3. DynamoDB をコンピュータにダウンロードします。その実行方法については、「DynamoDB (ダウ ンロード可能バージョン) のセットアップ (p. 44)」を参照してください。 4. Tic-Tac-Toe アプリケーションをダウンロードします。 a. Git をインストールします。手順については、「Git のダウンロード」を参照してください。 b. アプリケーションをダウンロードするには、次のコードを実行します。 git clone https://github.com/awslabs/dynamodb-tictactoe-example-app.git 1.2: ゲームアプリケーションをテストする Tic-Tac-Toe アプリケーションをテストするには、ローカルコンピュータで DynamoDB を実行する必 要があります。 Tic-Tac-Toe アプリケーションを実行するには 1. DynamoDB を起動します。 2. Tic-Tac-Toe アプリケーション用のウェブサーバーを起動します。 そのためには、コマンドターミナルを開き、Tic-Tac-Toe アプリケーションをダウンロードした フォルダに移動し、次に示すコードを使用してアプリケーションをローカルに実行します。 python.exe application.py --mode local --serverPort 5000 --port 8000 Linux では、.exe 拡張子を指定しません。 3. ウェブブラウザを開き、次のように入力します。 http://localhost:5000/ ブラウザにホームページが表示されます。 API Version 2012-08-10 628 Amazon DynamoDB 開発者ガイド ステップ 1: ローカルにデプロイおよびテストを実行する 4. [Log in] ボックスに「user1」と入力し、user1 としてログインします。 Note このサンプルアプリケーションは、ユーザー認証を実行しません。ユーザー ID のみがプ レーヤーを識別するために使用されます。2 人のプレーヤーが同じエイリアスでログイン すると、アプリケーションは 2 つの別のブラウザでプレイしているかのように動作しま す。 5. 初めてゲームを実行する場合、DynamoDB で必要なテーブル(Games)を作成するようにリクエ ストするページが表示されます。[CREATE TABLE] を選択します。 6. [CREATE] を選択して、最初の Tic-Tac-Toe ゲームを作成します。 7. [Choose an Opponent] ボックスに「user2」と入力し、[Create Game!] を選択します。 この操作を行うと、Games テーブルに項目を追加してゲームが作成されます。これにより、ゲー ムのステータスが PENDING に設定されます。 8. 別のブラウザウィンドウを開き、次のように入力します。 http://localhost:5000/ ブラウザは Cookie を通じて情報を渡すので、Cookie を引き継がないように、匿名モードまたは プライベートブラウジングを使用します。 9. user2 としてログインします。 API Version 2012-08-10 629 Amazon DynamoDB 開発者ガイド ステップ 2: データモデルと実装の詳細を調べる user1 からの保留中の招待を示すページが表示されます。 10. [accept] を選択して招待を受け入れます。 ゲームページが、空の Tic-Tac-Toe グリッドとともに表示されます。このページには、ゲーム ID、誰の番か、ゲームのステータスなど、関連するゲーム情報も表示されます。 11. ゲームをプレイします。 ユーザーが動くたびに、ウェブサービスは Games テーブルのゲーム項目を条件付きで更新するリク エストを DynamoDB に送信します。たとえば、条件により、動きが有効で、ユーザーが選択した四 角形が利用可能で、動いたユーザーの番であったことを確認できます。動きが有効な場合、更新操作 により、ボードでの選択に対応する新しい属性が追加されます。また、既存の属性値が、次に動くこ とができるユーザーに設定されます。 アプリケーションは、ゲームページで非同期 JavaScript 呼び出しを毎秒行い、最大 5 分にわた り、DynamoDB のゲーム状態が変わったかどうかを確認します。変わった場合、アプリケーション は新しい情報でページを更新します。5 分後に、アプリケーションはリクエストを中止します。ユー ザーはページを更新して、更新された情報を取得する必要があります。 ステップ 2: データモデルと実装の詳細を調べる トピック • 2.1: 基本的なデータモデル (p. 630) • 2.2: 実行中のアプリケーション(コードのウォークスルー) (p. 632) 2.1: 基本的なデータモデル このサンプルアプリケーションでは、次の DynamoDB データモデルの概念を説明します。 API Version 2012-08-10 630 Amazon DynamoDB 開発者ガイド ステップ 2: データモデルと実装の詳細を調べる • テーブル – DynamoDB では、テーブルは項目(レコード)の集合であり、各項目は属性と呼ばれる 名前と値のペアの集合です。 この Tic-Tac-Toe の例では、アプリケーションは、Games テーブル内のすべてのゲームデータを格 納します。アプリケーションはゲームごとにテーブルで 1 つの項目を作成し、すべてのゲームデー タを属性として格納します。Tic-Tac-Toe ゲームでは最大 9 回の移動が可能です。DynamoDB テー ブルは、プライマリキーのみが必須属性である場合はスキーマを持たないので、アプリケーション は 1 ゲーム項目あたり異なる数の属性を格納できます。 Games テーブルには、文字列型の 1 つの属性 GameId で構成されるシンプルなプライマリキーが あります。アプリケーションは各ゲームに一意の ID を割り当てます。DynamoDB プライマリキー の詳細については、「プライマリキー (p. 5)」を参照してください。 ユーザーが他のユーザーを招待して Tic-Tac-Toe ゲームを開始すると、アプリケーションは、次の ようなゲームメタデータを格納する属性で、Games テーブルに新しい項目を作成します。 • ゲームを開始したユーザーである HostId。 • ゲームに招待されたユーザーである Opponent。 • プレイする番のユーザー。最初にゲームを開始したユーザー。 • ボードで O 記号を使用するユーザー。ゲームを開始するユーザーは O 記号を使用します。 さらに、アプリケーションは StatusDate 連結属性を作成し、ゲームの初期状態を PENDING とし てマークします。次のスクリーンショットは、DynamoDB コンソールに表示されるサンプル項目を 示しています。 アプリケーションは、ゲームの進行に合わせて、ゲームで動きがあるたびに 1 つの属性をテーブル に追加します。属性名はボードの位置(TopLeft、BottomRight など)です。たとえば、動きに は値 Oの TopLeft 属性、値 O の TopRight 属性、および値 Xの BottomRight 属性があるなどで す。属性値は、動いたユーザーに応じて、O または X になります。たとえば、次のボードを考えて みます。 • 連結属性値 – StatusDate 属性が、連結値属性を示します。この手法では、ゲームのステータス (PENDING、IN_PROGRESS、FINISHED)および日付(最後の動き)を格納する個別の属性を作成 API Version 2012-08-10 631 Amazon DynamoDB 開発者ガイド ステップ 2: データモデルと実装の詳細を調べる する代わりに、IN_PROGRESS_2014-04-30 10:20:32 などの単一の属性としてそれらを組み合わ せます。 次に、アプリケーションは、インデックスのソートキーとして StatusDate を指定して、セカンダ リインデックスの作成で StatusDate 属性を使用します。StatusDate 連結値属性を使用する利点 について、さらに次のインデックスの説明で示します。 • グローバルセカンダリインデックス - テーブルのプライマリキー GameId を使用すると、テーブル を効率的に照会してゲーム項目を検索できます。プライマリキー属性以外の属性でテーブルを照会 するため、DynamoDB はセカンダリインデックスの作成をサポートしています。このサンプルアプ リケーションでは、次の 2 つのセカンダリインデックスを構築します。 • HostId-StatusDate-index. このインデックスはパーティションキーとして HostId を、ソートキー として StatusDate を持ちます。このインデックスを使用して、たとえば特定のユーザーによっ てホストされたゲームを検索するなど、HostId でクエリを実行できます。 • OpponentId-StatusDate-index. このインデックスはパーティションキーとして OpponentId を、 ソートキーとして StatusDate を持ちます。たとえば、特定のユーザーが対戦相手であるゲーム を検索するなど、このインデックスを使用して Opponent でクエリを実行できます。 これらのインデックスは、グローバルセカンダリインデックスと呼ばれます。これは、インデック スのパーティションキーが、テーブルのプライマリキーで使用されるパーティションキー (GameId) とは同じでないためです。 両方のインデックスがソートキーとして StatusDate を指定することに注意してください。これを 行うと、次のことが可能になります。 • BEGINS_WITH 比較演算子を使用してクエリを実行できます。たとえば、特定のユーザー によってホストされた IN_PROGRESS 属性を持つすべてのゲームを検索できます。この場 合、BEGINS_WITH 演算子は、IN_PROGRESS で始まる StatusDate 値を確認します。 • DynamoDB は、インデックスでソートキー値によってソートして項目を保存します。したがっ て、すべてのステータスのプレフィックスは同じ(たとえば、IN_PROGRESS)になり、日付部 分に使用される ISO 形式には、最も古いものから最も新しいものの順にソートされた項目が含ま れます。この手法により、たとえば次のように特定のクエリを効率的に実行できるようになりま す。 • ログインしているユーザーによってホストされている最新の IN_PROGRESS のゲームを最大 10 個取得します。このクエリでは、HostId-StatusDate-index インデックスを指定します。 • ログインしているユーザーが対戦相手である最新の IN_PROGRESS のゲームを最大 10 個取得 します。このクエリでは、OpponentId-StatusDate-index インデックスを指定します。 セカンダリインデックスの詳細については、「セカンダリインデックスを使用したデータアクセス性 の向上 (p. 333)」を参照してください。 2.2: 実行中のアプリケーション(コードのウォークスルー) このアプリケーションには 2 つのメインページがあります。 API Version 2012-08-10 632 Amazon DynamoDB 開発者ガイド ステップ 2: データモデルと実装の詳細を調べる • ホームページ – このページには、簡単なログイン、新しい Tic-Tac-Toe ゲームを作成する [CREATE] ボタン、進行中のゲームのリスト、ゲームの履歴、およびアクティブな保留中のゲーム の招待が表示されます。 ホームページは自動的に更新されません。リストを更新するには、ユーザーがページを更新する必 要があります。 • ゲームページ - このページには、ユーザーがプレイする Tic-Tac-Toe グリッドが表示されます。 アプリケーションは、毎秒ゲームページを自動的に更新します。ブラウザの JavaScript が毎秒 Python ウェブサーバーを呼び出して、テーブルのゲーム項目が変更されたかどうかを Games テー ブルに照会します。変更された場合、JavaScript はページ更新をトリガーし、更新されたボードが ユーザーに表示されるようにします。 アプリケーションの動作について詳細に説明します。 ホームページ ユーザーがログインすると、アプリケーションには、以下の 3 つの情報のリストが表示されます。 • 招待 – このリストには、ログインしているユーザーが受け入れを保留中の、他のユーザーからの最 新の招待が最大 10 個表示されます。前のスクリーンショットで、user1 は user5 および user2 から の招待を保留中です。 • 進行中のゲーム - このリストには、進行中の最新のゲームが最大 10 個表示されます。これらは、 ユーザーがアクティブに実行中のゲームで、そのステータスは IN_PROGRESS です。スクリーン ショットでは、user1 は user3 および user4 と Tic-Tac-Toe ゲームをアクティブにプレイ中です。 • 最近の履歴 – このリストには、ユーザーが終了した最近のゲームが最大 10 個表示されます。その ステータスは FINISHED です。スクリーンショットに示したゲームで、user1 は以前に user2 とプ レイしています。完了した各ゲームについて、ゲームの結果がリストに表示されます。 コードで、index 関数は(application.py で)次の 3 つの呼び出しを行い、ゲームのステータス 情報を取得します。 inviteGames = controller.getGameInvites(session["username"]) inProgressGames = controller.getGamesWithStatus(session["username"], "IN_PROGRESS") finishedGames = controller.getGamesWithStatus(session["username"], "FINISHED") これらは呼び出しはそれぞれ、Game オブジェクトでラップされた、DynamoDB からの項目のリスト を返します。ビューでこれらのオブジェクトからデータを抽出することは簡単です。インデックス関 数は、HTML を表示するため、これらのオブジェクトリストをビューに渡します。 API Version 2012-08-10 633 Amazon DynamoDB 開発者ガイド ステップ 2: データモデルと実装の詳細を調べる return render_template("index.html", user=session["username"], invites=inviteGames, inprogress=inProgressGames, finished=finishedGames) Tic-Tac-Toe アプリケーションは、主に DynamoDB から取得したゲームデータを格納するた め、Game クラスを定義します。これらの関数は、Amazon DynamoDB 項目に関連するコードからア プリケーションの他の部分を分離できるようにする Game オブジェクトのリストを返します。これら の関数により、このようにしてデータストア層の詳細からアプリケーションコードを切り離すことが できます。 ここで説明するアーキテクチャーパターンは、model-view-controller(MVC)UI パターンとも呼 ばれます。この場合、Game オブジェクトのインスタンス(データを表す)はモデルで、HTML ページはビューです。コントローラーは 2 つのファイルに分割されます。application.py ファイルには Flask フレームワーク用のコントローラーロジックがあり、ビジネスロジックは gameController.py ファイルに分離されます。つまり、アプリケーションは、DynamoDB SDK で 行う必要があるすべてを、dynamodb フォルダの独自の個別ファイルに格納します。 3 つの関数と、それらが該当データを取得するためにグローバルセカンダリインデックスを使用して Games テーブルを照会する方法について説明します。 getGameInvites を使用した保留中のゲームの招待リストの取得 getGameInvites 関数は保留中の最新の 10 個の招待リストを取得します。これらのゲームはユー ザーによって作成されましたが、対戦相手はゲームの招待を受け入れていません。これらのゲームの 場合、対戦相手が招待を受け入れるまでステータスは PENDING のままになります。対戦相手が招待 を辞退した場合、アプリケーションは、対応する項目をテーブルから削除します。 関数は、以下のようなクエリを指定します。 • 関数は、以下のキー値および比較演算子とともに使用する OpponentId-StatusDate-index イン デックスを指定します。 • パーティションキーは OpponentId で、インデックスキー user ID を受け取ります。 • ソートキーは StatusDate で、比較演算子およびインデックスキー値 beginswith="PENDING_" を受け取ります。 OpponentId-StatusDate-index インデックスを使用して、ログインしたユーザーが招待される ゲーム(ログインしたユーザーが対戦相手であるゲーム)を取得します。 • クエリは結果を 10 項目に制限します。 gameInvitesIndex = self.cm.getGamesTable().query( Opponent__eq=user, StatusDate__beginswith="PENDING_", index="OpponentId-StatusDateindex", limit=10) インデックスで、DynamoDB は OpponentId (パーティションキー) ごとに、StatusDate (ソート キー) でソートして項目を保持します。そのため、クエリが返すゲームは最新の 10 個のゲームになり ます。 getGamesWithStatus を使用した特定のステータスのゲームリストの取得 対戦相手がゲームの招待を受け入れると、ゲームのステータスは IN_PROGRESS に変わります。ゲー ムが完了すると、ステータスは FINISHED に変わります。 API Version 2012-08-10 634 Amazon DynamoDB 開発者ガイド ステップ 2: データモデルと実装の詳細を調べる 進行中または終了済みのゲームを検索するクエリは、ステータス値が異なる場合を除いて同じです。 したがって、アプリケーションは getGamesWithStatus 関数を定義し、この関数はステータス値を パラメータとして受け取ります。 inProgressGames = controller.getGamesWithStatus(session["username"], "IN_PROGRESS") finishedGames = controller.getGamesWithStatus(session["username"], "FINISHED") 次のセクションでは進行中のゲームについて説明しますが、終了済みのゲームにも同じ説明が当ては まります。 特定のユーザーの進行中のゲームのリストには、次の両方が含まれます。 • ユーザーによってホストされた進行中のゲーム • ユーザーが対戦相手である進行中のゲーム getGamesWithStatus 関数は、毎回適切なセカンダリインデックスを使用して次の 2 つのクエリを 実行します。 • この関数は HostId-StatusDate-index インデックスを使用して Games テーブルを照会しま す。インデックスについて、クエリでは比較演算子とともにプライマリキーの値 (パーティション キー (HostId) およびソートキー (StatusDate) の値の両方) を指定します。 hostGamesInProgress = self.cm.getGamesTable ().query(HostId__eq=user, StatusDate__beginswith=status, index="HostId-StatusDateindex", limit=10) 比較演算子の Python の構文に注意してください。 • HostId__eq=user は等価比較演算子を指定します。 • StatusDate__beginswith=status は BEGINS_WITH 比較演算子を指定します。 • この関数は OpponentId-StatusDate-index インデックスを使用して Games テーブルを照会し ます。 oppGamesInProgress = self.cm.getGamesTable().query(Opponent__eq=user, StatusDate__beginswith=status, index="OpponentId-StatusDateindex", limit=10) • 次に、この関数は 2 つのリストを組み合わせ、ソートし、最初の 0~10 項目について Game オブ ジェクトのリストを作成して、呼び出し元関数(インデックス)にリストを返します。 games = self.mergeQueries(hostGamesInProgress, oppGamesInProgress) return games API Version 2012-08-10 635 Amazon DynamoDB 開発者ガイド ステップ 2: データモデルと実装の詳細を調べる ゲームページ ゲームページは、ユーザーが Tic-Tac-Toe ゲームをプレイする場所です。このページには、ゲームの 関連情報とともに、ゲームグリッドが表示されます。次のスクリーンショットは、進行中のサンプル ゲームを示しています。 アプリケーションは次の状況でゲームページを表示します。 • ユーザーは他のユーザーを招待してゲームを作成します。 この場合、ページはホストやゲームのステータスを PENDING としてユーザーに表示し、対戦相手 が受け入れるのを待ちます。 • ユーザーは、ホームページで保留中の招待の 1 つを受け入れます。 この場合、ページではユーザーは対戦相手として、ゲームのステータスは IN_PROGRESS として表 示されます。 ボード上でのユーザーによる選択操作により、アプリケーションへのフォーム POST リクエ ストが生成されます。つまり、Flask は HTML フォームデータとともに selectSquare 関数 を(application.py で)呼び出します。次に、この関数は updateBoardAndTurn 関数を (gameController.py で)呼び出して、次のようにゲーム項目を更新します。 • これにより、動きに固有の新しい属性が追加されます。 • Turn 属性が、次の番のユーザーに更新されます。 controller.updateBoardAndTurn(item, value, session["username"]) 項目の更新が成功した場合、関数は true を返します。それ以外の場合は、false を返しま す。updateBoardAndTurn 関数について、以下の点に注意してください。 • この関数は、既存の項目に対する更新の一定のセットを作成するため、AWS SDK for Python の update_item 関数を呼び出します。この関数は、DynamoDB の UpdateItem オペレーションに対 応します。詳細については、「UpdateItem」を参照してください。 Note UpdateItem オペレーションと PutItem オペレーションの違いは、PutItem が項目全体 を置き換えることです。詳細については、「PutItem」を参照してください。 API Version 2012-08-10 636 Amazon DynamoDB 開発者ガイド ステップ 3: 本稼働環境でのデプロイ update_item 呼び出しでは、コードは以下を識別します。 • Games テーブルのプライマリキー(ItemId)。 key = { "GameId" : { "S" : gameId } } • 現在のユーザーの動きに固有の、追加する新しい属性とその値(例: TopLeft="X")。 attributeUpdates = { position : { "Action" : "PUT", "Value" : { "S" : representation } } } • 更新が実行されるために満たされる必要がある条件 • ゲームは進行中である必要があります。つまり、StatusDate 属性値は IN_PROGRESS で始まる 必要があります。 • 現在の番は、Turn 属性で指定されている有効なユーザーの番である必要があります。 • ユーザーが選択した四角形は使用可能である必要があります。つまり、四角形に対応する属性は 存在していてはなりません。 expectations = {"StatusDate" : {"AttributeValueList": [{"S" : "IN_PROGRESS_"}], "ComparisonOperator": "BEGINS_WITH"}, "Turn" : {"Value" : {"S" : current_player}}, position : {"Exists" : False}} ここで、関数は update_item を呼び出して項目を更新します。 self.cm.db.update_item("Games", key=key, attribute_updates=attributeUpdates, expected=expectations) 関数に戻ると、selectSquare 関数呼び出しは次の例に示すようにリダイレクトされます。 redirect("/game="+gameId) この呼び出しにより、ブラウザが更新されます。この更新の一環として、アプリケーションはゲーム が優勝または引き分けで終了したかどうかを確認します。終了した場合、アプリケーションはそれに 応じてゲーム項目を更新します。 ステップ 3: DynamoDB サービスを使用して本稼働 環境でデプロイする トピック • 3.1: Amazon EC2 向けの IAM ロールを作成する (p. 639) • 3.2: Amazon DynamoDB での Games テーブルの作成 (p. 639) • 3.3: Tic-Tac-Toe アプリケーションコードのバンドルとデプロイ (p. 639) • 3.4: AWS Elastic Beanstalk 環境のセットアップ (p. 641) API Version 2012-08-10 637 Amazon DynamoDB 開発者ガイド ステップ 3: 本稼働環境でのデプロイ 前のセクションでは、DynamoDB Local を使用してコンピュータでローカルに Tic-Tac-Toe アプリ ケーションをデプロイし、テストしました。ここでは、次のようにして本稼働環境でアプリケーショ ンをデプロイします。 • ウェブアプリケーションやサービスをデプロイ、スケーリングするための使いやすいサービスであ る Elastic Beanstalk を使用して、アプリケーションをデプロイします。詳細については、「AWS Elastic Beanstalk への Flask アプリケーションのデプロイ」を参照してください。 Elastic Beanstalk は 1 つ以上の Amazon Elastic Compute Cloud(Amazon EC2)インスタンスを起 動します。これは、Tic-Tac-Toe アプリケーションが実行される Elastic Beanstalk を通じて設定し ます。 • Amazon DynamoDB サービスを使用して、コンピュータにローカルに存在するのではなく、AWS に存在する Games テーブルを作成します。 さらに、アクセス許可も設定する必要があります。DynamoDB の Games テーブルなど、作成する AWS リソースは、デフォルトでプライベートになります。リソース所有者(Games テーブルを作 成した AWS アカウント)のみが、このテーブルにアクセスできます。したがって、デフォルトでは Tic-Tac-Toe アプリケーションは Games テーブルを更新することはできません。 必要なアクセス許可を付与するには、AWS Identity and Access Management(IAM)のロールを作成 し、Games テーブルへのアクセス許可をこのロールに付与します。Amazon EC2 インスタンスは最 初にこのロールを引き受けます。AWS は、その応答として Tic-Tac-Toe アプリケーションに代わって Amazon EC2 インスタンスが Games テーブルを更新するために使用できる一時的なセキュリティ認 証情報を返します。Elastic Beanstalk アプリケーションを設定するときは、Amazon EC2 インスタン スが引き受けることができる IAM ロールを指定します。IAM ロールの詳細については、『Linux イン スタンス用 Amazon EC2 ユーザーガイド』の「Amazon EC2 向けの IAM ロール」を参照してくださ い。 Note Tic-Tac-Toe 用の Amazon EC2 インスタンスを作成する前に、Elastic Beanstalk がインスタ ンスを作成する AWS リージョンを最初に決定する必要があります。Elastic Beanstalk アプ リケーションを作成したら、設定ファイルで同じリージョン名とエンドポイントを指定しま す。Tic-Tac-Toe アプリケーションはこのファイルの情報を使用して Games テーブルを作成 し、それ以降のリクエストを特定の AWS リージョンに送信します。DynamoDB Games テー ブルと Elastic Beanstalk が起動する Amazon EC2 インスタンスの両方は、同じ AWS リー ジョンにある必要があります。使用可能なリージョンのリストについては、『アマゾン ウェ ブ サービス全般のリファレンス』の「Amazon DynamoDB 」を参照してください。 要約すると、Tic-Tac-Toe アプリケーションを本稼働環境にデプロイするには、以下の作業を行いま す。 1. AWS IAM サービスを使用して IAM ロールを作成します。DynamoDB アクションが Games テーブ ルにアクセスするためのアクセス許可を付与するポリシーを、このロールにアタッチします。 2. Tic-Tac-Toe アプリケーションコードおよび設定ファイルをバンドルし、.zip ファイルを作成しま す。この .zip ファイルを使用して、サーバーに配置する Tic-Tac-Toe アプリケーションコードを Elastic Beanstalk に渡します。バンドル作成の詳細については、『AWS Elastic Beanstalk 開発者ガ イド』の「アプリケーションソースバンドルを作成する」を参照してください。 設定ファイル(beanstalk.config)で、AWS リージョンおよびエンドポイント情報を指定しま す。Tic-Tac-Toe アプリケーションは、この情報を使用して、通信する DynamoDB リージョンを決 定します。 3. Elastic Beanstalk 環境をセットアップします。Elastic Beanstalk は 1 つ以上の Amazon EC2 インス タンスを起動して、Tic-Tac-Toe アプリケーションバンドルをそれらのインスタンス上でデプロイ します。Elastic Beanstalk 環境の準備が整ったら、CONFIG_FILE 環境変数を追加して設定ファイ ル名を指定します。 API Version 2012-08-10 638 Amazon DynamoDB 開発者ガイド ステップ 3: 本稼働環境でのデプロイ 4. DynamoDB テーブルを作成します。Amazon DynamoDB サービスを使用して、コンピュータ上 にローカルにではなく AWS 上に Games テーブルを作成します。このテーブルは、文字列型の GameId パーティションキーで構成されたシンプルなプライマリキーを持ちます。 5. 本稼働環境でゲームをテストします。 3.1: Amazon EC2 向けの IAM ロールを作成する Amazon EC2 型の IAM ロールを作成すると、Tic-Tac-Toe アプリケーションを実行中の Amazon EC2 インスタンスは正しい IAM ロールを引き受け、Games テーブルにアクセスするアプリケーションリ クエストを行えるようになります。ロールを作成するときに、[Custom Policy] オプションを選択し、 次のポリシーをコピーして貼り付けます。 { "Version":"2012-10-17", "Statement":[ { "Action":[ "dynamodb:ListTables" ], "Effect":"Allow", "Resource":"*" }, { "Action":[ "dynamodb:*" ], "Effect":"Allow", "Resource":[ "arn:aws:dynamodb:us-west-2:922852403271:table/Games", "arn:aws:dynamodb:us-west-2:922852403271:table/Games/index/*" ] } ] } 詳細な手順については、『IAM ユーザーガイド』の「AWS サービス用のロールを作成する (AWS Management Console)」を参照してください。 3.2: Amazon DynamoDB での Games テーブルの作成 DynamoDB の Games テーブルはゲームデータを格納します。テーブルが存在しない場合、アプリ ケーションによって自動的にテーブルが作成されます。この例では、アプリケーションで Games テーブルを作成します。 3.3: Tic-Tac-Toe アプリケーションコードのバンドルとデプロ イ この例のステップを実行した場合、既に Tic-Tac-Toe アプリケーションをダウンロードしています。 そうでない場合は、アプリケーションをダウンロードし、すべてのファイルをローカルコンピュータ 上のフォルダに展開します。手順については、「ステップ 1: ローカルにデプロイおよびテストを実行 する (p. 627)」を参照してください。 すべてのファイルを展開すると、code フォルダが作成されます。このフォルダを Electric Beanstalk に渡すには、このフォルダのコンテンツを .zip ファイルとしてバンドルします。最初に、そのフォ ルダに設定ファイルを追加する必要があります。アプリケーションは、リージョンとエンドポイント API Version 2012-08-10 639 Amazon DynamoDB 開発者ガイド ステップ 3: 本稼働環境でのデプロイ 情報を使用して、指定されたリージョンで DynamoDB テーブルを作成し、指定されたエンドポイン トを使用して、それ以降のテーブルオペレーションのリクエストを行います。 1. Tic-Tac-Toe アプリケーションをダウンロードしたフォルダに切り替えます。 2. アプリケーションのルートフォルダで、次のコンテンツを使用して beanstalk.config という 名前のテキストファイルを作成します。 [dynamodb] region=<AWS region> endpoint=<DynamoDB endpoint> たとえば、次のコンテンツを使用します。 [dynamodb] region=us-west-2 endpoint=dynamodb.us-west-2.amazonaws.com 利用可能なリージョンのリストについては、『アマゾン ウェブ サービス全般のリファレンス』の 「Amazon DynamoDB」を参照してください。 Important 設定ファイルで指定されたリージョンは、Tic-Tac-Toe アプリケーションが DynamoDB で Games テーブルを作成する場所です。次のセクションで説明する Elastic Beanstalk ア プリケーションを、同じリージョンで作成する必要があります。 Note Elastic Beanstalk アプリケーションを作成するときは、環境タイプを選択できる環境を起 動するようにリクエストします。Tic-Tac-Toe サンプルアプリケーションをテストするに は、[Single Instance] 環境タイプを選択し、それ以降をスキップして、次のステップに進 みます。 ただし、[Load balancing, autoscaling] 環境タイプでは、高可用性でスケーラブルな環境 が提供されます。これは、他のアプリケーションを作成、デプロイする場合に検討して ください。この環境タイプを選択する場合、UUID を生成し、次に示すように設定ファイ ルに追加する必要があります。 [dynamodb] region=us-west-2 endpoint=dynamodb.us-west-2.amazonaws.com [flask] secret_key= 284e784d-1a25-4a19-92bf-8eeb7a9example クライアント/サーバー通信でサーバーが応答を送信するときは、セキュリティのため、 サーバーは、クライアントが次のリクエストでサーバーに送り返す署名済み Cookie を送 信します。サーバーが 1 台のみの場合、サーバーは、起動時にローカルに暗号化キーを 生成できます。多くのサーバーがある場合、それらのサーバーはすべて同じ暗号化キー を知る必要があります。そうしない場合、ピアサーバーによって設定された Cookie を読 み取ることができません。secret_key を設定ファイルに追加することで、この暗号化 キーを使用するようにすべてのサーバーに伝えます。 3. アプリケーションのルートフォルダのコンテンツ(beanstalk.config ファイルを含む)を、 たとえば TicTacToe.zip のように zip ファイルとしてバンドルします。 API Version 2012-08-10 640 Amazon DynamoDB 開発者ガイド ステップ 3: 本稼働環境でのデプロイ 4. Amazon Simple Storage Service(Amazon S3)バケットに .zip ファイルをアップロードしま す。次のセクションでは、この .zip ファイルを、1 つ以上のサーバーにアップロードするため に Elastic Beanstalk に渡します。 Amazon S3 バケットにアップロードする方法の手順については、『Amazon Simple Storage Service 入門ガイド』の「バケットの作成」および「バケットへのオブジェクトの追加」トピック を参照してください。 3.4: AWS Elastic Beanstalk 環境のセットアップ このステップでは、環境を含むコンポーネントの集合である Elastic Beanstalk アプリケーションを作 成します。この例では、1 つの Amazon EC2 インスタンスを起動して、Tic-Tac-Toe アプリケーショ ンをデプロイ、実行します。 1. 環境をセットアップするには、次のカスタム URL を入力して Elastic Beanstalk コンソールを セットアップします。 https://console.aws.amazon.com/elasticbeanstalk/?region=<AWS-Region>#/ newApplication ?applicationName=TicTacToeyour-name &solutionStackName=Python &sourceBundleUrl=https://s3.amazonaws.com/<bucket-name>/TicTacToe.zip &environmentType=SingleInstance &instanceType=t1.micro カスタム URL の詳細については、『AWS Elastic Beanstalk 開発者ガイド』の「Launch Now URL の作成」を参照してください。URL については、次の点に注意してください。 • (設定ファイルで指定したものと同じ)AWS リージョン名、Amazon S3 バケット名、および オブジェクト名を指定する必要があります。 • テストでは、URL は SingleInstance 環境タイプ、および t1.micro をインスタンスタイプとして リクエストします。 • アプリケーション名は一意である必要があります。そのため、前の URL で は、applicationName の前に名前を追加することをお勧めします。 この操作を行うと、Elastic Beanstalk コンソールが開きます。場合によっては、サインインが必 要にあることがあります。 2. Elastic Beanstalk コンソールで、[Review and Launch] を選択し、[Launch] を選択します。 3. 今後の参照用に URL を書き留めてください。この URL により、Tic-Tac-Toe アプリケーション のホームページが開きます。 4. Tic-Tac-Toe アプリケーションを設定し、設定ファイルの場所を指定します。 Elastic Beanstalk がアプリケーションを作成したら、[Configuration] を選択します。 API Version 2012-08-10 641 Amazon DynamoDB 開発者ガイド ステップ 3: 本稼働環境でのデプロイ a. 次のスクリーンショットに示すように、[Software Configuration] の横にある歯車のボックス を選択します。 b. [Environment Properties] セクションの最後で、「CONFIG_FILE」とその値 「beanstalk.config」を入力し、[Save] を選択します。 この環境の更新が完了するには数分かかる場合があります。 更新が完了したら、ゲームをプレイできます。 5. ブラウザで、前のステップでコピーした URL を、以下の例に示すように入力します。 http://<pen-name>.elasticbeanstalk.com これにより、アプリケーションのホームページが開きます。 API Version 2012-08-10 642 Amazon DynamoDB 開発者ガイド ステップ 3: 本稼働環境でのデプロイ 6. testuser1 としてログインし、[CREATE] を選択して新しい Tic-Tac-Toe ゲームを開始します。 7. [Choose an Opponent] ボックスに「testuser2」と入力します。 8. 別のブラウザウィンドウを開きます。 ブラウザウィンドウのすべての Cookie を消去し、同じユーザーとしてログインしないようにし ます。 9. 以下の例に示すように、同じ URL を入力してアプリケーションのホームページを開きます。 http://<env-name>.elasticbeanstalk.com 10. testuser2 としてログインします。 11. 保留中の招待のリストで、testuser1 からの招待に対して [accept] を選択します。 12. ゲームページが表示されます。 API Version 2012-08-10 643 Amazon DynamoDB 開発者ガイド ステップ 4: リソースをクリーンアップする testuser1 と testuser2 の両者がゲームをプレイできます。動きがあるごとに、アプリケーション は Games テーブルの対応する項目に動きを保存します。 ステップ 4: リソースをクリーンアップする これで Tic-Tac-Toe アプリケーションのデプロイとテストを完了しました。このアプリケーション は、ユーザー認証を除いて、Amazon DynamoDB でのウェブアプリケーション開発をすべて網羅して います。このアプリケーションは、ゲームの作成時にプレーヤーの名前を追加するためにのみ、ホー ムページのログイン情報を使用します。本稼働アプリケーションでは、ユーザーログインおよび認証 を実行するために必要なコードを追加します。 テストを終了したら、料金が発生しないようにするため、Tic-Tac-Toe アプリケーションのテスト用 に作成したリソースを削除できます。 作成したリソースを削除するには 1. DynamoDB で作成した Games テーブルを削除します。 2. 3. Elastic Beanstalk 環境を終了し、Amazon EC2 インスタンスを解放します。 作成した IAM ロールを削除します。 4. Amazon S3 で作成したオブジェクトを削除します。 DynamoDB 用の追加のツールとリソース トピック • Amazon DynamoDB Storage Backend for Titan (p. 645) • Amazon DynamoDB 用 Logstash プラグイン (p. 668) このセクションでは、Amazon DynamoDB でアプリケーションを開発するときに役立ついくつかの追 加のツールとリソースについて説明します。 Tip ベストプラクティス、使用方法、およびツールの詳細については、DynamoDB 開発者用リ ソースページを参照してください。 API Version 2012-08-10 644 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan • http://aws.amazon.com/dynamodb/developer-resources/ Amazon DynamoDB Storage Backend for Titan DynamoDB Storage Backend for Titan パッケージは、Amazon DynamoDB 上で実装される Titan グ ラフデータベース用のストレージバックエンドです。Titan は、グラフの保存とクエリ用に最適化さ れたスケーラブルなグラフデータベースです。DynamoDB Storage Backend for Titan パッケージは GitHub で入手できます。Titan: 分散グラフデータベース は GitHub (Titan バージョン0.4.4、Titanバー ジョン0.5.4、Titanバージョン1.0.0) でも入手できます。 以下のセクションでは、グラフデータベース、グラフデータベースのいくつかのユースケース、およ び Titan: 分散グラフデータベース を DynamoDB Storage Backend で使用する方法について説明しま す。 トピック • グラフデータベースの使用 (p. 645) • Titan と DynamoDB Storage Backend for Titan (p. 646) • Titan の機能 (p. 647) • DynamoDB Storage Backend for Titan の使用開始 (p. 649) • DynamoDB の Titan グラフモデリング (p. 655) • DynamoDB Storage Backend for Titan メトリクス (p. 662) グラフデータベースの使用 グラフデータベースとは、頂点と、これらの頂点をつなぐ有向辺を保存したものです。頂点と辺はい ずれも、キーと値のペアとして保存されたプロパティを持ちます。 グラフデータベースは隣接関係のリストやマトリックスを使用して辺を保存し、探索を容易にしま す。グラフデータベースのグラフは特定の辺のタイプによって、またはグラフ全体にかけて探索でき ます。 グラフデータベースはアクション、所有権、親子関係などによって、エンティティ同士の関係性を表 すことができます。モデル化するデータの核となるのがエンティティ同士のつながりまたは関係性 である場合は、グラフデータベースが適しています。したがって、グラフデータベースはソーシャル ネットワーク、ビジネス関係、依存関係、船舶移動などの項目をモデル化およびクエリするのに便利 です。 グラフデータベースの辺を使用して、エンティティ (頂点またはノードとも呼ばれます) 間のタイプ ドリレーションシップを表示できます。辺は、親子関係、アクション、製品の推奨、購入などを表す ことができます。関係または辺は、常に開始ノード、終了ノード、タイプ、および方向を持つ 2 つの 頂点間の接続です。グラフデータベースの重要なルールは、壊れたリンクは許可されないことです。 各リンクは 2 つのノード間の関係を表します。ノードを削除すると、そのすべてのインシデント関係 (つまり、削除されるノードで開始または終了する関係) が削除されます。 ソーシャルネットワークグラフの例を次に示します。 API Version 2012-08-10 645 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan この例では、友だちのグループとその趣味をグラフとしてモデリングします。 Note 各辺には方向があり、矢印によって示されますが、辺の情報は "入力" ノードと "出力" ノード の両方に保存されます。 このグラフの単純な探索により、Justin の友だちについて知ることができます。 Titan と DynamoDB Storage Backend for Titan Titan には、グラフの多くのストレージバックエンドの 1 つを使用できるようにするプラグインアー キテクチャがあります。DynamoDB Storage Backend for Titan はそれらのプラグインの 1 つです。 次の表では、Titan の [Storage Backend Overview] ページで利用できるパリティマトリックスに DynamoDB Storage Backend を追加します。 ストレージバックエンドの比較 名前 ストレージ バックエン ドの設定値 整合性 可用性 DynamoDB com.amazon.titan.diskstorage.dynamodb.DynamoDBStoreManager 結果的に 可用性が高 線形のス はい、マ 整合性があ い、マネー ケーラビ ネージド る、マネー ジド リティ、マ ジド ネージド SSD、マ ネージド Cassandra cassandra 結果整合性 高い可用性 線形のス ケーラビリ ティ はい ディスク HBase hbase 頂点整合性 フェイル オーバー復 旧 線形のス ケーラビリ ティ はい ディスク BerkeleyDB berkeleyje ACID 単一障害点 単一のマシ ン HA モード が使用可能 ディスク Persistit persistit ACID 単一障害点 単一のマシ ン なし ディスク InMemory inmemory ACID 単一障害点 単一のマシ ン なし なし API Version 2012-08-10 646 スケーラビ リティ レプリケー ション 永続性 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan グラフストレージでの DynamoDB の使用により、データベースクラスターを管理する負担なしで、 高度にスケーラブルな分散グラフデータベースを得ることができます。DynamoDB は任意のサイズ にスケーリングでき、高速で予測可能なパフォーマンスを提供し、AWS リージョンの 3 つのアベイ ラビリティーゾーン間で自動データレプリケーションによる高可用性が確保されます。また、プレ フィックスを Titan グラフテーブルの前に追加して、1 つのアカウントとリージョンで AWS が管理す る認証と複数のグラフが提供されます。 Titan の機能 DynamoDB Storage Backend for Titan プラグインは Titan バージョン 0.4.4、0.5.4、および 1.0.0 をサ ポートします。 DynamoDB Storage Backend for Titan 1.0.0 の使用をお勧めしますが、Titan 0.4.4 および 0.5.4 のプラ グインバージョンもまだ利用できます。 Titan には次の機能があります。 • 指定された辺のタイプに沿った高速なトラバーサルと任意のトラバーサル • 有向で型付けされた辺 • 保存された関係 Titan 0.4.4 は、Blueprints API を実装して TinkerPop 2.4 スタックをサポートします。TinkerPop には 以下のコンポーネントが含まれます。 • Rexster グラフサーバー • Furnace グラフアルゴリズム • Frames オブジェクトグラフマッパー • Gremlin トラバーサル言語 • Pipes データフロー • Blueprints 汎用グラフ API Gremlin、Rexster、Furnace、Frames、および Blueprints を含む TinkerPop スタックについて は、TinkerPop のホームページを参照してください。 Titan バージョン 0.5.4 では、いくつかの重要な変更点や追加機能が提供されています。 • TinkerPop 2.5 のスタックのサポート • 頂点のパーティション化のサポート • 頂点ラベルのサポート • ユーザー定義のトランザクションログ • 2 つの新しいシステムトランザクションログテーブル: (txlog および systemlog) • edgeindex および vertexindex は単一の graphindex テーブルにマージされます Titan バージョン 0.5.4 の機能は、Titan バージョン 0.4.4 の機能のスーパーセットです。Titan の変更 の詳細については、「Titan 0.5.4 リリースノート」を参照してください。 Titan バージョン 1.0.0 では、以下の変更と追加機能が提供されます。 • TinkerPop 3.0 のスタックのサポート。 • TinkerPop 用の Titan 固有の TraversalStrategies。 • クエリ実行エンジンの最適化。 API Version 2012-08-10 647 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan Titan バージョン 1.0.0 の機能は、Titan バージョン 0.5.4 の機能のスーパーセットです。Titan の変更 の詳細については、「Titan 1.0 リリースノート」を参照してください。 Titan 機能の詳細については、Titan のドキュメントページを参照してください。 他の Titan ストレージバックエンドと同様に、Java ネイティブ API または Blueprints API の使用に加 えて、Gremlin シェルおよび Groovy 言語を使用して Titan グラフを操作できます。 次の表では、Titan ストレージバックエンドで使用できる機能を比較しています。 機能名 dynamodb cassandra berkeleyje hbase persistit (0.4.4 のみ) in memory (0.5.4 および 1.0.0) batchMutation はい はい いいえ はい いいえ いいえ distributed はい はい いいえ はい いいえ いいえ keyConsistent はい はい いいえ 構成によっ て異なる いいえ 構成によっ て異なる keyOrdered いいえ パーティ ショナーに よって異な る はい はい はい はい localKeyPartition いいえ パーティ ショナーに よって異な る いいえ いいえ いいえ いいえ locking はい いいえ はい いいえ はい いいえ multiQuery はい は いいえ い、cassandra 埋め込みを 除く はい いいえ いいえ orderedScan いいえ パーティ ショナーに よって異な る はい はい はい はい transactional いいえ いいえ はい いいえ はい いいえ unorderedScanはい パーティ ショナーに よって異な る いいえ はい いいえ はい optimisticLocking はい はい いいえ はい はい cellTTL (0.5.4 のみ) いいえ はい いいえ いいえ いいえ storeTTL (0.5.4 のみ) いいえ いいえ いいえ はい いいえ MILLI preferredTimestamps (0.5.4 のみ) API Version 2012-08-10 648 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan timestamps (0.5.4 のみ) いいえ はい いいえ はい いいえ visibility (0.5.4 のみ) いいえ いいえ いいえ いいえ いいえ Cassandra パーティショナー パーティショナー RANDOM BYTEORDER keyOrdered / localKeyPartition いいえ はい orderedScan いいえ はい unorderedScan はい いいえ 次のステップ • DynamoDB Storage Backend for Titan の使用開始 (p. 649) DynamoDB Storage Backend for Titan の使用開始 DynamoDB Storage Backend for Titan の使用を開始するには、このセクションの最初の 2 つのトピッ クのいずれかの手順に従って、次の操作を行うことができます。 • Download, install, and run Titan with the DynamoDB Storage Backend for Titan (p. ) • Launch DynamoDB Storage Backend for Titan with Gremlin Server on Amazon EC2 (p. 652) このセクションの「ローカルの DynamoDB と Amazon DynamoDB サービス (p. 655)」トピックで は、ローカルに実行している DynamoDB (初期テストに最適です) の使用から、本稼働環境での使用の ための Amazon DynamoDB サービスの使用に DynamoDB Storage Backend for Titan を切り替える方 法を示します。 トピック • DynamoDB Storage Backend for Titan のインストールおよび実行 (p. 649) • AWS CloudFormation テンプレートを使用して、Gremlin Server とともに DynamoDB Storage Backend for Titan サーバーを Amazon EC2 で起動する (p. 652) • ローカルの DynamoDB と Amazon DynamoDB サービス (p. 655) DynamoDB Storage Backend for Titan のインストールおよび実行 DynamoDB Storage Backend for Titan は GitHub 上の Apache Maven プロジェクトとして利用で き、Windows、Mac、または Linux コンピュータ上で実行されます。DynamoDB Storage Backend for Titan では、Java 1.7 (またはそれ以降) および Apache Maven が必要になります。Java を入手 するには、http://java.com/download/ に移動してください。Apache Maven を取得するには、http:// maven.apache.org/ に移動してください。次の手順に従ってローカルの Maven リポジトリに DynamoDB Storage Backend for Titan をインストールし、インストールをテストします。 Important このドキュメントは DynamoDB Storage Backend for Titan バージョン 1.0 用です。以前の バージョンの詳細については、Titan 0.4.4 用 README.md ファイルおよび Titan 0.5.4 用 README.md ファイルを参照してください。 API Version 2012-08-10 649 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan 最初の例では、Marvel Universe Social Graph を使用します。このグラフには頂点に漫画のキャラク ターがあり、辺にはキャラクターが登場する漫画本があります。Marvel Universe Social Graph の詳細 については、Marvel Universe Social Graph データセットのウェブページを参照してください。 Marvel Universe Social Graph のサブセットを読み込むには 1. Git プロジェクトをセットアップするフォルダで、次のコマンドを実行して Git プロジェクトのク ローンを作成します。 git clone https://github.com/awslabs/dynamodb-titan-storage-backend.git Note この git コマンドは Titan Version 1.0.0 用です。Titan 0.4.4 git コマンドについて は、Titan 0.4.4 用の README.md ファイルを参照してください。Titan 0.5.4 git コマンド については、Titan 0.5.4 用の README.md ファイルを参照してください。 2. dynamodb-titan-storage-backend フォルダに切り替え、次のコマンドを入力し、Maven を 使用してパッケージをインストールします。 mvn install Maven をインストールすると、Titan パッケージを含む追加の依存関係が Maven リポジトリから ダウンロードされます。 3. 別のコマンドプロンプトウィンドウを開き、次のコマンドを入力して、お使いのコンピュータで DynamoDB を起動します (グラフデータベースをテストします)。 mvn test -Pstart-dynamodb-local 4. 前のコマンドプロンプトウィンドウで、次のコマンドを入力して古い Elasticsearch インデックス をクリーンアップします。 rm -rf /tmp/searchindex 5. 次のコマンドを入力して、Gremlin Server と DynamoDB Storage Backend for Titan をインストー ルします。 src/test/resources/install-gremlin-server.sh 6. 次のコマンドを入力して、Gremlin Server のホームディレクトリにディレクトリを変更します。 cd server/dynamodb-titan100-storage-backend-1.0.0-hadoop1 7. 次のコマンドを入力して、ローカルマシンで DynamoDB を使用するように設定された Gremlin Server を起動します。 bin/gremlin-server.sh ${PWD}/conf/gremlin-server/gremlin-server-local.yaml 8. 別のコマンドプロンプトウィンドウで、Gremlin Server ホームにディレクトリを変更します。 続いて、次のように入力して Gremlin シェルを開始します。 bin/gremlin.sh 9. Gremlin シェルで、次のように入力して Gremlin Server に接続します。 API Version 2012-08-10 650 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan :remote connect tinkerpop.server conf/remote.yaml Note コロン (:) は、コマンドで必須の部分です。 10. 次のコマンドを入力して、Marvel Universe Social Graph の最初の 100 行を読み込みます。 :> com.amazon.titan.example.MarvelGraphFactory.load(graph, 100, false) Important コマンドの先頭にある : > 文字は必須です。これらの文字は、前のコマンドで接続した Gremlin Server でこれらのコマンドが実行されることをシェルに対して示します。 残りの手順では、すべてこの同じ構文を使用します。 テスト行の数を増やして大きなグラフを作成するには、MarvelGraphFactory.load() メソッ ドの 2 番目の引数の値を増やします。 11. 次のように入力して、キャラクターと、盾または爪の武器を持ってキャラクターが登場した漫画 本を出力します。 :> g.V().as('character').has('weapon', within('shield','claws')).out('appeared').as('comicbook').select('character','comic-book') 12. 次のように入力して、キャラクターと、盾または爪ではない武器を持ってキャラクターが登場し た漫画本を出力します。 :> g.V().as('character').has('weapon', without('shield','claws')).out('appeared').as('comicbook').select('character','comic-book') 13. 次のように入力して、漫画本 AVF 4 に登場するキャラクターのソートされたリストを出力しま す。 :> g.V().has('comic-book', 'AVF 4').in('appeared').values('character').order() 14. 盾または爪ではない武器を持って漫画本 AVF 4 に登場したキャラクターのソートされた一覧を出 力します。 :> g.V().has('comic-book', 'AVF 4').in('appeared').has('weapon', without('shield','claws')).values('character').order() Graph of the Gods を読み込むには Graph of the Gods は、Titan に組み込まれ、Titan ドキュメントで使用されているグラフの例です。こ の手順では、DynamoDB Storage Backend for Titan で Graph of the Gods を読み込み、「Titan 入門ガ イド」ドキュメントのチュートリアルを実行できるようにする方法を示します。 1. 「Marvel グラフセクション (p. 650)」のステップ 1~9 に従います。 2. 次のように入力して、Graph of the Gods を読み込みます。 API Version 2012-08-10 651 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan :> com.thinkaurelius.titan.example.GraphOfTheGodsFactory.load(graph) 3. 「Titan 入門ガイド」ドキュメントに移動し、「グローバルグラフインデックス」セクションか ら、残りのセットアッププロセスに従います。 Important Gremlin Server エンドポイントでリモートにコマンドを実行するには、各コマンドの前 に :> を付ける必要があります。 また、ローカル変数を含むトラバーサルと同じ行の先頭に、ローカルの変数定義を付ける必要が あります。 たとえば、トラバーサル g.V(hercules).out('father', 'mother').values('name') を リモートで実行するには、その前に Hercules の定義を付ける必要があります。 :> hercules = g.V(saturn).repeat(__.in('father')).times(2).next(); g.V(hercules).out('father', 'mother').values('name') ただし、saturn はローカル変数でもあるため、これも定義する必要があります。 :> saturn = g.V().has('name', 'saturn').next(); hercules = g.V(saturn).repeat(__.in('father')).times(2).next(); g.V(hercules).out('father', 'mother').values('name') これを前に付ける必要があるのは、Gremlin サーバーがオンのときに実行されるスクリプトで定義さ れた変数を除き、各リモートスクリプトの実行でローカル変数の状態は引き継がれないためです。詳 細については、Gremlin Server YAML ファイルの scriptEngines/gremlin-groovy/scripts リ スト要素を参照してください。 AWS CloudFormation テンプレートを使用して、Gremlin Server とともに DynamoDB Storage Backend for Titan サーバーを Amazon EC2 で起動する AWS マネジメントコンソールを使用して、テンプレートから AWS CloudFormation スタックを起動 し、Amazon EC2 でユーザーが選択するインスタンスタイプで Gremlin Server とともに Titan を起動 できます。このスタックでは、gremlin-server.yaml 設定ファイルへの Amazon S3 読み取りアクセス 権、およびテーブルを作成し、テーブルの項目を読み取り、書き込むための DynamoDB のフルアク セス権がある既存の IAM ロールが必要です。 VPC のネットワーク ACL には、次を許可するための必要十分なアクセスが含まれます。 • インスタンスへの SSH 接続。 • セントラルリポジトリから yum の更新をダウンロードする EC2 インスタンス (HTTP アウトバウン ド)。 • S3 から gremlin-server.yaml と Gremlin Server パッケージをダウンロードする EC2 インスタンス (HTTPS アウトバウンド)。 • DynamoDB (HTTPS アウトバウンド) に接続する EC2 インスタンス。 前提条件 • Amazon EC2 インスタンスの SSH キーは、Gremlin Server スタックを作成する計画のリージョン に存在する必要があります。 API Version 2012-08-10 652 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan • Amazon S3読み取りアクセスと DynamoDB フルアクセスがあるリージョンの IAM ロールの名前と パスで、この CloudFormation スタックを実行するには、最小限のポリシーが必要です。cloud-init のスタックに dynamodb.properties ファイルを提供するには、Amazon S3 読み取りアクセスが 必要です。DynamoDB フルアクセスが必要なのは、DynamoDB Storage Backend for Titan がテー ブルを作成および削除し、それらのテーブルでデータを読み取り、書き込む必要があるためです。 • 設定を含む gremlin-server および dynamodb.properties を持つ Amazon S3 バケット。これ らのファイルは、server/dynamodb-titan100-storage-backend-1.0.0-hadoop1/conf/gremlin-server に あります。 作成と Amazon S3 へのアップロードの詳細については、「Working with Amazon S3 Buckets」を 参照してください。 Note AWS CloudFormation テンプレートは再パッケージ化されたバージョンの titan-1.0.0hadoop1.zip、titan-dynamodb-0.5.4-hadoop2.zip、および titan-dynamodb-server-0.4.4.zip を ダウンロードします。 DynamoDB Storage Backend for Titan およびその依存関係が、デフォルトのディストリ ビューションに追加されています。これらは次のウェブサイトからダウンロードできます。 • 0.4.4: dynamodb-titan044-storage-backend-server-1.0.0.zip (SHA256 ハッシュ: a3bbd0e5eb0b71bbadf6762def516f5836c8032c442d5f39799c56c5345cb14b) • 0.5.4: dynamodb-titan054-storage-backend-1.0.0-hadoop2.zip (SHA256 ハッシュ: 612979bc0c3c4ced3d01c2366c3a95888a40931d3dea72c47284653cdcc1) • 1.0.0: dynamodb-titan100-storage-backend-1.0.0-hadoop1.zip (SHA256 ハッシュ: 5e8c31c97227ebc19eb6ac555d914de950ebbcd93b8eb5439b6f28a1990) AWS CloudFormation を使用して Amazon EC2 で Gremlin Server を起動するには 1. 次のリンクを選択し、DynamoDB Storage Backend for Titan を使用して Gremlin Server スタック を作成する AWS CloudFormation テンプレートを表示します。 バージョン 1.0.0 テンプレートの表示 2. スタックを起動する準備ができたら、このボタンを選択します。 3. [Select Template] ページで、[Next] を選択します。 Note このチュートリアルでは、デフォルト設定を使用します。ただし、このページで AWS CloudFormation スタックの名前をカスタマイズするか、別のテンプレートを使用するこ とができます。 4. [Specify Parameters] ページで、次のように指定します。 • EC2 インスタンスタイプ • Gremlin Server Websockets ポートのネットワークホワイトリストパターン • Gremlin Server ポート、デフォルトは 8182。 • dynamodb.properties 設定ファイルへの S3 URL • 既存の EC2 SSH キーの名前 • SSH プロトコル用のネットワークホワイトリスト。SSH 経由の着信接続を許可し、Gremlin Server への Websockets 接続を保護する SSH トンネルを有効にする必要があります。 API Version 2012-08-10 653 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan Note デフォルトの CIDR である 0.0.0.0/32 は、すべての IP アドレスからの SSH アクセ スをブロックします。適切なアドレス範囲を指定する必要があります。詳細について は、「Linux インスタンス用の受信トラフィックの認可」を参照してください。 • この CloudFormation スクリプトを実行し、DynamoDB Storage Backend for Titan で Gremlin Server を実行する最小限の権限を持つ IAM ロールへのパス。このロールで は、dynamodb.properties ファイルを取得する S3 読み取りと、テーブルを作成し、項目を読み 取って書き込むための DynamoDB のフルアクセスが必要です。 5. Network ホワイトリストおよび Amazon EC2 インスタンスタイプは変更できます。 [Options] ページで、[Next] を選択します。 Note 6. このチュートリアルでは、デフォルト設定を使用します。 [Review] ページで、[I acknowledge that this template might cause AWS CloudFormation to create IAM resources] を選択し、[Create] を選択します。 Note 7. 8. 9. この AWS CloudFormation テンプレートでは IAM リソースは作成されません。 スタックのデプロイ中は、AWS CloudFormation コンソールに移動し、Amazon EC2 インスタン スの [Status] 列を参照することで、進捗状況をモニタリングできます。 スタックの作成が完了したら、新しいスタックの [Outputs] タブに移動します。 CloudFormation スクリプトの Outputs から SSH トンネルコマンドをコピーし、それを使用し て、スタックのデプロイが完了した後で、localhost ポート 8182 から EC2 ホストの Gremlin Server ポート (8182) への SSH トンネルを作成します。 10. 前のトピックの「Marvel Universe Social Graph のサブセットを読み込むには (p. 650)」セク ションをステップ 5 から続行します。 次のステップ これで EC2 に Gremlin Server が作成されたため、Titan の作業を開始できます。継続するためのいく つかのオプションを示します。 「Titan 入門ガイド」チュートリアルに従います 「Titan 入門ガイド」ドキュメントに移動し、「グローバルグラフインデックス」セクションか ら、残りのセットアッププロセスに従います。 Gremlin の例に従います Gremlin の詳細については、このセクションの手順を繰り返し、Gremlin ドキュメントの例に従っ てください。 Important Gremlin Server エンドポイントでリモートにコマンドを実行するには、各コマンドの前に :> を付ける必要があります。 Marvel グラフを試す Marvel Social Graph データを操作するには、このセクションの手順を繰り返し、「Marvel グラ フ」セクションのステップ 5~14 に従います。 DynamoDB Storage Backend for Titan の詳細について学ぶ 詳細については、最初に「ローカルの DynamoDB と Amazon DynamoDB サービス (p. 655)」 セクションを参照してください。 API Version 2012-08-10 654 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan ローカルの DynamoDB と Amazon DynamoDB サービス DynamoDB Storage Backend for Titan はデフォルトで DynamoDB のダウンロード可能バージョ ンをストレージに使用します。DynamoDB のこのエディションは、最初にアプリケーションを DynamoDB Storage Backend for Titan でテストするのに便利ですが、実稼働環境のパフォーマンスを 正確に表すには、テストプロセスの早い段階で Amazon DynamoDB に切り替えることをお勧めしま す。 ローカル DynamoDB から Amazon DynamoDB ウェブサービスにストレージバックエンドを 切り替えるには 1. デフォルトのリージョンは 米国東部(バージニア北部) です。別のリージョンが必要な場合は、 設定ファイルでこれを変更する必要があります。それ以外の場合は、ステップ 2 に進みます。 src/test/resources/dynamodb.properties の設定ファイルで、リージョンのエンドポイン トを https://dynamodb.us-east-1.amazonaws.com から DynamoDB に変更します。たと えば、リージョンが 米国西部 (オレゴン) である場合は、次のエンドポイント設定を使用します。 storage.dynamodb.client.endpoint=https://dynamodb.us-west-2.amazonaws.com 使用可能なリージョンとエンドポイントのリストについては、『アマゾン ウェブ サービス全般の リファレンス』の「Amazon DynamoDB」セクションを参照してください。 2. 次のコマンドで Gremlin Server を起動します。 bin/gremlin-server.sh ${PWD}/conf/gremlin-server/gremlin-server.yaml コンピュータで DynamoDB を実行することなく、Titan を実行できます。Titan DynamoDB Storage バックエンドは、DynamoDB のローカルインスタンスではなく、エンドポイントの DynamoDB リー ジョンのテーブルを使用します。 関連トピック DynamoDB の Titan グラフモデリング (p. 655) DynamoDB の Titan グラフモデリング Titan は、頂点と一意のキーに関連付けられた列と値のペアとして、辺とプロパティを保存しま す。DynamoDB Storage Backend for Titan は列と値の各ペアを、DynamoDB の 1 つの属性に保存し ます。列と値のペアのシリアル化の詳細については、「Titan データモデル」ドキュメントの「個別の 辺のレイアウト」セクションを参照してください。 次のセクションでは、DynamoDB Storage Backend for Titan のグラフモデリングについて説明しま す。 トピック • 単一項目データモデル (p. 657) • 複数項目データモデル (p. 657) • Titan バージョン 0.5.4 以降のストレージの変更 (p. 659) • DynamoDB Storage Backend for Titan の制限 (p. 659) • バックエンドデータの使用 (p. 660) • メトリックス (p. 661) API Version 2012-08-10 655 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan Titan は KeyColumnValueStore インターフェイスを使用して、バックエンドデータベースに列と値の ペアを保存します。DynamoDB Storage Backend for Titan には、このインターフェイスについて次の 2 つの具体的な実装があります。 実装クラス 設定プロパティ 説明 DynamoDBSingleRowStore SINGLE キーのすべての列と値のペアを 1 つの項目に保存します。 DynamoDBStore MULTI キーの列と値の各ペアを、複合 プライマリキー (パーティショ ンキーとソートキー) を持つ テーブルの別の項目に保存しま す。 両方の実装では、edgestore という名前の DynamoDB テーブルに情報が保存されます。 edgestore を含めて、Titan バージョン 0.4.4 では、保存のために次の DynamoDB テーブルが使用さ れます。 表 説明 edgestore すべてのプロパティと辺 (列の値のペア) を保存 します。頂点ごとに 1 つの項目。 edgeindex 辺のインデックス。 vertexindex すべての頂点のインデックス。 titan_ids プラグインの各インスタンスのクライアント ID。 system_properties ストレージバックエンドのプロパティ。 Titan バージョン 0.5.4 以降では、異なるバックエンドテーブルが使用されます。edgestore を含め て、Titan バージョン 0.5.4 以降では、保存のために次の DynamoDB テーブルが使用されます。 表 説明 edgestore すべてのプロパティと辺 (列の値のペア) を保存 します。頂点ごとに 1 つの項目。 graphindex 辺と頂点のインデックス。 systemlog Titan システムログ。 txlog トランザクションログ。 titan_ids プラグインの各インスタンスのクライアント ID。 system_properties ストレージバックエンドのプロパティ。 Note Titan バージョン 0.5.4 以降では、それぞれがテーブルに保存される、ユーザー定義のトラン ザクションログもサポートされます。 API Version 2012-08-10 656 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan DynamoDB Storage Backend for Titan プロパティファイルで、1 つまたは複数の項目のストレージオ プションを選択できます。以下のセクションでは、2 つの実装について説明します。 単一項目データモデル 単一項目データモデルでは、すべての列と値のペアが、1 つの DynamoDB 項目の特定のキーに保存 されます。 edgestore テーブルでは、頂点のすべてのプロパティと辺が 1 つの項目に保存されます。 ここで、パーティションキーは KeyColumnValueStore ストア (KCV) のキーです。詳細については、 「KeyColumnValueStore」を参照してください。 次の表は、前述の「グラフデータベースの使用 (p. 645)」セクションのソーシャルネットワークグラ フが、単一項目データモデルの edgestore DynamoDB テーブルにどのように保存されるかを示してい ます。また、非表示のプロパティも示します。Titan は、非表示のプロパティを各ノードに追加し、そ れが存在していることを示します。 Note これは、テーブルに保存されているデータを表したものです。実際のデータは圧縮メタデー タでシリアル化され、人間が読み取ることはできません。 パーティショ ンキー (pk) 属性 属性 属性 属性 属性 Vertex id 1 Property Name: Justin Edge (out) Friend: Anna Edge (out) Friend: Kris Edge (out) Likes: Movies Hidden Property Exists Vertex id 2 Property Name: Anna Edge (in) Friend: Justin Edge (out) Likes: Books Hidden Property Exists Vertex id 3 Property Name: Kris Edge (in) Friend: Justin Edge (out) Likes: Movies Hidden Property Exists Vertex id 4 Property Name: Movie Edge (in) Likes: Justin Edge (in) Likes: Kris Hidden Property Exists Vertex id 5 Property Name: Books Edge (in) Likes: Anna Hidden Property Exists この表は、各属性に保存されたすべてのデータを示していません。属性に保存される辺とプロパティ のデータおよびデータ形式の詳細については、「Titan データモデル」ページを参照してください。 このモデルの制限として、すべてを単一の項目に保存すると、各頂点に対するプロパティと辺の数が 制限されます。これは、DynamoDB には 400 KB という項目サイズの制限があるためです。 複数項目データモデル 400 KB の項目サイズの制限を回避するため、DynamoDB Storage Backend for Titan は複数項目のス トレージを代替モデルとして提供します。グラフに次のいずれかの特徴がある場合、複数項目のスト レージを使用することをお勧めします。 • 各頂点に多くの辺がある • 多数の頂点プロパティがある API Version 2012-08-10 657 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan • 項目サイズの制限に近いサイズの個別のプロパティ値がある これらの場合、少なくとも edgestore と インデックスストア (0.4.4 の edgeindex および vertexindex、および 0.5.4 の graphindex) について、複数項目モデルを使用することをお勧めしま す。edgestore とインデックスストアは、項目サイズの制限の影響を受ける可能性が高くあります。 複数項目データモデルでは、列と値の各ペアが個別の DynamoDB 項目に保存されます。列と値の各 ペアは、パーティションキーが KCV のキーで、ソートキーが KCV の列である項目として保存されま す。特定のキーの列と値のすべてのペアは、edgestore テーブルの異なる項目に保存されます。 次の表は、前述の「グラフデータベースの使用 (p. 645)」セクションのソーシャルネットワークグラ フが、複数項目データモデルの edgestore DynamoDB テーブルにどのように保存されるかを示してい ます。また、非表示のプロパティも示します。Titan は、非表示のプロパティを各ノードに追加し、そ れが存在していることを示します。 Note これは、テーブルに保存されているデータを表したものです。実際のデータは圧縮メタデー タでシリアル化され、人間が読み取ることはできません。 パーティションキー (pk) ソートキー (sk) 値 (v) Vertex id 1 ソートキー Vertex id 1 Property id Property - Name: Justin Vertex id 1 Edge id Edge (out) - Friend: Anna Vertex id 1 Edge id Edge (out) - Friend: Kris Vertex id 1 Edge id Edge (out) - Likes: Movies Vertex id 1 Property id Hidden Property - Exists Vertex id 2 ソートキー Vertex id 2 Property id Property - Name: Anna Vertex id 2 Edge id Edge (in) - Friend: Justin Vertex id 2 Edge id Edge (out) - Likes: Books Vertex id 2 Property id Hidden Property - Exists Vertex id 3 ソートキー Vertex id 3 Property id Property - Name: Kris Vertex id 3 Edge id Edge (in) - Friend: Justin Vertex id 3 Edge id Edge (out) - Likes: Movies Vertex id 3 Property id Hidden Property - Exists Vertex id 4 ソートキー Vertex id 4 Property id Property - Name: Movies Vertex id 4 Edge id Edge (in) - Likes: Justin Vertex id 4 Edge id Edge (in) - Likes: Kris API Version 2012-08-10 658 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan Vertex id 4 Property id Hidden Property - Exists Vertex id 5 ソートキー Vertex id 5 Property id Property - Name: Books Vertex id 5 Edge id Edge (in) - Likes: Anna Vertex id 5 Property id Hidden Property - Exists この表は、各属性に保存されたすべてのデータを示していません。属性に保存される辺とプロパティ のデータおよびデータ形式の詳細については、「Titan データモデル」ページを参照してください。 複数項目データモデルでは 400 KB 項目の制限を回避できますが、パフォーマンスが低下します。基 本テーブルのスキャンによる edgestore テーブルの頂点の反復的な処理は、単一項目のデータモデル よりも複数項目のデータモデルで長い時間がかかる可能性があります。 複数項目のデータモデルは、ストアの 1 つのエンティティをキーで列ごとに 1 つの項目に非正規化す ることで、400 KB の制限を解消します。この機能では、1 つのキーが複数項目のデータストアの行ご とに 1 回表示されます。このモデルでスキャン時間が長くなるのは、各辺ラベル、頂点プロパティ、 および辺プロパティに対して、別の項目がこのモデルで存在するためです。edgestore_key テーブル は、ストアエンティティのキーと改訂番号を保存するため、スキャンでは変化のオペレーションごと に 1 回のみ KCV キーにアクセスします。この機能は、KCV ストアへの変化では少なくとも 2 つの HTTP ラウンドトリップが必要になります。その対象の 1 つはキーテーブルで、少なくとももう 1 つ はベーステーブル、変化に列の削除のみが関連する場合はさらに多くのラウンドトリップが必要にな ります。 Titan バージョン 0.5.4 以降のストレージの変更 DynamoDB Storage Backend for Titan バージョン 0.5.4 以降では、バージョン 0.4.4 と同じ方法でグ ラフデータが保存されますが、以下の違いがあります。 • パーティション化された頂点を使用できます。頂点のパーティションはすべて並行して読み取り、 書き込まれます。 • vertexindex と edgeindex テーブルは、graphindex という名前の 1 つのインデックスストアに結合 されます。 • Titan 0.5.4 は、ユーザー定義のトランザクションログをサポートします。各ユーザー定義のトラン ザクションログは、.properties/rexster.xml で設定する必要がある追加の DynamoDB テーブ ルに対応します。 • Titan 1.0.0 も、ユーザー定義のトランザクションログをサポートします。各ユーザー定義のトラ ンザクションログは、dynamodb-properties ファイルで設定する必要がある追加の DynamoDB テーブルに対応します。 DynamoDB Storage Backend for Titan の制限 DynamoDB は、パーティションキーのサイズ (2048 バイト)、ソートキーのサイズ (1024 バイト)、 および合計項目サイズ (400 KB) に制限を適用しています。したがって、Titan DynamoDB BigTable の実装には、次のリストに示すいくつかの制限があります。BigTable は Titan バックエンド用のスト レージの抽象概念の名前です。Titan BigTable の抽象化の詳細については、BigTable を参照してくだ さい。 • 組み込みのインデックスを使用する場合、インデックスを作成したプロパティ値は、パーティショ ンキーの最大サイズによって制限されます。2048 バイトドキュメントなど、より大きな値のイン デックスを作成する必要がある場合、複合インデクサ (Elasticsearch、Solr、Lucene など) を使用し て、全文検索を有効にします。 • 列の最大値のサイズは、可変の ID エンコードスキーマと Titan の圧縮オブジェクトのシリアル化 によって異なりますが、これが DynamoDB の最大項目サイズであるため、項目の表現では 400 KB API Version 2012-08-10 659 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan に制限されます。単一項目のデータモデルでは、KCVStore の 1 つのキー (edgestore の out-vertex) に保存されたすべての列が、400 KB 未満でなければならないことを意味します。複数項目のデー タモデルでは、1 つの列に保存されたすべて (頂点プロパティ、辺などの 1 つのキーと列のペア) は、400 KB 以下のサイズである必要があります。頂点からのすべての辺は単一項目のデータモデル の 1 つの項目に保存されるため、1 つの項目モデルは、出力度合が小さいグラフでのみ使用できま す。 • DynamoDB テーブルのプレフィックスを使用して、ユーザー定義のトランザクションログがない限 り、バージョン 0.4.4 ではリージョンあたり 51 のグラフ、バージョン 0.5.4 以降ではリージョンあ たり 42 のグラフを持つことができます。ユーザー定義トランザクションログを使用する場合、各 ログに追加のテーブルがあるため、リージョンに保存できるグラフの数は少なくなります。詳細に ついては、Titan ドキュメントの「ユーザー定義トランザクションログ」を参照してください。デ フォルトでは、DynamoDB のテーブル数は、リージョンあたり 256 テーブルに制限されています。 リージョンでさらに多くのグラフを作成する場合は、アカウント制限の引き上げをリクエストでき ます。アカウントの制限の詳細については、「DynamoDB の制限」ページを参照してください。 前述の制限は、Titan の制限に加えて適用されます。Titan の制限の詳細については、Titan ドキュメン トの「技術的な制限」ページを参照してください。 バックエンドデータの使用 TitanDB バックエンドストレージ用のプロビジョニングは、グラフの設計 (多くの頂点と多くのプロパ ティ)、使用量 (読み取り、書き込み、更新)、ストレージデータモデル (単一と複数) に応じて異なりま す。 どのグラフでも、edgestore テーブルにほとんどのデータがあり、最も使用されます。 次の表は、edgestore テーブルに対するプロビジョニング量の予測に役立ちます。毎秒、処理 (読み取 り、書き込み、更新) する次のグラフオブジェクトの数を予測する必要があります。 • 頂点: 頂点の数。単一および複数項目モデルに適用されます。 • 頂点あたりのプロパティ: 各頂点のプロパティの数。複数項目モデルに適用されます。 • 頂点ごとの外部方向の辺: 頂点から他の頂点への辺の数。単一および複数項目モデルに適用されま す。 Note 辺はデフォルトでは双方向になります。一方向 (外部方向のみ) の辺を作成しない限り、外 部方向と内部方向の辺は等しくなります。 • 頂点への辺: 頂点に入る辺の数。 • 非表示のプロパティ: Titan によって保存されるプロパティ。各頂点には、少なくとも exists プロ パティがあります。Inn Titan バージョン 0.4.4 には、頂点あたり少なくとも 1 つの非表示のプロパ ティがあり、Titan 0.5.4 には頂点あたり少なくとも 2 つの非表示プロパティがあります。 Note 単一項目データモデルでは、多くのグラフオブジェクトは頂点を持つ単一の項目にシリアル 化されるため、使用量の予測には必要ありません。 タイプ edgestore に対する Update/ edgestore に対する Update/ DeleteItem 呼び出し、単一項目 DeleteItem 呼び出し、複数項目 モデル モデル 作成 vertices * edgesOutOfVertex API Version 2012-08-10 660 vertices * (vertexProperties + edgesIntoVertex + Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan edgesOutOfVertex + titanHiddenProperties) 更新 vertices * edgesOutOfVertex vertices + vertexProperties + edgesIntoVertex + edgesOutOfVertex + titanHiddenProperties 読み取り 頂点 vertices + vertexProperties + edgesIntoVertex + edgesOutOfVertex + titanHiddenProperties 前の表は、ストレージモデルとオペレーションタイプ別に、キャパシティー予測を分けています。次 のリストは、さまざまなオペレーションタイプについて DynamoDB アクティビティの詳細と、イン デックスの影響を示しています。 データのロード データの一括ロードは、書き込みに大きな負荷がかかります。グラフへの新しいデータのロード では、バックエンドデータベースで項目を作成する必要があります。複数項目モデルの作成で は、各頂点、プロパティ、および辺が個別の項目として書き込まれるため、より大きな負荷が発 生します。 データの更新 データの更新は、複数項目ストレージモデルでは負荷が低くなります。これは、更新中の特定の プロパティまたは辺に対して項目を更新するだけで済むためです。単一項目ストレージモデルで は、項目全体を更新する必要があります。 データの読み取り 複数項目モデルでは、プロパティまたは辺のサブセットの読み取りは、単一モデルよりも効率が 高い場合があります。これは、項目全体ではなくリクエストした項目のみが読み取られるためで す。 graphindex テーブルでの操作 単一項目モデルでは、graphindex テーブルの項目は一意の頂点/辺のプロパティの名前と値の組 み合わせでキーが付けられ、その他の項目属性 (列) は、このプロパティ値が持つ頂点/辺の ID を 表します。複数項目モデルには、graphindex の項目は引き続きプロパティの名前と値の組み合 わせでキーが付けられますが、そのプロパティの名前と値の組み合わせを持つ頂点/辺ごとに異 なる項目があります。したがって、単一項目モデルでは、プロパティと値の組み合わせごとに 1 つの項目が graphindex に書き込まれます。複数項目モデルでは、vertices * vertexProperties + edges * edgeProperties の項目が graphindex に書き込まれます。 メトリックス Titan は Metrics core パッケージを使用してメトリクスを記録、出力します。Metrics core は、JMX、HTTP、STDOUT、CSV、SLF4j、Ganglia、および Graphite を介したメトリクスの報告 をサポートします。サードパーティーのプラグインとして使用できるその他のレポーターがありま す。Metrics core パッケージの詳細については、Metrics ウェブサイトを参照してください。 次のプロパティを使用して Metrics を有効にできます。 metrics.enabled=true # prefix for metrics from titan-core. Optional. If not specified, com.thinkaurelius.titan will be used. # Currently, the prefix for Titan system stores (system log, txlog, titan_ids, system_properties, and all user logs) # is set to com.thinkaurelius.titan.sys and cannot be changed. metrics.prefix=titan API Version 2012-08-10 661 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan # polling interval in milliseconds metrics.csv.interval=500 # the directory where to write metrics in CSV files metrics.csv.directory=metrics # The metrics prefix in titan-dynamodb allows you to change what gets prepended to the codahale metric names. #storage.dynamodb.metrics-prefix=dynamodb Note プロパティは、クラスパスのプロパティファイルで設定できます。直接 Gremlin シェルで設 定オブジェクトを使用するか、rexster.xml ファイル内で設定できます。 Gremlin シェルでメトリクス設定プロパティを設定するには、次のように入力します。 conf = new BaseConfiguration() conf.setProperty("metrics.enabled", "true") conf.setProperty("metrics.prefix", "titan") conf.setProperty("metrics.csv.interval", 1000) conf.setProperty("metrics.csv.directory", "metrics") conf.setProperty("storage.dynamodb.metrics-prefix", "dynamodb") Metrics core は、さまざまな数量の測定をサポートします。Timer は、コードのレイテン シーのレートとヒストグラムの Meter です。ヒストグラムでは、特定の値の分布を測定 し、count、max、mean、min、stddev、p50、p75、p95、p98、p99、および p999 を出力しま す。Meter は呼び出しレート (tps) を測定し、count、mean_rate、m1_rate、m5_rate、および m15_rate を出力します。Gauge はさまざまなスレッドの値を測定し、値を出力します。Counter は コードが呼び出された回数をカウントし、カウントを出力します。 Titan は「Titan メトリクス (p. 663)」ページの表に示したメトリクスを出力します。 Amazon DynamoDB Storage Backend for Titan は、Titan によって出力されたものに加えてメトリ クスを出力します。これらは、「追加の Amazon DynamoDB Storage Backend for Titan メトリク ス (p. 666)」の表に説明されている、低レベルの DynamoDB オペレーションの統計に関連します。 DynamoDB Storage Backend for Titan メトリクス Titan は Metrics core パッケージを使用してメトリクスを記録、出力します。Metrics core は、JMX、HTTP、STDOUT、CSV、SLF4j、Ganglia、および Graphite を介したメトリクスの報告 をサポートします。サードパーティーのプラグインとして使用できるその他のレポーターがありま す。Metrics ウェブサイト (https://dropwizard.github.io/metrics/3.1.0/manual/core/) で、Metrics core パッケージの詳細を参照できます。 DynamoDB Storage Backend for Titan は、Titan によって生成されるものに加えてメトリクスを生成 します。 これらは、以下の表に説明されている、低レベルの DynamoDB オペレーションの統計に関連しま す。 トピック • Titan メトリクス (p. 663) • 追加の Amazon DynamoDB Storage Backend for Titan メトリクス (p. 666) API Version 2012-08-10 662 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan Titan メトリクス Titan 1.0.0 および 0.5.4 のメトリクスは、Titan 0.4.4 によって生成されるメトリクスのスーパーセッ トです。 Note • <store> は、メトリクスが関連付けられているグラフストアを示します。 メトリクス名 Titan のバージョン スコープ 計器のタイプ db.getVertexByID 0.4.4、0.5.4、1.0.0 グローバル Counter db.getVerticesByID 0.4.4、0.5.4、1.0.0 グローバル Counter <store>.acquireLock.calls 0.4.4、0.5.4、1.0.0 Graph Store Counter <store>.acquireLock.time 0.4.4、0.5.4、1.0.0 Graph Store Timer (Histogram +Meter) <store>.getKeys.calls Graph Store Counter <store>.getKeys.iterator.hasNext.calls 0.5.4、1.0.0 Graph Store Counter <store>.getKeys.iterator.hasNext.time 0.5.4、1.0.0 Graph Store Timer (Histogram +Meter) <store>.getKeys.iterator.next.calls 0.5.4、1.0.0 Graph Store Counter <store>.getKeys.iterator.next.time 0.5.4、1.0.0 Graph Store Timer (Histogram +Meter) <store>.getKeys.time 0.5.4、1.0.0 Graph Store Timer (Histogram +Meter) <store>.getSlice.calls 0.4.4、0.5.4、1.0.0 Graph Store Counter <store>.getSlice.entries-0.4.4、0.5.4、1.0.0 histogram Graph Store Histogram <store>.getSlice.entries-0.4.4、0.5.4、1.0.0 returned Graph Store Counter <store>.getSlice.time Graph Store Timer (Histogram +Meter) <store>.storeManager.mutate.calls 1.0.0 Graph Store Counter <store>.storeManager.mutate.time 1.0.0 Graph Store Timer global.storeManager.closeManager.calls 1.0.0 グローバル Counter global.storeManager.openDatabase.calls 1.0.0 グローバル Counter global.storeManager.startTransaction.calls 1.0.0 グローバル Counter query.graph.execute.calls0.4.4、0.5.4、1.0.0 グローバル Counter query.graph.execute.exceptions 0.5.4 グローバル Counter query.graph.execute.time 0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) 0.5.4、1.0.0 0.4.4、0.5.4、1.0.0 API Version 2012-08-10 663 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan query.graph.getNew.calls 0.4.4、0.5.4、1.0.0 グローバル Counter query.graph.getNew.time 0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) query.graph.hasDeletions.calls 0.4.4、0.5.4、1.0.0 グローバル Counter query.graph.hasDeletions.time 0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) query.graph.isDeleted.calls 0.4.4、0.5.4 グローバル Counter query.graph.isDeleted.time 0.4.4、0.5.4 グローバル Timer (Histogram +Meter) query.vertex.execute.calls0.4.4、0.5.4、1.0.0 グローバル Counter query.vertex.execute.time0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) query.vertex.getNew.calls0.4.4、0.5.4、1.0.0 グローバル Counter query.vertex.getNew.time0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) query.vertex.hasDeletions.calls 0.4.4、0.5.4、1.0.0 グローバル Counter query.vertex.hasDeletions.time 0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) query.vertex.isDeleted.calls 0.5.4 グローバル Counter query.vertex.isDeleted.time 0.5.4 グローバル Timer (Histogram +Meter) schemacache.name.misses 0.5.4 グローバル Counter schemacache.name.retrievals 0.5.4 グローバル Counter schemacache.relations.misses 0.5.4 グローバル Counter schemacache.relations.retrievals 0.5.4 グローバル Counter stores.acquireLock.calls 0.4.4、0.5.4、1.0.0 グローバル Counter stores.acquireLock.time 0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) stores.getKeys.calls 0.5.4、1.0.0 グローバル Counter stores.getKeys.iterator.hasNext.calls 0.5.4、1.0.0 グローバル Counter stores.getKeys.iterator.hasNext.time 0.5.4、1.0.0 グローバル Timer (Histogram +Meter) stores.getKeys.iterator.next.calls 0.5.4、1.0.0 グローバル Counter stores.getKeys.iterator.next.time 0.5.4、1.0.0 グローバル Timer (Histogram +Meter) stores.getKeys.time グローバル Timer (Histogram +Meter) 0.5.4、1.0.0 API Version 2012-08-10 664 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan stores.getSlice.calls 0.4.4、0.5.4、1.0.0 グローバル Counter stores.getSlice.entrieshistogram 0.4.4、0.5.4、1.0.0 グローバル Histogram stores.getSlice.entriesreturned 0.4.4、0.5.4、1.0.0 グローバル Counter stores.getSlice.time 0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) sys.schemacache.name.misses 1.0.0 グローバル Counter sys.schemacache.name.retrievals 1.0.0 グローバル Counter sys.schemacache.relations.misses 1.0.0 グローバル Counter sys.schemacache.relations.retrievals 1.0.0 グローバル Counter sys.<store>.getSlice.calls 0.4.4、0.5.4、1.0.0 System Store Counter sys.<store>.getSlice.entries0.4.4、0.5.4、1.0.0 histogram System Store Histogram sys.<store>.getSlice.entries0.4.4、0.5.4、1.0.0 returned System Store Counter sys.<store>.getSlice.time0.4.4、0.5.4、1.0.0 System Store Timer (Histogram +Meter) sys.<store>.mutate.calls0.4.4、0.5.4、1.0.0 System Store Counter sys.<store>.mutate.time0.4.4、0.5.4、1.0.0 System Store Timer (Histogram +Meter) sys.stores.getSlice.calls 0.4.4、0.5.4、1.0.0 グローバル Counter sys.stores.getSlice.entries0.4.4、0.5.4、1.0.0 histogram グローバル Histogram sys.stores.getSlice.entries0.4.4、0.5.4、1.0.0 returned グローバル Counter sys.stores.getSlice.time 0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) sys.stores.mutate.calls 0.4.4、0.5.4、1.0.0 グローバル Counter sys.stores.mutate.time 0.4.4、0.5.4、1.0.0 グローバル Timer (Histogram +Meter) sys.storeManager.mutate.calls 1.0.0 グローバル Counter sys.storeManager.mutate.time 1.0.0 グローバル Timer sys.schema.query.graph.execute.calls 1.0.0 グローバル Counter sys.schema.query.graph.execute.time 1.0.0 グローバル Timer sys.schema.query.graph.getNew.calls 1.0.0 グローバル Counter sys.schema.query.graph.getNew.time 1.0.0 グローバル Timer API Version 2012-08-10 665 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan sys.schema.query.graph.hasDeletions.calls 1.0.0 グローバル Counter sys.schema.query.graph.hasDeletions.time 1.0.0 グローバル Timer sys.schema.stores.getSlice.calls 1.0.0 グローバル Counter sys.schema.stores.getSlice.entries1.0.0 histogram グローバル Histogram sys.schema.stores.getSlice.entries1.0.0 returned グローバル Counter sys.schema.stores.getSlice.time 1.0.0 グローバル Timer sys.schema.tx.begin 1.0.0 グローバル Counter sys.schema.tx.rollback 1.0.0 グローバル Counter sys.schema.v100_edgestore.getSlice.calls 1.0.0 グローバル Counter sys.schema.v100_edgestore.getSlice.entries1.0.0 histogram グローバル Histogram sys.schema.v100_edgestore.getSlice.entries1.0.0 returned グローバル Counter sys.schema.v100_edgestore.getSlice.time 1.0.0 グローバル Timer sys.schema.v100_graphindex.getSlice.calls 1.0.0 グローバル Counter sys.schema.v100_graphindex.getSlice.entries1.0.0 histogram グローバル Histogram sys.schema.v100_graphindex.getSlice.entries1.0.0 returned グローバル Counter sys.schema.v100_graphindex.getSlice.time 1.0.0 グローバル Timer tx.begin 0.4.4、0.5.4、1.0.0 グローバル Counter tx.commit 0.4.4、0.5.4、1.0.0 グローバル Counter tx.commit.exceptions 0.5.4 グローバル Counter tx.rollback 0.5.4 グローバル Counter 追加の Amazon DynamoDB Storage Backend for Titan メトリクス Note • <prefix> は、プロパティファイルで設定されるテーブルのプレフィックスです。 • <ddb> は、プロパティファイルで設定される DynamoDB メトリクスのプレフィックスで す。 • <store> は、メトリクスが関連付けられているグラフストアを示します。 メトリクス名 Titan のバージョン 計器のタイプ <ddb>.<prefix>_executorqueue-size 0.4.4、0.5.4、1.0.0 Gauge API Version 2012-08-10 666 Amazon DynamoDB 開発者ガイド Amazon DynamoDB Storage Backend for Titan <ddb>.<prefix>_ListTablesPagesTimer 0.4.4、0.5.4、1.0.0 Histogram <ddb>.<prefix>_ListTablesHistogram 0.4.4、0.5.4、1.0.0 Timer (Histogram+Meter) <ddb>.<prefix>_mutateManyGauge 0.4.4、0.5.4 Timer (Histogram+Meter) <ddb>.<prefix>_mutateMany Timer (Histogram+Meter) 1.0.0 <ddb>.<prefix>_mutateManyKeys 1.0.0 Meter <ddb>.<prefix>_mutateManyStores 1.0.0 Meter <ddb>.<prefix>_mutateManyUpdateOrDeleteItemCalls 1.0.0 Meter <ddb>.CreateTable.<prefix>_<store> 0.4.4、0.5.4、1.0.0 Timer (Histogram+Meter) <ddb>.DeleteItem.<prefix>_<store> 0.4.4、0.5.4、1.0.0 Timer (Histogram+Meter) <ddb>.DeleteItemConsumedCapacity. 0.4.4、0.5.4、1.0.0 <prefix>_<store> Meter <ddb>.DeleteItemRetries.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Meter <ddb>.DeleteItemThrottling.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Timer (Histogram+Meter) <ddb>.DeleteTable.<prefix>_<store> 0.4.4、0.5.4、1.0.0 Timer (Histogram+Meter) <ddb>.DescribeTable.<prefix>_0.4.4、0.5.4、1.0.0 <store> Timer (Histogram+Meter) <ddb>.GetItem.<prefix>_<store> 0.4.4、0.5.4、1.0.0 Timer (Histogram+Meter) <ddb>.GetItemConsumedCapacity. 0.4.4、0.5.4、1.0.0 <prefix>_<store> Meter <ddb>.GetItemRetries.<prefix>_0.4.4、0.5.4、1.0.0 <store> Meter <ddb>.GetItemThrottling.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Timer (Histogram+Meter) <ddb>.Query.<prefix>_<store>0.4.4、0.5.4、1.0.0 Timer (Histogram+Meter) <ddb>.QueryConsumedCapacity.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Meter <ddb>.QueryItemCountCounter.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Counter <ddb>.QueryItemCountHistogram.0.4.4、0.5.4、1.0.0 <prefix>_<store> Histogram <ddb>.QueryPages.<prefix>_<store> 0.4.4、0.5.4、1.0.0 Histogram <ddb>.QueryRetries.<prefix>_<store> 0.4.4、0.5.4、1.0.0 Meter <ddb>.QueryThrottling.<prefix>0.4.4、0.5.4、1.0.0 _<store> Timer (Histogram+Meter) <ddb>.Scan.<prefix>_<store>0.4.4、0.5.4、1.0.0 Timer (Histogram+Meter) <ddb>.ScanConsumedCapacity.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Meter <ddb>.ScanItemCountCounter.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Counter <ddb>.ScanItemCountHistogram.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Histogram <ddb>.ScanPages.<prefix>_<store> 0.4.4、0.5.4、1.0.0 Histogram <ddb>.ScanRetries.<prefix>_<store> 0.4.4、0.5.4、1.0.0 Meter <ddb>.ScanThrottling.<prefix>_0.4.4、0.5.4、1.0.0 <store> Timer (Histogram+Meter) API Version 2012-08-10 667 Amazon DynamoDB 開発者ガイド Amazon DynamoDB 用 Logstash プラグイン <ddb>.UpdateItem.<prefix>_<store> 0.4.4、0.5.4、1.0.0 Timer (Histogram+Meter) <ddb>.UpdateItemBytes.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Histogram <ddb>.UpdateItemConsumedCapacity. 0.4.4、0.5.4、1.0.0 <prefix>_<store> Meter <ddb>.UpdateItemRetries.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Meter <ddb>.UpdateItemThrottling.<prefix> 0.4.4、0.5.4、1.0.0 _<store> Timer (Histogram+Meter) Amazon DynamoDB 用 Logstash プラグイン Amazon DynamoDB 用 Logstash プラグイン は、DynamoDB テーブルでデータにほぼリアルタイムで 表示します。DynamoDB 用 Logstash プラグイン は DynamoDB ストリーム を使用して、DynamoDB テーブルに追加されるデータを解析および出力します。 DynamoDB 用 Logstash プラグイン をインス トールしてアクティブにすると、指定されたテーブルでデータをスキャンし、DynamoDB ストリーム を使用して更新の消費を開始し、Elasticsearch に出力するか、ユーザーが選択した Logstash に出力 します。 詳細についてとソースコードのダウンロードについてには、次の GitHub リポジトリを参照してくだ さい。 • https://github.com/awslabs/logstash-input-dynamodb DynamoDB の予約語 以下のキーワードは、DynamoDB で予約されています。式の中で属性名としてこれらの単語を使用し ないでください。 DynamoDB の予約語と競合する属性名を含む式を書き込む必要がある場合、予約語の代わりに使用す る式の属性名を定義できます。詳細については、「式の属性名 (p. 213)」を参照してください。 ABORT ABSOLUTE ACTION ADD AFTER AGENT AGGREGATE ALL ALLOCATE ALTER ANALYZE AND ANY ARCHIVE ARE ARRAY AS ASC ASCII ASENSITIVE ASSERTION ASYMMETRIC AT ATOMIC API Version 2012-08-10 668 Amazon DynamoDB 開発者ガイド DynamoDB の予約語 ATTACH ATTRIBUTE AUTH AUTHORIZATION AUTHORIZE AUTO AVG BACK BACKUP BASE BATCH BEFORE BEGIN BETWEEN BIGINT BINARY BIT BLOB BLOCK BOOLEAN BOTH BREADTH BUCKET BULK BY BYTE CALL CALLED CALLING CAPACITY CASCADE CASCADED CASE CAST CATALOG CHAR CHARACTER CHECK CLASS CLOB CLOSE CLUSTER CLUSTERED CLUSTERING CLUSTERS COALESCE COLLATE COLLATION COLLECTION COLUMN COLUMNS COMBINE COMMENT COMMIT COMPACT COMPILE COMPRESS CONDITION CONFLICT API Version 2012-08-10 669 Amazon DynamoDB 開発者ガイド DynamoDB の予約語 CONNECT CONNECTION CONSISTENCY CONSISTENT CONSTRAINT CONSTRAINTS CONSTRUCTOR CONSUMED CONTINUE CONVERT COPY CORRESPONDING COUNT COUNTER CREATE CROSS CUBE CURRENT CURSOR CYCLE DATA DATABASE DATE DATETIME DAY DEALLOCATE DEC DECIMAL DECLARE DEFAULT DEFERRABLE DEFERRED DEFINE DEFINED DEFINITION DELETE DELIMITED DEPTH DEREF DESC DESCRIBE DESCRIPTOR DETACH DETERMINISTIC DIAGNOSTICS DIRECTORIES DISABLE DISCONNECT DISTINCT DISTRIBUTE DO DOMAIN DOUBLE DROP DUMP DURATION DYNAMIC EACH ELEMENT API Version 2012-08-10 670 Amazon DynamoDB 開発者ガイド DynamoDB の予約語 ELSE ELSEIF EMPTY ENABLE END EQUAL EQUALS ERROR ESCAPE ESCAPED EVAL EVALUATE EXCEEDED EXCEPT EXCEPTION EXCEPTIONS EXCLUSIVE EXEC EXECUTE EXISTS EXIT EXPLAIN EXPLODE EXPORT EXPRESSION EXTENDED EXTERNAL EXTRACT FAIL FALSE FAMILY FETCH FIELDS FILE FILTER FILTERING FINAL FINISH FIRST FIXED FLATTERN FLOAT FOR FORCE FOREIGN FORMAT FORWARD FOUND FREE FROM FULL FUNCTION FUNCTIONS GENERAL GENERATE GET GLOB GLOBAL GO API Version 2012-08-10 671 Amazon DynamoDB 開発者ガイド DynamoDB の予約語 GOTO GRANT GREATER GROUP GROUPING HANDLER HASH HAVE HAVING HEAP HIDDEN HOLD HOUR IDENTIFIED IDENTITY IF IGNORE IMMEDIATE IMPORT IN INCLUDING INCLUSIVE INCREMENT INCREMENTAL INDEX INDEXED INDEXES INDICATOR INFINITE INITIALLY INLINE INNER INNTER INOUT INPUT INSENSITIVE INSERT INSTEAD INT INTEGER INTERSECT INTERVAL INTO INVALIDATE IS ISOLATION ITEM ITEMS ITERATE JOIN KEY KEYS LAG LANGUAGE LARGE LAST LATERAL LEAD LEADING API Version 2012-08-10 672 Amazon DynamoDB 開発者ガイド DynamoDB の予約語 LEAVE LEFT LENGTH LESS LEVEL LIKE LIMIT LIMITED LINES LIST LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION LOCATOR LOCK LOCKS LOG LOGED LONG LOOP LOWER MAP MATCH MATERIALIZED MAX MAXLEN MEMBER MERGE METHOD METRICS MIN MINUS MINUTE MISSING MOD MODE MODIFIES MODIFY MODULE MONTH MULTI MULTISET NAME NAMES NATIONAL NATURAL NCHAR NCLOB NEW NEXT NO NONE NOT NULL NULLIF NUMBER NUMERIC API Version 2012-08-10 673 Amazon DynamoDB 開発者ガイド DynamoDB の予約語 OBJECT OF OFFLINE OFFSET OLD ON ONLINE ONLY OPAQUE OPEN OPERATOR OPTION OR ORDER ORDINALITY OTHER OTHERS OUT OUTER OUTPUT OVER OVERLAPS OVERRIDE OWNER PAD PARALLEL PARAMETER PARAMETERS PARTIAL PARTITION PARTITIONED PARTITIONS PATH PERCENT PERCENTILE PERMISSION PERMISSIONS PIPE PIPELINED PLAN POOL POSITION PRECISION PREPARE PRESERVE PRIMARY PRIOR PRIVATE PRIVILEGES PROCEDURE PROCESSED PROJECT PROJECTION PROPERTY PROVISIONING PUBLIC PUT QUERY QUIT API Version 2012-08-10 674 Amazon DynamoDB 開発者ガイド DynamoDB の予約語 QUORUM RAISE RANDOM RANGE RANK RAW READ READS REAL REBUILD RECORD RECURSIVE REDUCE REF REFERENCE REFERENCES REFERENCING REGEXP REGION REINDEX RELATIVE RELEASE REMAINDER RENAME REPEAT REPLACE REQUEST RESET RESIGNAL RESOURCE RESPONSE RESTORE RESTRICT RESULT RETURN RETURNING RETURNS REVERSE REVOKE RIGHT ROLE ROLES ROLLBACK ROLLUP ROUTINE ROW ROWS RULE RULES SAMPLE SATISFIES SAVE SAVEPOINT SCAN SCHEMA SCOPE SCROLL SEARCH SECOND API Version 2012-08-10 675 Amazon DynamoDB 開発者ガイド DynamoDB の予約語 SECTION SEGMENT SEGMENTS SELECT SELF SEMI SENSITIVE SEPARATE SEQUENCE SERIALIZABLE SESSION SET SETS SHARD SHARE SHARED SHORT SHOW SIGNAL SIMILAR SIZE SKEWED SMALLINT SNAPSHOT SOME SOURCE SPACE SPACES SPARSE SPECIFIC SPECIFICTYPE SPLIT SQL SQLCODE SQLERROR SQLEXCEPTION SQLSTATE SQLWARNING START STATE STATIC STATUS STORAGE STORE STORED STREAM STRING STRUCT STYLE SUB SUBMULTISET SUBPARTITION SUBSTRING SUBTYPE SUM SUPER SYMMETRIC SYNONYM SYSTEM API Version 2012-08-10 676 Amazon DynamoDB 開発者ガイド DynamoDB の予約語 TABLE TABLESAMPLE TEMP TEMPORARY TERMINATED TEXT THAN THEN THROUGHPUT TIME TIMESTAMP TIMEZONE TINYINT TO TOKEN TOTAL TOUCH TRAILING TRANSACTION TRANSFORM TRANSLATE TRANSLATION TREAT TRIGGER TRIM TRUE TRUNCATE TTL TUPLE TYPE UNDER UNDO UNION UNIQUE UNIT UNKNOWN UNLOGGED UNNEST UNPROCESSED UNSIGNED UNTIL UPDATE UPPER URL USAGE USE USER USERS USING UUID VACUUM VALUE VALUED VALUES VARCHAR VARIABLE VARIANCE VARINT VARYING API Version 2012-08-10 677 Amazon DynamoDB 開発者ガイド レガシー条件パラメータ VIEW VIEWS VIRTUAL VOID WAIT WHEN WHENEVER WHERE WHILE WINDOW WITH WITHIN WITHOUT WORK WRAPPED WRITE YEAR ZONE レガシー条件パラメータ このセクションでは、DynamoDB のレガシー条件パラメータを式パラメータを比較します。 式パラメーター (「式を使用した項目の読み取りと書き込み (p. 210)」を参照) の導入に伴って、旧パ ラメーターがいくつか廃止されました。新しいアプリケーションでは、これらのレガシーパラメー ターではなく、式パラメーターを使用する必要があります。(詳しくは、式を使用した項目の読み取 りと書き込み (p. 210) を参照してください)。 Note DynamoDB では、単一の 呼び出しにレガシー条件パラメータと式パラメータを混在させる ことはできません。たとえば、Query オペレーションの呼び出しで AttributesToGet と ConditionExpression を使用すると、エラーになります。 次の表に、これらのレガシーパラメーターを引き続きサポートしている DynamoDB API と、代わりに 使用される式パラメーターを示します。この表は、アプリケーションを更新して式パラメーターを使 用することを検討する際に役立ちます。 この API を使用する場合 使用しているレガシーパラメー ター 代わりに使用する式パラメー ター BatchGetItem AttributesToGet ProjectionExpression DeleteItem Expected ConditionExpression GetItem AttributesToGet ProjectionExpression PutItem Expected ConditionExpression Query AttributesToGet ProjectionExpression KeyConditions KeyConditionExpression QueryFilter FilterExpression AttributesToGet ProjectionExpression ScanFilter FilterExpression Scan API Version 2012-08-10 678 Amazon DynamoDB 開発者ガイド AttributesToGet この API を使用する場合 使用しているレガシーパラメー ター 代わりに使用する式パラメー ター UpdateItem AttributeUpdates UpdateExpression Expected ConditionExpression 以下のセクションでは、レガシー条件パラメータについて詳しく説明します。 トピック • AttributesToGet (p. 679) • AttributeUpdates (p. 680) • ConditionalOperator (p. 681) • Expected (p. 682) • KeyConditions (p. 685) • QueryFilter (p. 687) • ScanFilter (p. 689) • レガシー パラメータを使用した条件書き込み (p. 690) AttributesToGet AttributesToGet は、DynamoDB から取得する 1 つ以上の属性の配列です。属性名を省略した場 合、すべての属性が返されます。リクエストされた属性のうち見つからなかったものは、結果には表 示されません。 AttributesToGet リスト型またはマップ型の属性を取得できます。ただし、リストまたはマップ内 の個別要素は取得できません。 AttributesToGet はプロビジョニングされたスループットの消費量には影響しないことに留意し てください。アプリケーションに返されるデータ量ではなく、項目のサイズに基づいて、消費される キャパシティーユニットが DynamoDB で決定されます。 代替として ProjectionExpression を使用する Music テーブルから項目を取得するとします。ただし、返す属性は一部のみとします。次のように AttributesToGet パラメーターを指定して GetItem リクエストを使用できます。 { TableName: "Music", AttributesToGet: ["Artist", "Genre"], Key: { SongTitle: {"Call Me Today"}, Artist: {"No One You Know"} } ただし、代わりに ProjectionExpression を使用できます。 { TableName: "Music", ProjectionExpression: "Artist, Genre", Key: { API Version 2012-08-10 679 Amazon DynamoDB 開発者ガイド AttributeUpdates SongTitle: {"Call Me Today"}, Artist: {"No One You Know"} } AttributeUpdates UpdateItem オペレーションでは、AttributeUpdates は変更する属性の名前、それぞれで実行す るアクション、およびそれぞれの新しい値です。そのテーブルの任意のインデックスのインデックス キー属性である属性を更新する場合は、属性タイプがテーブルの説明の AttributesDefinition で 定義されたインデックスキーのタイプに一致する必要があります。UpdateItem を使用して、キーで はない属性を更新できます。 属性値を null にすることはできません。文字列タイプおよびバイナリタイプの属性は、ゼロより大 きい長さが必要です。セットタイプの属性は空にする必要があります。空白の値があるリクエスト は、ValidationException 例外で拒否されます。 各 AttributeUpdates 要素は、次と併せて、変更する属性名で構成されます。 • Value - 該当する場合、この属性の新しい値。 • Action - 更新の実行方法を指定する値。このアクションは、データ型が数値型またはセットである 既存の属性でのみ有効です。他のデータ型で ADD を使用しないでください。 指定のプライマリキーを持つ項目がテーブル内に存在する場合、以下の値で以下のアクションが実 行されます。 • PUT - 指定された属性を項目に追加します。属性がすでに存在する場合、新しい値に置き換えま す。 • DELETE - DELETE に値を指定しなかった場合、属性とその値が削除されます。指定した値のデー タ型は、既存の値のデータ型に一致する必要があります。 値のセットを指定すると、これらの値が古いセットから減算されます。たとえば、属性値が [a,b,c] のセットで、DELETE アクションが [a,c] を指定する場合、最終的な属性値は [b] で す。空白のセットを指定するとエラーになります。 • ADD - 属性が存在しない場合、指定された値を項目に追加します。属性が存在する場合は、ADD の動作は属性のデータ型によって決まります。 • 既存の属性が数値で、Value も数値である場合、Value は既存の属性に数学的に追加されま す。Value が負の数値である場合は、既存の属性から減算されます。 Note ADD を使用して、更新前に存在しない項目の数値を増やすまたは減らす場 合、DynamoDB は初期値として 0 を使用します。 同様に、既存の項目に ADD を使用して、更新前に存在しない項目の属性値を加算また は減算する場合、DynamoDB は初期値として 0 を使用します。たとえば、更新する項 目に itemcount という名前の属性がないが、この属性に ADD で数字 3 を加算するとし ます。DynamoDB は itemcount 属性を作成し、初期値を 0 に設定して、最後に 3 を加 算します。結果として、3 という値を持つ新しい itemcount 属性ができます。 • 既存のデータ型がセットであり、Value もセットもある場合、Value は既存のセットに付けら れます。たとえば、属性値が [1,2] のセットで、ADD アクションで [3] を指定する場合、最 終的な属性値は [1,2,3] です。ADD アクションをセット属性に対して指定し、指定した属性 の型が既存のセット型と一致しない場合、エラーが発生します。 両方のセットが同じプリミティブデータ型である必要があります。たとえば、既存のデータ型 が一連の文字列の場合、Value も一連の文字列である必要があります。 指定のキーを持つ項目がテーブル内に存在しない場合、以下の値で以下のアクションが実行されま す。 API Version 2012-08-10 680 Amazon DynamoDB 開発者ガイド ConditionalOperator • PUT - DynamoDB で指定のプライマリキーを持つ新しい項目が作成され、属性が追加されます。 • DELETE - 存在しない項目から属性を削除できないので、何も起こりません。オペレーションは成 功しますが、DynamoDB によって新しい項目は作成されません。 • ADD - DynamoDB によって、提供されたプライマリキーと属性値に対する数値 (または数値のセッ ト) で項目が作成されます。使用できるデータ型は数値型および数値セットのみです。 インデックスキーの一部である任意の属性を指定した場合、それらの属性のデータ型はテーブルの属 性定義のスキーマのデータ型に一致する必要があります。 代替として UpdateExpression を使用する Music テーブルの項目を変更するとします。次のように AttributeUpdates パラメーターを指定し て UpdateItem リクエストを使用できます。 { TableName: "Music", Key: { "SongTitle": "Call Me Today", "Artist": "No One You Know" }, AttributeUpdates: { "Genre": { "Action": "PUT", "Value": "Rock" } } } ただし、代わりに UpdateExpression を使用できます。 { TableName: "Music", Key: { "SongTitle": "Call Me Today", "Artist": "No One You Know" }, UpdateExpression: "SET Genre = :g", ExpressionAttributeValues: { ":g": "Rock" } } ConditionalOperator Expected、QueryFilter、または ScanFilter マップで条件に適用される論理演算子: • AND - すべての条件が true として評価された場合、マップ全体が true として評価されます。 • OR - 条件の少なくとも 1 つが true として評価された場合、マップ全体が true として評価されま す。 ConditionalOperator を省略する場合は、AND がデフォルトです。 オペレーションはマップ全体が true である場合のみ成功します。 API Version 2012-08-10 681 Amazon DynamoDB 開発者ガイド Expected Note このパラメーターはリスト型またはマップ型の属性をサポートしていません。 Expected Expected は UpdateItem オペレーションの条件ブロックです。Expected は属性と条件のペ アのマップです。マップの各要素は、属性名、比較演算子、および 1 つ以上の値で構成されま す。DynamoDB で比較演算子を使用して提供された属性と値が比較されます。各 Expected 要素で、 評価の結果が true または false になります。 Expected マップ内の複数のエレメントを指定すると、デフォルトではすべての条件が true である必 要があります。言い換えると、条件は AND で結ばれます。(ConditionalOperator パラメーターを 使用して、条件を OR で結ぶこともできます。その場合、条件のすべてではなく、そのうち少なくと も 1 つが true である必要があります。) Expected マップが true であると評価されると、条件演算が成功します。そうでない場合、失敗しま す。 Expected には以下が含まれています。 • AttributeValueList - 提供された属性に対して評価する 1 つまたは複数の値。リストの値の数値 は使用される ComparisonOperator によって異なります。 数値型の場合、値比較は数値です。 大なり、等しい、小なりの文字列値比較は、UTF-8 バイナリエンコードを使用した Unicode に基づ きます。たとえば、a は A より大きく、a は B より大きい文字列です。 バイナリ型では、DynamoDB は、バイナリ値を比較する際にバイナリデータの各バイトを符号なし として扱います。 • ComparisonOperator - AttributeValueList の属性を評価するコンパレータ。比較を実行する 際、DynamoDB は強力な整合性のある読み込みを使用します。 次の比較演算子を使用できます。 EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | BETWEEN 各比較演算子の説明は、以下のとおりです。 • EQ : 等しい。EQ は、リストおよびマップを含むすべてのデータ型でサポートされています。 AttributeValueList に指定できるのは、文字列型、数値型、バイナリ型、文字列セット型、 数値セット型、またはバイナリセット型の AttributeValue 要素 1 つのみです。リクエストで 指定した型とは異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しませ ん。たとえば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} と {"NS": ["6", "2", "1"]} も等しくありません。 • NE : 等しくない。NE は、リストおよびマップを含むすべてのデータ型でサポートされています。 AttributeValueList に指定できるのは、文字列型、数値型、バイナリ型、文字列セット型、 数値セット型、またはバイナリセット型の AttributeValue 1 つのみです。リクエストで指定し た型とは異なる型の AttributeValue が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} と {"NS":["6", "2", "1"]} も等しくありません。 • LE : 以下。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 要素 1 つのみです (セット型は指定できません)。リクエストで指定した型と API Version 2012-08-10 682 Amazon DynamoDB 開発者ガイド Expected は異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 • LT : 未満。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 1 つのみです (セット型は指定できません)。リクエストで指定した型とは 異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 • GE : 以上。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 要素 1 つのみです (セット型は指定できません)。リクエストで指定した型と は異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 • GT : より大きい。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 要素 1 つのみです (セット型は指定できません)。リクエストで指定した型と は異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 • NOT_NULL : 属性がある。NOT_NULL は、リストおよびマップを含むすべてのデータ型でサポート されています。 Note この演算子はデータ型ではなく、属性の存在をテストします。属性「a」のデータ型が null の場合、NOT_NULL を使用して評価すると、結果はブール値 true になります。これ は、属性「a」が存在し、そのデータ型が NOT_NULL 比較演算子に関係ないためです。 • NULL : 属性が存在しない。NULL は、リストおよびマップを含むすべてのデータ型でサポートさ れています。 Note この演算子はデータ型ではなく、属性の非存在をテストします。属性「a」のデータ型が null の場合、NULL を使用して評価すると、結果はブール値 false になります。これは、 属性「a」が存在し、そのデータ型が NULL 比較演算子に関係ないためです。 • CONTAINS : サブシーケンスまたはセットの値のチェック。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 要素 1 つのみです (セット型は指定できません)。比較する属性が文字列型 の場合、部分文字列の一致があることが確認されます。比較する属性がバイナリ型の場合、入 力に一致する対象の属性のサブシーケンスがあることが確認されます。比較する属性がセット (「SS」、「NS」、または「BS」) の場合、セットのいずれかの値と完全一致すると、演算子は true と評価されます。 CONTAINS はリストでサポートされます。「a CONTAINS b」を評価する場合、「a」をリスト 型にはできますが、「b」をセット型、マップ型、リスト型にはできません。 • NOT_CONTAINS : サブシーケンスがない、またはセットの値がないことのチェック。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 要素 1 つのみです (セット型は指定できません)。比較する属性が文字列型 の場合、部分文字列の一致がないことが確認されます。比較する属性がバイナリ型の場合、入 API Version 2012-08-10 力に一致する対象の属性のサブシーケンスがないことが確認されます。比較する属性がセット 683 Amazon DynamoDB 開発者ガイド Expected (「SS」、「NS」、または「BS」) の場合、セットのいずれの値とも完全一致しない (does not) と、演算子は true と評価されます。 NOT_CONTAINS はリストでサポートされます。「a NOT CONTAINS b」を評価する場合、 「a」をリスト型にはできますが、「b」をセット型、マップ型、リスト型にはできません。 • BEGINS_WITH : プレフィックスのチェック。 AttributeValueList に指定できるのは、文字列型またはバイナリ型の AttributeValue 1 つ のみです (数値型またはセット型は指定できません)。比較対象の属性は、(数値型またはセット型 ではなく) 文字列型またはバイナリ型である必要があります。 • IN : 2 つのセット内での要素の一致のチェック。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の 1 つ以上の AttributeValue 要素です (セット型は指定できません)。これらの属性は、項目の既存のセット 型の属性に対して比較されます。入力セットのいずれかの要素が項目の属性に含まれる場合、式 は true と評価されます。 • BETWEEN : 最初の値以上、かつ 2 番目の値以下。 AttributeValueList には、同じ型 (文字列、数値、またはバイナリ) の AttributeValue 要素を 2 つ指定する必要があります (セット型は指定できません)。対象の属性が一致するの は、対象の値が最初の要素以上かつ 2 番目の要素以下の場合です。リクエストで指定した型と は異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} は {"N":"6"} と同等ではありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 次のパラメーターを AttributeValueList および ComparisonOperator の代わりに使用できま す。 • Value - 属性と比較する DynamoDB の値。 • Exists - DynamoDB で条件付き演算を実行する前に値を評価するブール値。 • Exists が true の場合、DynamoDB はその属性値がすでにテーブルに存在するかどうかを チェックします。存在する場合は、条件の評価結果が true になります。存在しない場合は条件は false に評価されます。 • Exists が false の場合、DynamoDB はその属性値がテーブルに存在しない (not) とみなしま す。実際に値が存在しない場合は、みなしが有効であり、条件の評価結果が true になります。値 が存在しないとみなされていたにもかかわらず値が見つかった場合は、条件は false と評価され ます。 Exists のデフォルト値は true であることに注意してください。 Value および Exists パラメーターは、AttributeValueList および ComparisonOperator との互換性はありません。両方のパラメーターのセットを同時に使用すると、DynamoDB が ValidationException 例外を返すことに注意してください。 Note このパラメーターはリスト型またはマップ型の属性をサポートしていません。 代替として ConditionExpression を使用する 特定の条件が true の場合のみ Music テーブルの項目を変更するとします。次のように Expected パ ラメーターを指定して UpdateItem リクエストを使用できます。 { TableName: "Music", API Version 2012-08-10 684 Amazon DynamoDB 開発者ガイド KeyConditions Key: { "SongTitle": "Call Me Today", "Artist": "No One You Know" }, AttributeUpdates: { "Price": { Action: "PUT", Value: 1.98 }, Expected: { "Price": { "ComparisonOperator": "LE", "AttributeValueList": [ 2.00 ] } } } } ただし、代わりに ConditionExpression を使用できます。 { TableName: "Music", Key: { "SongTitle": "Call Me Today", "Artist": "No One You Know" }, UpdateExpression: "SET Price = :p1", ConditionExpression: "Price <= :p2", ExpressionAttributeValues: { ":p1": 1.98, ":p2": 2.00 } } KeyConditions KeyConditions は Query オペレーションの選択条件です。テーブルに対するクエリの場合、テーブ ルのプライマリキー属性のみの条件を持つことができます。EQ 条件としてパーティションキーの名 前と値を提供する必要があります。オプションで、ソートキーを参照する 2 番目の条件を指定できま す。 Note ソートキー条件を指定しない場合、パーティションキーと一致するすべての項目が取得され ます。FilterExpression または QueryFilter が存在する場合、項目が取得された後に適 用されます。 インデックスのクエリでは、インデックスキー属性のみの条件を持つことができます。EQ 条件として インデックスパーティションキーの名前と値を提供する必要があります。オプションで、インデック スソートキーを参照する 2 番目の条件を指定できます。 各 KeyConditions 要素は、次と併せて、比較する属性名で構成されます。 • AttributeValueList - 提供された属性に対して評価する 1 つまたは複数の値。リストの値の数値 は使用される ComparisonOperator によって異なります。 数値型の場合、値比較は数値です。 API Version 2012-08-10 685 Amazon DynamoDB 開発者ガイド KeyConditions 大なり、等しい、小なりの文字列値比較は、UTF-8 バイナリエンコードを使用した Unicode に基づ きます。たとえば、a は A より大きく、a は B より大きい文字列です。 バイナリ型では、DynamoDB は、バイナリ値を比較する際にバイナリデータの各バイトを符号なし として扱います。 • ComparisonOperator - 属性を評価するコンパレータ。たとえば、等しい、大なり、小なりなどで す。 KeyConditions の場合、次の比較演算子のみがサポートされています。 EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN 比較演算子の説明は、以下のとおりです。 • EQ : 等しい。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 1 つのみです (セット型は指定できません)。リクエストで指定した型とは 異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} と {"NS":["6", "2", "1"]} も等しくありません。 • LE : 以下。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 要素 1 つのみです (セット型は指定できません)。リクエストで指定した型と は異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 • LT : 未満。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 1 つのみです (セット型は指定できません)。リクエストで指定した型とは 異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 • GE : 以上。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 要素 1 つのみです (セット型は指定できません)。リクエストで指定した型と は異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 • GT : より大きい。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の AttributeValue 要素 1 つのみです (セット型は指定できません)。リクエストで指定した型と は異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} と {"N":"6"} は等しくありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 • BEGINS_WITH : プレフィックスのチェック。 AttributeValueList に指定できるのは、文字列型またはバイナリ型の AttributeValue 1 つ のみです (数値型またはセット型は指定できません)。比較対象の属性は、(数値型またはセット型 ではなく) 文字列型またはバイナリ型である必要があります。 • BETWEEN : 最初の値以上、かつ 2 番目の値以下。 AttributeValueList には、同じ型 (文字列、数値、またはバイナリ) の AttributeValue 要素を 2 つ指定する必要があります (セット型は指定できません)。対象の属性が一致するの API Version 2012-08-10 686 Amazon DynamoDB 開発者ガイド QueryFilter は、対象の値が最初の要素以上かつ 2 番目の要素以下の場合です。リクエストで指定した型と は異なる型の AttributeValue 要素が項目に含まれている場合、値は一致しません。たとえ ば、{"S":"6"} は {"N":"6"} と同等ではありません。また、{"N":"6"} は {"NS":["6", "2", "1"]} と同等ではありません。 代替として KeyConditionExpression を使用する Music テーブルから、同じパーティションキーを持つ複数の項目を取得するとします。次のように KeyConditions パラメーターを指定して Query リクエストを使用できます。 { TableName: "Music", KeyConditions: { "SongTitle": { ComparisonOperator: AttributeValueList: }, "Artist": { ComparisonOperator: AttributeValueList: } } "BETWEEN", ["A", "M"] "EQ", ["No One You Know"] } ただし、代わりに KeyConditionExpression を使用できます。 { TableName: "Music", KeyConditionExpression: "Artist = :a AND SongTitle BETWEEN :t1 AND :t2", ExpressionAttributeValues: { ":a": "No One You Know", ":t1": "A", ":t2": "M" } } QueryFilter Query オペレーションでは、QueryFilter は項目が読み込まれ目的の値のみが返された後にクエリ 結果を評価する条件です。 このパラメーターはリスト型またはマップ型の属性をサポートしていません。 Note QueryFilter は項目が読み込まれた後に適用されます。フィルタ処理は追加の読み込みキャ パシティーユニットを消費しません。 QueryFilter マップ内の複数の条件を指定すると、デフォルトではすべての条件が true である必 要があります。言い換えると、条件は AND で結ばれます。(ConditionalOperator (p. 681) パラメー ターを使用して、条件を OR で結ぶこともできます。その場合、条件のすべてではなく、そのうち少 なくとも 1 つが true である必要があります。) ただし、QueryFilter ではキー属性を使用できないことに注意してください。パーティションキー またはソートキーにフィルタ条件を定義することはできません。 API Version 2012-08-10 687 Amazon DynamoDB 開発者ガイド QueryFilter 各 QueryFilter 要素は、次と併せて、比較する属性名で構成されます。 • AttributeValueList - 提供された属性に対して評価する 1 つまたは複数の値。リストの値の数値 は ComparisonOperator で指定される演算子によって異なります。 数値型の場合、値比較は数値です。 大なり、等しい、小なりの文字列値比較は、UTF-8 バイナリエンコードに基づきます。たとえ ば、a は A より大きく、a は B より大きい文字列です。 バイナリ型では、DynamoDB は、バイナリ値を比較する際にバイナリデータの各バイトを符号なし として扱います。 JSON でデータ型を指定する方法については、「DynamoDB 低レベル API (p. 68)」を参照してくだ さい。 • ComparisonOperator - 属性を評価するコンパレータ。たとえば、等しい、より大きい、より小さ い、などです。 次の比較演算子を使用できます。 EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | BETWEEN 代替として FilterExpression を使用する Music テーブルにクエリして、項目が返される前に条件を適用するとします。次のように QueryFilter パラメーターを指定して Query リクエストを使用できます。 { TableName: "Music", KeyConditions: { "Artist": { ComparisonOperator: AttributeValueList: } }, QueryFilter: { "Price": { ComparisonOperator: AttributeValueList: } } "EQ", [ "No One You Know" ] "GT", [ 1.00 ] } ただし、代わりに FilterExpression を使用できます。 { TableName: "Music", KeyConditionExpression: "Artist = :a", FilterExpression: "Price > :p", ExpressionAttributeValues: { ":p": 1.00, ":a": "No One You Know" } } API Version 2012-08-10 688 Amazon DynamoDB 開発者ガイド ScanFilter ScanFilter Scan オペレーションでは、ScanFilter がスキャン結果を評価して目的の値のみを返す条件です。 Note このパラメーターはリスト型またはマップ型の属性をサポートしていません。 ScanFilter マップ内の複数の条件を指定すると、デフォルトではすべての条件が true である必要が あります。言い換えると、条件は AND で結ばれます。(ConditionalOperator (p. 681) パラメーター を使用して、条件を OR で結ぶこともできます。その場合、条件のすべてではなく、そのうち少なく とも 1 つが true である必要があります。) 各 ScanFilter 要素は、次と併せて、比較する属性名で構成されます。 • AttributeValueList - 提供された属性に対して評価する 1 つまたは複数の値。リストの値の数値 は ComparisonOperator で指定される演算子によって異なります。 数値型の場合、値比較は数値です。 大なり、等しい、小なりの文字列値比較は、UTF-8 バイナリエンコードに基づきます。たとえ ば、a は A より大きく、a は B より大きい文字列です。 バイナリ型では、DynamoDB は、バイナリ値を比較する際にバイナリデータの各バイトを符号なし として扱います。 JSON でデータ型を指定する方法については、「DynamoDB 低レベル API (p. 68)」を参照してくだ さい。 • ComparisonOperator - 属性を評価するコンパレータ。たとえば、等しい、より大きい、より小さ い、などです。 次の比較演算子を使用できます。 EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | BETWEEN 代替として FilterExpression を使用する Music テーブルをスキャンして、項目が返される前に条件を適用するとします。次のように ScanFilter パラメーターを指定して Scan リクエストを使用できます。 { TableName:"Music", ScanFilter:{ "Genre":{ AttributeValueList:[ "Rock" ], ComparisonOperator:"EQ" } } } ただし、代わりに FilterExpression を使用できます。 { TableName:"Music", FilterExpression:"Genre = :g", API Version 2012-08-10 689 Amazon DynamoDB 開発者ガイド レガシー パラメータを使用した条件書き込み ExpressionAttributeValues:{ ":g":"Rock" } } レガシー パラメータを使用した条件書き込み このセクションでは、Expected、QueryFilter、および ScanFilter などのレガシーパラメータを 使用して条件を書き込む方法を説明します。 Note 新しいアプリケーションでは代わりに式パラメータを使用してください。詳細については、 「式を使用した項目の読み取りと書き込み (p. 210)」を参照してください。 単純な条件 属性値を使用して、テーブル属性に対する比較のための条件を記述できます。条件は常に true または false と評価され、次の演算子と値で構成されます。 • ComparisonOperator - 「より大きい」、「より小さい」、「等しい」などの演算子。 • AttributeValueList(省略可能) - 比較対象の属性値。使用する ComparisonOperator に応じ て、AttributeValueList に 1 つ、2 つ、またはそれ以上の値を指定できます。値を指定しない 場合もあります。 この後のセクションでは、さまざまな比較演算子について説明し、それらの演算子を条件に使用する 例を示します。 属性値を指定しない比較演算子 • NOT_NULL - 属性が存在する場合に true。 • NULL - 属性が存在しない場合に true。 これらの演算子を使用して、属性が存在するかどうかを確認します。比較対象の値がないた め、AttributeValueList を指定しないでください。 例 次の式では、Dimensions 属性が存在する場合に true と評価されます。 { "Dimensions": { ComparisonOperator: "NOT_NULL" } } 1 つの属性値を指定する比較演算子 • EQ - 属性が値と等しい場合に true。 AttributeValueList に指定できるのは、文字列型、数値型、バイナリ型、文字列セット、数値 セット、またはバイナリセットの 1 つの値だけです。リクエストで指定した型とは異なる型の値が 項目に含まれている場合、値は一致しません。たとえば、文字列 "3" は数値 3 と等しくありませ ん。また、数値 3 は数値セット [3, 2, 1] と等しくありません。 • NE - 属性が値に等しくない場合に true。 API Version 2012-08-10 690 Amazon DynamoDB 開発者ガイド レガシー パラメータを使用した条件書き込み AttributeValueList に指定できるのは、文字列型、数値型、バイナリ型、文字列セット、数値 セット、またはバイナリセットの 1 つの値だけです。リクエストで指定した型とは異なる型の値が 項目に含まれている場合、値は一致しません。 • LE - 属性が値以下の場合に true。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の 1 つの値だけ です(セット型は指定できません)。リクエストで指定した型とは異なる型の AttributeValue が項目に含まれている場合、値は一致しません。 • LT - 属性が値より小さい場合に true。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の 1 つの値だけ です(セット型は指定できません)。リクエストで指定した型とは異なる型の値が項目に含まれて いる場合、値は一致しません。 • GE - 属性が値以上の場合に true。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の 1 つの値だけ です(セット型は指定できません)。リクエストで指定した型とは異なる型の値が項目に含まれて いる場合、値は一致しません。 • GT - 属性が値よりも大きい場合に true。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の 1 つの値だけ です(セット型は指定できません)。リクエストで指定した型とは異なる型の値が項目に含まれて いる場合、値は一致しません。 • CONTAINS - 値がセットに含まれる場合、または値が別の値を含む場合に true。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の 1 つの値だけ です(セット型は指定できません)。比較する属性が文字列型の場合、部分文字列の一致があるこ とが確認されます。比較する属性がバイナリ型の場合、入力に一致する対象の属性のサブシーケン スがあることが確認されます。比較する属性がセットの場合、セットのいずれかの値と完全一致す ると、演算子は true と評価されます。 • NOT_CONTAINS - 値がセットに含まれない場合、または値が別の値を含まない場合に true。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の 1 つの値だけ です(セット型は指定できません)。比較する属性が文字列型の場合、部分文字列の一致がない ことが確認されます。比較する属性がバイナリ型の場合、入力に一致する対象の属性のサブシーケ ンスがないことが確認されます。比較する属性がセットの場合、セットのどの値とも完全一致しな いと、演算子は true と評価されます。 • BEGINS_WITH - 属性の先頭からの数文字が指定した値と一致した場合に true。この演算子を数値の 比較に使用しないでください。 AttributeValueList に指定できるのは、文字列型またはバイナリ型の 1 つの値だけです(数値 型またはセット型は指定できません)。比較対象の属性は、(数値型またはセット型ではなく)文 字列型またはバイナリ型である必要があります。 これらの演算子は属性と値の比較に使用してください。1 つの値で構成される AttributeValueList を指定する必要があります。ほとんどの演算子では、この値はスカラーであ ることが必要ですが、EQ と NE 演算子では、セットもサポートされています。 例 ここで示している式は次の場合に true と評価されます。 • 商品の価格が 100 より大きい。 { "Price": { API Version 2012-08-10 691 Amazon DynamoDB 開発者ガイド レガシー パラメータを使用した条件書き込み ComparisonOperator: "GT", AttributeValueList: [ 100 ] } } • 商品のカテゴリが「Bo」で始まる。 { "ProductCategory": { ComparisonOperator: "BEGINS_WITH", AttributeValueList: [ "Bo" ] } } • 商品の色が「Red」、「Green」、「Black」のいずれか。 { "Color": { ComparisonOperator: "EQ", AttributeValueList: [ [ "Black", "Red", "Green" ] ] } } Note セットデータ型を比較するとき、要素の順序は重要ではありません。DynamoDB では、リ クエストで指定した順序に関係なく、同じ値のセットを持つ項目のみが返されます。 2 つの属性値を指定する比較演算子 • BETWEEN - 値が下限から上限の範囲内にある場合に true(上限または下限に一致する場合も含 む)。 AttributeValueList には、同じ型(文字列、数値、またはバイナリ)の要素を 2 つ指定する必 要があります(セット型は指定できません)。対象の属性が一致するのは、対象の値が最初の要素 以上かつ 2 番目の要素以下の場合です。リクエストで指定した型とは異なる型の値が項目に含まれ ている場合、値は一致しません。 この演算子は、属性値が範囲内にあるかどうかを調べるために使用します。AttributeValueList には、同じ型(文字列、数値、またはバイナリ)のスカラー要素を 2 つ指定する必要があります。 例 商品の価格が 100~200 の範囲内にある場合、次の式は true と評価されます。 { "Price": { ComparisonOperator: "BETWEEN", AttributeValueList: [ 100, 200 ] } } API Version 2012-08-10 692 Amazon DynamoDB 開発者ガイド レガシー パラメータを使用した条件書き込み N 個の属性値を指定する比較演算子 • IN - 値が列挙リスト内のいずれかの値と等しい場合に true。列挙リストではスカラー値のみがサ ポートされています。セットはサポートされていません。比較する属性と一致するには、同じ型と 値であることが必要です。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の 1 つ以上の要 素です(セット型は指定できません)。これらの属性は、項目の既存のセット型以外の属性に対し て比較されます。入力セットのいずれかの要素が項目の属性に含まれる場合、式は true と評価され ます。 AttributeValueList に指定できるのは、文字列型、数値型、またはバイナリ型の 1 つ以上の値 です(セット型は指定できません)。比較対象の属性は、同じ型と正確な値に一致する必要があり ます。文字列は文字列セットには一致しません。 この演算子は、指定した値が列挙リストに含まれるかどうかを調べるために使用しま す。AttributeValueList には任意の個数のスカラー値を指定できますが、それらの値はすべて同 じデータ型であることが必要です。 例 Id の値が 201、203、または 205 の場合、次の式は true と評価されます。 { "Id": { ComparisonOperator: "IN", AttributeValueList: [ 201, 203, 205 ] } } 複数条件の使用 DynamoDB では、複数の条件を組み合わせて複雑な式を構成できます。そのためには、必要に応じて ConditionalOperator (p. 681) で複数の式を指定します。 デフォルトでは、複数の条件を指定した場合に式全体が true と評価されるには、すべての条件が true と評価される必要があります。つまり、暗黙的な AND 演算が行われます。 例 商品が 600 ページ以上の書籍(Book)である場合、次の式は true と評価されます。暗黙的な AND 演 算が行われるため、両方の条件が true と評価される必要があります。 { "ProductCategory": { ComparisonOperator: AttributeValueList: }, "PageCount": { ComparisonOperator: AttributeValueList: } "EQ", [ "Book" ] "GE", [ 600 ] } ConditionalOperator (p. 681) を使用して AND 演算を明示的に行うこともできます。次の例では、前 の例と同じ結果になります。 API Version 2012-08-10 693 Amazon DynamoDB 開発者ガイド レガシー パラメータを使用した条件書き込み { ConditionalOperator : "AND", "ProductCategory": { ComparisonOperator: "EQ", AttributeValueList: [ "Book" ] }, "PageCount": { ComparisonOperator: "GE", AttributeValueList: [ 600 ] } } ConditionalOperator を OR に設定することもできます。この場合、少なくとも 1 つの条件が true と評価される必要があります。 例 次の式は、商品がマウンテンバイク(Mountain)であるか、その名前が特定のブランド名であるか、 その価格が 100 よりも大きい場合に、true と評価されます。 { ConditionalOperator : "OR", "BicycleType": { ComparisonOperator: "EQ", AttributeValueList: [ "Mountain" ] }, "Brand": { ComparisonOperator: "EQ", AttributeValueList: [ "Brand-Company A" ] }, "Price": { ComparisonOperator: "GT", AttributeValueList: [ 100 ] } } Note 複雑な式では、条件は最初のものから最後のものまで順に処理されます。 AND と OR の両方を 1 つの式で使用することはできません。 その他の条件付き演算子 DynamoDB の以前のリリースでは、Expected パラメーターの動作は条件付き書き込みに対して異 なっていました。Expected マップの各項目は、確認する DynamoDB の属性名を表しており、次のオ プションと共に使用していました。 • Value - 属性に対して比較する値。 • Exists - オペレーションの試行前に値が存在するかどうかを調べます。 Value と Exists のオプションは引き続き DynamoDB でサポートされますが、可能なのは等価 条件、つまり属性が存在するかどうかのテストのみです。代わりに ComparisonOperator と AttributeValueList を使用することをお勧めします。これらのオプションを使用すると、より広 範な条件を作成できるためです。 API Version 2012-08-10 694 Amazon DynamoDB 開発者ガイド レガシー パラメータを使用した条件書き込み Example DeleteItem では、書籍が絶版になっているかどうかを確認し、この条件が true と評価された場合に のみ、その書籍を削除できます。次に示すのは、レガシー条件を使用した例です。 { TableName: "Product", Item: { "Id": 600, "Title": "Book 600 Title" }, Expected: { "InPublication": { Exists: true, Value : false } } } 次の例でも、同じ結果になりますが、レガシー条件を使用していません。 { TableName: "Product", Item: { "Id": 600, "Title": "Book 600 Title" }, Expected: { "InPublication": { ComparisonOperator: "EQ", AttributeValueList: [ false ] } } } API Version 2012-08-10 695 Amazon DynamoDB 開発者ガイド 現在の低レベル API バージョン (2012-08-10) Example PutItem オペレーションでは、同じプライマリキー属性を持つ既存の項目が上書きされないようにで きます。次に示すのは、レガシー条件を使用した例です。 { TableName: "Product", Item: { "Id": 500, "Title": "Book 500 Title" }, Expected: { "Id": { Exists: false } } } 次の例でも、同じ結果になりますが、レガシー条件を使用していません。 { TableName: "Product", Item: { "Id": 500, "Title": "Book 500 Title" }, Expected: { "Id": { ComparisonOperator: "NULL" } } } Note Expected マップの条件には、レガシーオプションである Value および Exists を、ComparisonOperator および AttributeValueList と一緒に使用しないでくださ い。一緒に使用すると、条件付き書き込みが失敗します。 現在の低レベル API バージョン (2012-08-10) 低レベル &DDB; API の現在のバージョンは 2012-08-10 です。 完全なドキュメントについては、 『Amazon DynamoDB API Reference』を参照してください 以下のオペレーションがサポートされています。 • BatchGetItem • BatchWriteItem • CreateTable • DeleteItem • DeleteTable • DescribeLimits • DescribeTable API Version 2012-08-10 696 Amazon DynamoDB 開発者ガイド 前バージョンの低レベル API (2011-12-05) • GetItem • ListTables • ListTagsOfResource • PutItem • Query • Scan • TagResource • UpdateItem • UpdateTable • UntagResource 前バージョンの低レベル API (2011-12-05) ここでは、前バージョンの DynamoDB 低レベル API (2011-12-05) で利用可能なオペレーションを文 書化します。 この 低レベル API のバージョンは、既存のアプリケーションとの下位互換性を確保す るために保持されています。 新しいアプリケーションでは、現在の API バージョン(2012-08-10)を使用してください。詳細につ いては、「現在の低レベル API バージョン (2012-08-10) (p. 696)」を参照してください。 Note 新しい DynamoDB の機能は前の API のバージョンにはバックポートされないため、アプリ ケーションを最新の API バージョン(2012-08-10)に移行することをお勧めします。 トピック • BatchGetItem (p. 697) • BatchWriteItem (p. 703) • CreateTable (p. 708) • DeleteItem (p. 713) • DeleteTable (p. 717) • DescribeTables (p. 721) • GetItem (p. 724) • ListTables (p. 726) • PutItem (p. 728) • Query (p. 734) • スキャン (p. 743) • UpdateItem (p. 754) • UpdateTable (p. 760) BatchGetItem Important ############## API ##### 2011-12-05 ################################## 現在の低レベル API のドキュメントについては、Amazon DynamoDB API Referenceを参照 してください。 API Version 2012-08-10 697 Amazon DynamoDB 開発者ガイド BatchGetItem 説明 BatchGetItem オペレーションは、プライマリキーを使用して複数のテーブルから複数の項目の属性 を返します。1 回のオペレーションで取り出すことができる項目の最大数は 100 です。また、取り出 される項目の数は、1 MB のサイズ制限を受けます。レスポンスサイズの制限を超えた場合、または、 テーブルのプロビジョニングされたスループットの超過や内部処理エラーが原因で一部の結果しか返 されなかった場合、DynamoDB は UnprocessedKeys 値を返します。この場合、オペレーションを やり直して次の項目から取得を再開することができます。DynamoDB は、ページごとに返される項目 の数を自動的に調整し、この制限を適用します。たとえば、100 項目を取り出すように指示した場合 でも、各項目のサイズが 50 KB の場合、20 個の項目と、結果の次のページを取得できるように適切 な UnprocessedKeys 値が返されます。必要に応じて、アプリケーションに独自のロジックを追加し て、結果のページを 1 つのセットにまとめることができます。 リクエストに含まれる各テーブルのプロビジョニングされたスループットが不十 分であることが原因で、項目をまったく処理できなかった場合、DynamoDB は ProvisionedThroughputExceededException エラーを返します。 Note デフォルトでは、BatchGetItem は、リクエストのすべてのテーブルに対して結果整合 性のある読み込みを実行します。整合性のある読み込みが必要な場合は、テーブル単位で ConsistentRead パラメータを true に設定できます。 BatchGetItem は、並列で項目をフェッチして、レスポンスのレイテンシーを最小限に抑え ます。 アプリケーションの設計にあたっては、DynamoDB によって返される属性の順序が保証され ないことに注意してください。リクエストで項目の AttributesToGet にプライマリキーの 値を追加すると、項目別にレスポンスを解析しやすくなります。 リクエストした項目が存在しない場合、レスポンスではその項目に関して何も返されませ ん。存在しない項目のリクエストは、読み込みのタイプに応じて最小の読み込みキャパシ ティーユニットを消費します。詳細については、「キャパシティーユニットの計算 (p. 181)」 を参照してください。 リクエスト 構文 // This header is abbreviated. For a sample of a complete header, see DynamoDB #### API (p. 68). POST / HTTP/1.1 x-amz-target: DynamoDB_20111205.BatchGetItem content-type: application/x-amz-json-1.0 {"RequestItems": {"Table1": {"Keys": [{"HashKeyElement": {"S":"KeyValue1"}, "RangeKeyElement": {"N":"KeyValue2"}}, {"HashKeyElement": {"S":"KeyValue3"}, "RangeKeyElement": {"N":"KeyValue4"}}, {"HashKeyElement": {"S":"KeyValue5"}, "RangeKeyElement": {"N":"KeyValue6"}}], "AttributesToGet":["AttributeName1", "AttributeName2", "AttributeName3"]}, "Table2": {"Keys": [{"HashKeyElement": {"S":"KeyValue4"}}, API Version 2012-08-10 698 Amazon DynamoDB 開発者ガイド BatchGetItem {"HashKeyElement": {"S":"KeyValue5"}}], "AttributesToGet": ["AttributeName4", "AttributeName5", "AttributeName6"] } } } 名前 説明 必須 RequestItems テーブル名とプライマリキーに よって取得する対応する項目の コンテナ。項目をリクエスト しているとき、各テーブル名 は、1 回のオペレーションにつ き一度だけ呼び出すことができ ます。 型: String デフォルト: なし はい Table 取得する項目を含んでいるテー ブルの名前。エントリは、ラベ ルなしで既存のテーブルを指定 する文字列です。 型: 文字列 デフォルト: なし はい Table:Keys 指定したテーブルの項目を定義 するプライマリキーの値。プラ イマリキーの詳細については、 「プライマリキー (p. 5)」を参 照してください。 型: キー はい Table:AttributesToGet 指定したテーブル内の属性名の 配列。属性名を省略した場合、 すべての属性が返されます。見 つからなかった属性は、結果に は表示されません。 型: 配列 いいえ Table:ConsistentRead true に設定した場合、整合性 のある読み込みが実行されま す。それ以外の場合は、結果整 合性が使用されます。 タイプ: ブール値 いいえ レスポンス 構文 HTTP/1.1 200 x-amzn-RequestId: 8966d095-71e9-11e0-a498-71d736f27375 content-type: application/x-amz-json-1.0 content-length: 855 API Version 2012-08-10 699 Amazon DynamoDB 開発者ガイド BatchGetItem {"Responses": {"Table1": {"Items": [{"AttributeName1": {"S":"AttributeValue"}, "AttributeName2": {"N":"AttributeValue"}, "AttributeName3": {"SS":["AttributeValue", "AttributeValue", "AttributeValue"]} }, {"AttributeName1": {"S": "AttributeValue"}, "AttributeName2": {"S": "AttributeValue"}, "AttributeName3": {"NS": ["AttributeValue", "AttributeValue", "AttributeValue"]} }], "ConsumedCapacityUnits":1}, "Table2": {"Items": [{"AttributeName1": {"S":"AttributeValue"}, "AttributeName2": {"N":"AttributeValue"}, "AttributeName3": {"SS":["AttributeValue", "AttributeValue", "AttributeValue"]} }, {"AttributeName1": {"S": "AttributeValue"}, "AttributeName2": {"S": "AttributeValue"}, "AttributeName3": {"NS": ["AttributeValue", "AttributeValue","AttributeValue"]} }], "ConsumedCapacityUnits":1} }, "UnprocessedKeys": {"Table3": {"Keys": [{"HashKeyElement": {"S":"KeyValue1"}, "RangeKeyElement": {"N":"KeyValue2"}}, {"HashKeyElement": {"S":"KeyValue3"}, "RangeKeyElement": {"N":"KeyValue4"}}, {"HashKeyElement": {"S":"KeyValue5"}, "RangeKeyElement": {"N":"KeyValue6"}}], "AttributesToGet":["AttributeName1", "AttributeName2", "AttributeName3"]} } } 名前 説明 Responses テーブル名とテーブルからの各項目の属性。 タイプ: マップ Table 項目を含んでいるテーブルの名前。エントリ は、ラベルなしでテーブルを指定する文字列で す。 タイプ: 文字列 Items オペレーションパラメータを満たす属性名と値 のコンテナ。 型: 属性名とそのデータ型と値のマップ。 API Version 2012-08-10 700 Amazon DynamoDB 開発者ガイド BatchGetItem 名前 説明 ConsumedCapacityUnits 各テーブルの消費された読み込みキャパシ ティーユニットの数。この値は、プロビジョ ニングされたスループットに対して適用され た数を示します。存在しない項目のリクエス トは、読み込みのタイプに応じて最小の読み 込みキャパシティーユニットを消費します。詳 細については、「テーブルの読み書き要件の指 定 (p. 179)」を参照してください。 型: 数値 UnprocessedKeys テーブルと、現在のレスポンスで処理さ れなかった個別のキーの配列を含んでいま す。レスポンスサイズの制限に達したこと が原因で処理されなかった可能性がありま す。UnprocessedKeys 値は、RequestItems パラメータと同じフォームです(これにより、 この値を後続の BatchGetItem オペレーション でそのまま使用できます)。詳細については、 前述の RequestItems パラメータを参照してく ださい。 型: 配列 UnprocessedKeys: Table: Keys 項目と項目に関連付けられた属性を定義するプ ライマリキー属性値。プライマリキーの詳細に ついては、「プライマリキー (p. 5)」を参照して ください。 型: 属性名と値のペアの配列 UnprocessedKeys: Table: AttributesToGet 指定したテーブル内の属性名。属性名を省略し た場合、すべての属性が返されます。見つから なかった属性は、結果には表示されません。 型: 属性名の配列 UnprocessedKeys: Table: ConsistentRead true に設定した場合、指定したテーブルに対し て整合性のある読み込みが使用されます。それ 以外の場合、結果整合性のある読み込みが使用 されます。 型: ブール値 特殊なエラー エラー 説明 ProvisionedThroughputExceededException プロビジョニングされたスループットの許容さ れている最大値を超えました。 例 次の例は、BatchGetItem オペレーションを使用した HTTP POST リクエストとレスポンスで す。AWS SDK を使用した例については、「DynamoDB での項目の操作 (p. 204)」を参照してくださ い。 API Version 2012-08-10 701 Amazon DynamoDB 開発者ガイド BatchGetItem リクエスト例 次のリクエスト例では、2 つの異なるテーブルから属性を取得します。 // This header is abbreviated. // For a sample of a complete header, see DynamoDB #### API (p. 68). POST / HTTP/1.1 x-amz-target: DynamoDB_20111205.BatchGetItem content-type: application/x-amz-json-1.0 content-length: 409 {"RequestItems": {"comp2": {"Keys": [{"HashKeyElement":{"S":"Julie"}},{"HashKeyElement": {"S":"Mingus"}}], "AttributesToGet":["user","friends"]}, "comp1": {"Keys": [{"HashKeyElement":{"S":"Casey"},"RangeKeyElement": {"N":"1319509152"}}, {"HashKeyElement":{"S":"Dave"},"RangeKeyElement": {"N":"1319509155"}}, {"HashKeyElement":{"S":"Riley"},"RangeKeyElement": {"N":"1319509158"}}], "AttributesToGet":["user","status"]} } } レスポンス例 次の例はレスポンスです。 HTTP/1.1 200 OK x-amzn-RequestId: GTPQVRM4VJS792J1UFJTKUBVV4KQNSO5AEMVJF66Q9ASUAAJG content-type: application/x-amz-json-1.0 content-length: 373 Date: Fri, 02 Sep 2011 23:07:39 GMT {"Responses": {"comp2": {"Items": [{"status":{"S":"online"},"user":{"S":"Casey"}}, {"status":{"S":"working"},"user":{"S":"Riley"}}, {"status":{"S":"running"},"user":{"S":"Dave"}}], "ConsumedCapacityUnits":1.5}, "comp2": {"Items": [{"friends":{"SS":["Elisabeth", "Peter"]},"user":{"S":"Mingus"}}, {"friends":{"SS":["Dave", "Peter"]},"user":{"S":"Julie"}}], "ConsumedCapacityUnits":1} }, "UnprocessedKeys":{} } API Version 2012-08-10 702 Amazon DynamoDB 開発者ガイド BatchWriteItem BatchWriteItem Important ############## API ##### 2011-12-05 ################################## 現在の低レベル API のドキュメントについては、Amazon DynamoDB API Referenceを参照 してください。 説明 このオペレーションでは、1 回の コールで複数のテーブルにまたがる複数の項目を入力または削除で きます。 1 つの項目をアップロードするには、PutItem を使用します。また、1 つの項目を削除するに は、DeleteItem を使用します。 ただし、大量のデータを Amazon EMR(Amazon EMR)からアッ プロードしたり、別のデータベースから DynamoDB にデータを移行したりするなど、大量のデータ をアップロードまたは削除する場合は、BatchWriteItem を使用すると効率的に実行できます。 Java などの言語を使用する場合、スレッドを使用して項目を並列でアップロードできます。この場 合、アプリケーションの処理はスレッド処理が加わってより複雑なものになります。他の言語はス レッド処理をサポートしていません。たとえば、PHP を使用している場合、項目を 1 つずつアップ ロードまたは削除する必要があります。どちらの場合でも、BatchWriteItem では、指定された入力 および削除オペレーションが並列で処理されるので、アプリケーションの処理を複雑なものにするこ となく、スレッドプールの利点に浴することができます。 BatchWriteItem オペレーションで指定された各入力と削除のコストは、消費されるキャパシティー ユニットの点では同じです。 ただし、BatchWriteItem は、指定されたオペレーションを並列で実 行するので、レイテンシーが短縮されます。 存在しない項目に対する削除オペレーションでは、1 書 き込みキャパシティーユニットを消費します。消費されるキャパシティーユニットの詳細について は、「DynamoDB でのテーブルの操作 (p. 178)」を参照してください。 BatchWriteItem を使用するときは、次の制限事項に注意してください。 • 1 つのリクエストの最大オペレーション数 – 合計で最大 25 個の入力または削除オペレーションを指 定できます。ただし、リクエストサイズの合計は 1 MB(HTTP ペイロード)以下にする必要があり ます。 • BatchWriteItem オペレーションは、項目を入力および削除する場合にのみ使用できます。既存の 項目を更新する場合は使用できません。 • アトミックオペレーションではありません – BatchWriteItem に指定する各オペレーションは アトミックですが、BatchWriteItem 全体では、アトミックオペレーションではなく、"ベスト エフォート" オペレーションです。つまり、BatchWriteItem リクエストでは、成功するオペ レーションと失敗するオペレーションがあります。失敗したオペレーションは、レスポンスの UnprocessedItems フィールドで返されます。失敗の原因として、テーブルに対して設定され たプロビジョニングされたスループットを超過したか、ネットワークエラーなどの一時的なエ ラーが考えられます。調査して、必要に応じてリクエストを再送信できます。通常、ループで BatchWriteItem を呼び出し、各反復で、未処理の項目の有無を確認し、その未処理の項目を指定 した新しい BatchWriteItem リクエストを送信します。 • 項目を返しません – BatchWriteItem は、大量のデータを効率的にアップロードすることを目的に 設計されています。これには、PutItem や DeleteItem などによって提供される高度な機能の一 部が備わっていません。 たとえば、DeleteItem では、レスポンスで削除された項目をリクエスト するためにリクエストの本文に ReturnValues フィールドを指定することをサポートしています。 BatchWriteItem オペレーションでは、レスポンスで項目を返しません。 • PutItem や DeleteItem とは異なり、BatchWriteItem では、オペレーションの各書き込みリク エストに条件を指定できません。 API Version 2012-08-10 703 Amazon DynamoDB 開発者ガイド BatchWriteItem • 属性値を null にすることはできません。文字列型およびバイナリ型の属性の長さは、ゼロより大き くする必要があります。セット型属性を空白にすることはできません。空白の値があるリクエスト は、ValidationException で拒否されます。 DynamoDB は、次の条件のいずれか 1 つでも当てはまる場合、バッチ書き込みオペレーション全体を 拒否します。 • BatchWriteItem リクエストに指定された 1 つ以上のテーブルが存在しない。 • リクエストの項目に指定されたプライマリキー属性が、対応するテーブルのプライマリキースキー マと一致しない。 • 同じ BatchWriteItem リクエストで、同じ項目に対して複数のオペレーションを実行しようとし ている。たとえば、同じ BatchWriteItem リクエストで、同じ項目を入力および削除することは できません。 • リクエストサイズの合計が 1 MB リクエストサイズ(HTTP ペイロード)制限を超えている。 • バッチの項目のいずれかが 64 KB 項目サイズ制限を超えている。 リクエスト 構文 // This header is abbreviated. For a sample of a complete header, see DynamoDB #### API (p. 68). POST / HTTP/1.1 x-amz-target: DynamoDB_20111205.BatchGetItem content-type: application/x-amz-json-1.0 { "RequestItems" : RequestItems } RequestItems { "TableName1" : "TableName2" : ... } [ Request, Request, ... ], [ Request, Request, ... ], Request ::= PutRequest | DeleteRequest PutRequest ::= { "PutRequest" : { "Item" : { "Attribute-Name1" : Attribute-Value, "Attribute-Name2" : Attribute-Value, ... } } } DeleteRequest ::= { "DeleteRequest" : { "Key" : PrimaryKey-Value API Version 2012-08-10 704 Amazon DynamoDB 開発者ガイド BatchWriteItem } } PrimaryKey-Value ::= HashTypePK | HashAndRangeTypePK HashTypePK ::= { "HashKeyElement" : Attribute-Value } HashAndRangeTypePK { "HashKeyElement" : Attribute-Value, "RangeKeyElement" : Attribute-Value, } Attribute-Value ::= String | Numeric| Binary | StringSet | NumericSet | BinarySet Numeric ::= { "N": "Number" } String ::= { "S": "String" } Binary ::= { "B": "Base64 encoded binary data" } StringSet ::= { "SS": [ "String1", "String2", ... ] } NumberSet ::= { "NS": [ "Number1", "Number2", ... ] } BinarySet ::= { "BS": [ "Binary1", "Binary2", ... ] } リクエストの本文で、RequestItems JSON オブジェクトは、実行するオペレーションを記述しま す。オペレーションはテーブル別にグループ化されます。BatchWriteItem を使用して、複数のテー ブルにまたがる複数の項目を更新または削除できます。 書き込みリクエストごとに、リクエストのタ イプ(PutItem、DeleteItem)とその後にオペレーションの詳細を指定する必要があります。 • PutRequest の場合、項目(つまり、属性とその値のリスト)を指定します。 • DeleteRequest の場合、プライマリキーの名前と値を指定します。 API Version 2012-08-10 705 Amazon DynamoDB 開発者ガイド BatchWriteItem レスポンス 構文 次に、レスポンスで返される JSON 本文の構文を示します。 { "Responses" : "UnprocessedItems" : ConsumedCapacityUnitsByTable RequestItems } ConsumedCapacityUnitsByTable { "TableName1" : { "ConsumedCapacityUnits", : NumericValue }, "TableName2" : { "ConsumedCapacityUnits", : NumericValue }, ... } RequestItems This syntax is identical to the one described in the JSON syntax in the request. 特殊なエラー このオペレーションに固有のエラーはありません。 例 次の例は、BatchWriteItem オペレーションの HTTP POST リクエストとレスポンスです。リクエス トでは、Reply テーブルと Thread テーブルに対して次のオペレーションを指定しています。 • Reply テーブルで項目を入力し、項目を削除する • Thread テーブルに項目を入力する AWS SDK を使用した例については、「DynamoDB での項目の操作 (p. 204)」を参照してください。 リクエスト例 // This header is abbreviated. For a sample of a complete header, see DynamoDB #### API (p. 68). POST / HTTP/1.1 x-amz-target: DynamoDB_20111205.BatchGetItem content-type: application/x-amz-json-1.0 { "RequestItems":{ "Reply":[ { "PutRequest":{ "Item":{ "ReplyDateTime":{ "S":"2012-04-03T11:04:47.034Z" }, "Id":{ "S":"DynamoDB#DynamoDB Thread 5" } API Version 2012-08-10 706 Amazon DynamoDB 開発者ガイド BatchWriteItem } } }, { "DeleteRequest":{ "Key":{ "HashKeyElement":{ "S":"DynamoDB#DynamoDB Thread 4" }, "RangeKeyElement":{ "S":"oops - accidental row" } } } } ], "Thread":[ { "PutRequest":{ "Item":{ "ForumName":{ "S":"DynamoDB" }, "Subject":{ "S":"DynamoDB Thread 5" } } } } ] } } レスポンス例 次のレスポンス例は、Thread テーブルと Reply テーブルの両方に対する入力オペレーションが成功 し、(テーブルのプロビジョニングされたスループットを超過したときに発生する調整などが原因 で)Reply テーブルに対する削除オペレーションが失敗したことを示しています。JSON レスポンス の次の点に注意してください。 • Responses オブジェクトは、Thread テーブルと Reply テーブルに対する入力オペレーションが 成功した結果、両方のテーブルで 1 キャパシティーユニットが消費されたことを示しています。 • UnprocessedItems オブジェクトは、Reply テーブルに対する削除オペレーションが失敗したこ とを示しています。新しい BatchWriteItem コールを実行して、この未処理のリクエストに対応 できます。 HTTP/1.1 200 OK x-amzn-RequestId: G8M9ANLOE5QA26AEUHJKJE0ASBVV4KQNSO5AEMVJF66Q9ASUAAJG Content-Type: application/x-amz-json-1.0 Content-Length: 536 Date: Thu, 05 Apr 2012 18:22:09 GMT { "Responses":{ "Thread":{ "ConsumedCapacityUnits":1.0 }, API Version 2012-08-10 707 Amazon DynamoDB 開発者ガイド CreateTable "Reply":{ "ConsumedCapacityUnits":1.0 } }, "UnprocessedItems":{ "Reply":[ { "DeleteRequest":{ "Key":{ "HashKeyElement":{ "S":"DynamoDB#DynamoDB Thread 4" }, "RangeKeyElement":{ "S":"oops - accidental row" } } } } ] } } CreateTable Important ############## API ##### 2011-12-05 ################################## 現在の低レベル API のドキュメントについては、Amazon DynamoDB API Referenceを参照 してください。 説明 CreateTable オペレーションは、新しいテーブルをアカウントに追加します。 テーブル名は、リクエストを発行している AWS アカウントに関連付けられたテーブルおよびリクエ ストを受け取る AWS リージョン(dynamodb.us-west-2.amazonaws.com) を使用する場合、Amazon S3 は仮想ホスティング形式のリクエストをデフォルトで米国東部 (バージニア北部) リージョンに ルーティングします。各 DynamoDB エンドポイントは完全に独立しています。たとえば、"MyTable" という名前のテーブルが 2 つあり、その 1 つが dynamodb.us-west-2.amazonaws.com にあり、もう 1 つが dynamodb.us-west-1.amazonaws.com にある場合、この 2 つのテーブルは完全に独立してお り、データを共有しません。 CreateTable オペレーションは、非同期ワークフローをトリガーして、テーブルの作成を開始しま す。DynamoDB は、テーブルが ACTIVE 状態になるまで、すぐにテーブルの状態(CREATING)を返 します。テーブルが ACTIVE 状態になると、データプレーンオペレーションを実行できます。 DescribeTables (p. 721) オペレーションを使用して、テーブルのステータスを確認します。 リクエスト 構文 // This header is abbreviated. // For a sample of a complete header, see DynamoDB #### API (p. 68). POST / HTTP/1.1 x-amz-target: DynamoDB_20111205.CreateTable API Version 2012-08-10 708 Amazon DynamoDB 開発者ガイド CreateTable content-type: application/x-amz-json-1.0 {"TableName":"Table1", "KeySchema": {"HashKeyElement": {"AttributeName":"AttributeName1","AttributeType":"S"}, "RangeKeyElement": {"AttributeName":"AttributeName2","AttributeType":"N"}}, "ProvisionedThroughput":{"ReadCapacityUnits":5,"WriteCapacityUnits":10} } 名前 説明 必須 TableName 作成するテーブルの名前。 使用できる文字は、a~z、A ~Z、0~9、'_'(アンダースコ ア)、'-'(ダッシュ)、および '.'(ドット)です。名前は 3~ 255 文字で指定します。 タイプ: 文字列 はい KeySchema テーブルのプライマリ キー(単純または複合)構 造。HashKeyElement の 名前と値のペアは必須で す。RangeKeyElement の名 前と値のペアはオプションです (複合プライマリキーの場合の み、必須)。プライマリキーの 詳細については、「プライマリ キー (p. 5)」を参照してくださ い。 プライマリキー要素の名前 は、1~255 文字の長さで、文 字に関する制限はありません。 AttributeType の有効な値 は、"S"(文字列)、"N"(数 値)、または "B"(バイナリ) です。 型: HashKeyElement のマッ プ、または複合プライマリキー の場合、HashKeyElement と RangeKeyElement のマップ はい API Version 2012-08-10 709 Amazon DynamoDB 開発者ガイド CreateTable 名前 説明 必須 ProvisionedThroughput 指定したテーブル の新しいスループッ ト。ReadCapacityUnits と WriteCapacityUnits の値で 構成されます。詳細について は、「テーブルの読み書き要件 の指定 (p. 179)」を参照してく ださい。 はい Note 現在の最大値および 最小値については、 「DynamoDB での制 限 (p. 558)」を参照し てください。 型: 配列 ProvisionedThroughput: ReadCapacityUnits DynamoDB が他のオペレー はい ションと負荷のバランスをとる までの、指定したテーブルに関 して 1 秒間に消費され
© Copyright 2024 Paperzz