AWS SDK for .NET での Table.Query メソッド - Amazon DynamoDB

AWS SDK for .NET での Table.Query メソッド

Query メソッドを使用すると、テーブルのクエリを行うことができます。複合プライマリキー (パーティションキーおよびソートキー) があるテーブルにのみ、クエリを実行できます。テーブルのプライマリキーがパーティションキーだけで構成されている場合、Query オペレーションはサポートされていません。デフォルトでは、Query の内部で結果整合性のあるクエリが実行されます。整合性モデルの詳細については、「読み込み整合性」を参照してください。

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 のオプションパラメータを指定することもできます。すべてのパラメータのリストは、「クエリ」でご確認ください。オプションパラメータを指定するには、次のオーバーロードを使用して QueryOperationConfig オブジェクトを指定する必要があります。

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 System; using System.Collections.Generic; using System.Linq; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DocumentModel; using Amazon.Runtime; using Amazon.SecurityToken; namespace com.amazonaws.codesamples { class MidLevelQueryAndScan { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { 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>(); 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); 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); } } } }