AWS SDK for .NET 中的 Table.Query 方法 - Amazon DynamoDB

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

AWS SDK for .NET 中的 Table.Query 方法

您可以使用 Query 方法查询表。您只能查询具有复合主键(分区键和排序键)的表。如果表的主键只有分区键,则不支持 Query 操作。默认情况下,Query 会在内部执行查询,且采用最终一致性。要了解一致性模型,请参阅读取一致性

Query 方法提供两个重载。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 数据元。现在,您能够以迭代方式调用 Search.GetNextSet 方法,一次检索一页结果(如以下 C# 代码示例所示)。代码会为查询返回的每个项目打印属性值。

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 数据元。

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 天内发布的论坛话题回复。

      此查询运行两次。在第一次 Table.Query 调用中,示例只提供必需的查询参数。在第二次 Table.Query 调用中,您提供了可选查询参数来请求强一致性读取和要检索的一系列属性。

    • 查找一段时期内发布的论坛话题回复。

      此查询使用 Between 查询运算符来查找两个日期之间发布的回复。

  • 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); } } } }