テーブルおよびインデックスにクエリを実行: Java - Amazon DynamoDB

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

テーブルおよびインデックスにクエリを実行: Java

Query オペレーションを使用すると、Amazon DynamoDB でテーブルまたはセカンダリインデックスのクエリを実行できます。この関数ではパーティションキー値と等価条件を指定する必要があります。テーブルまたはインデックスにソートキーがある場合は、ソートキー値と条件を指定することで結果を絞り込むことができます。

注記

にはオブジェクト永続性モデル AWS SDK for Java も用意されており、クライアント側のクラスを DynamoDB テーブルにマッピングできます。この方法により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java 1.x: DynamoDBMapper」を参照してください。

AWS SDK for Java ドキュメント API を使用して項目を取得する手順を次に示します。

  1. DynamoDB クラスのインスタンスを作成します。

  2. 操作対象のテーブルを表すために、Table クラスのインスタンスを作成します。

  3. query インスタンスの Table メソッドを呼び出します。任意のオプションクエリパラメータとともに、取得する項目のパーティションキー値を指定する必要があります。

応答には、クエリによって返されたすべての項目を示す ItemCollection オブジェクトが含まれています。

以下の Java コード例は、前述のタスクの例です。この例では、フォーラムスレッドへの返信を格納する Reply テーブルがあることを前提としています。詳細については、「DynamoDB でのコード例用のテーブルの作成とデータのロード」を参照してください。

Reply ( Id, ReplyDateTime, ... )

各フォーラムスレッドには一意の ID があり、0 またはそれ以上の返信を受け取ることができます。つまり、Id テーブルの Reply 属性は、フォーラム名とフォーラムの件名の両方で構成されています。 Id (パーティションキー) と ReplyDateTime (ソートキー) が、テーブルの複合プライマリキーを構成しています。

次のクエリでは、特定のスレッド件名に対するすべての返信を取り出します。このクエリでは、テーブル名と Subject の両方の値が必要になります。

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard() .withRegion(Regions.US_WEST_2).build(); DynamoDB dynamoDB = new DynamoDB(client); 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 入力パラメータにアクセスできる Query オブジェクトを使用します。

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 を使用したクエリ

以下のテーブルには、フォーラムのコレクションに関する情報が格納されています。詳細については、「DynamoDB でのコード例用のテーブルの作成とデータのロード」を参照してください。

注記

SDK for Java には、オブジェクト永続性モデルも用意されています。このモデルにより、クライアント側のクラスを DynamoDB テーブルにマッピングできます。この方法により、記述する必要のあるコードの量を減らすことができます。詳細については、「Java 1.x: DynamoDBMapper」を参照してください。

Forum ( Name, ... ) Thread ( ForumName, Subject, Message, LastPostedBy, LastPostDateTime, ...) Reply ( Id, ReplyDateTime, Message, PostedBy, ...)

この Java コードの例では、「DynamoDB」フォーラムの「DynamoDB Thread 1」スレッドに対するさまざまな返信の検索を実行します。

  • スレッドに対する返信を検索します。

  • 結果のページあたりの項目数に対する制限を指定して、スレッドへの返信を探します。結果セットの項目数がページサイズを超えた場合は、結果の最初のページだけが得られます。このコーディングパターンによって、確実にクエリ結果の全ページがコードで処理されます。

  • 過去 15 日間の返信を検索します。

  • 特定の日付範囲の返信を検索します。

    前述の 2 つのクエリはどちらも、ソートキー条件を指定してクエリ結果を絞り込む方法、必要に応じてその他のクエリパラメータを使用する方法を示しています。

注記

このコード例では、アカウントの DynamoDB に対し、DynamoDB でのコード例用のテーブルの作成とデータのロード セクションの手順に従ってデータが既にロードされていることを前提としています。

次の例を実行する step-by-step 手順については、「」を参照してくださいJava コードの例

package com.amazonaws.codesamples.document; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; import com.amazonaws.services.dynamodbv2.document.DynamoDB; import com.amazonaws.services.dynamodbv2.document.Item; import com.amazonaws.services.dynamodbv2.document.ItemCollection; import com.amazonaws.services.dynamodbv2.document.Page; import com.amazonaws.services.dynamodbv2.document.QueryOutcome; import com.amazonaws.services.dynamodbv2.document.Table; import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec; import com.amazonaws.services.dynamodbv2.document.utils.ValueMap; public class DocumentAPIQuery { static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build(); static DynamoDB dynamoDB = new DynamoDB(client); 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:"); // 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-MM-dd'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("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); String startDate = df.format(startDateMilli); 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()); } } }