Amazon SDK for .NET 中的 Table.Query 方法 - Amazon DynamoDB
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

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