Amazon DynamoDB
入门指南 (API Version 2012-08-10)
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。点 击 Getting Started with Amazon AWS to see specific differences applicable to the China (Beijing) Region.

步骤 4:查询和扫描数据

您可以使用 Query 方法来检索表中的数据。您必须指定分区键值;排序键是可选项。

Movies 表的主键由以下部分组成:

  • year - 分区键。属性类型是数字。

  • title - 排序键。属性类型是字符串。

要查找一年当中发行的所有电影,您只需指定 year 分区键属性。您可以添加 title 排序键属性,以根据某种条件 (作用于排序键属性) 来检索电影子集,例如查找 2014 年发行并且标题以字母“A”开头的电影。

Query 外,还可使用 Scan 方法检索所有表数据。

要了解有关查询和扫描数据的更多信息,请参阅 Amazon DynamoDB 开发人员指南 中的查询和扫描

步骤 4.1:查询

此步骤中包含的 C# 代码将执行以下查询:

  • 检索在 year 1985 发行的所有电影。

  • 检索在 year 1992 发行并且 title 以字母“A”到字母“L”开头的所有电影。

  1. 将以下程序复制到 Program.cs 文件中,替代其当前内容。

    Copy
    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Amazon; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.Model; using Amazon.DynamoDBv2.DocumentModel; namespace DynamoDB_intro { class Program { static string commaSep = ", "; static string movieFormatString = " \"{0}\", lead actor: {1}, genres: {2}"; static void Main(string[] args) { // Get an AmazonDynamoDBClient for the local DynamoDB database AmazonDynamoDBClient client = GetLocalClient(); // Get a Table object for the table that you created in Step 1 Table table = GetTableObject(client, "Movies"); if (table == null) { PauseForDebugWindow(); return; } /*----------------------------------------------------------------------- * 4.1.1: Call Table.Query to initiate a query for all movies with * year == 1985, using an empty filter expression. *-----------------------------------------------------------------------*/ Search search; try { search = table.Query(1985, new Expression()); } catch (Exception ex) { Console.WriteLine("\n Error: 1985 query failed because: " + ex.Message); PauseForDebugWindow(); return; } // Display the titles of the movies returned by this query List<Document> docList = new List<Document>(); Console.WriteLine("\n All movies released in 1985:" + "\n-----------------------------------------------"); do { try { docList = search.GetNextSet(); } catch (Exception ex) { Console.WriteLine("\n Error: Search.GetNextStep failed because: " + ex.Message); break; } foreach (var doc in docList) Console.WriteLine(" " + doc["title"]); } while (!search.IsDone); /*----------------------------------------------------------------------- * 4.1.2a: Call Table.Query to initiate a query for all movies where * year equals 1992 AND title is between "B" and "Hzzz", * returning the lead actor and genres of each. *-----------------------------------------------------------------------*/ Primitive y_1992 = new Primitive("1992", true); QueryOperationConfig config = new QueryOperationConfig(); config.Filter = new QueryFilter(); config.Filter.AddCondition("year", QueryOperator.Equal, new DynamoDBEntry[] { 1992 }); config.Filter.AddCondition("title", QueryOperator.Between, new DynamoDBEntry[] { "B", "Hzz" }); config.AttributesToGet = new List<string> { "title", "info" }; config.Select = SelectValues.SpecificAttributes; try { search = table.Query(config); } catch (Exception ex) { Console.WriteLine("\n Error: 1992 query failed because: " + ex.Message); PauseForDebugWindow(); return; } // Display the movie information returned by this query Console.WriteLine("\n\n Movies released in 1992 with titles between \"B\" and \"Hzz\" (Document Model):" + "\n-----------------------------------------------------------------------------"); docList = new List<Document>(); Document infoDoc; do { try { docList = search.GetNextSet(); } catch (Exception ex) { Console.WriteLine("\n Error: Search.GetNextStep failed because: " + ex.Message); break; } foreach (var doc in docList) { infoDoc = doc["info"].AsDocument(); Console.WriteLine(movieFormatString, doc["title"], infoDoc["actors"].AsArrayOfString()[0], string.Join(commaSep, infoDoc["genres"].AsArrayOfString())); } } while (!search.IsDone); /*----------------------------------------------------------------------- * 4.1.2b: Call AmazonDynamoDBClient.Query to initiate a query for all * movies where year equals 1992 AND title is between M and Tzz, * returning the genres and the lead actor of each. *-----------------------------------------------------------------------*/ QueryRequest qRequest = new QueryRequest { TableName = "Movies", ExpressionAttributeNames = new Dictionary<string, string> { { "#yr", "year" } }, ExpressionAttributeValues = new Dictionary<string, AttributeValue> { { ":y_1992", new AttributeValue { N = "1992" } }, { ":M", new AttributeValue { S = "M" } }, { ":Tzz", new AttributeValue { S = "Tzz" } } }, KeyConditionExpression = "#yr = :y_1992 and title between :M and :Tzz", ProjectionExpression = "title, info.actors[0], info.genres" }; QueryResponse qResponse; try { qResponse = client.Query(qRequest); } catch (Exception ex) { Console.WriteLine("\n Error: Low-level query failed, because: " + ex.Message); PauseForDebugWindow(); return; } // Display the movie information returned by this query Console.WriteLine("\n\n Movies released in 1992 with titles between \"M\" and \"Tzz\" (low-level):" + "\n-------------------------------------------------------------------------"); foreach (Dictionary<string, AttributeValue> item in qResponse.Items) { Dictionary<string, AttributeValue> info = item["info"].M; Console.WriteLine(movieFormatString, item["title"].S, info["actors"].L[0].S, GetDdbListAsString(info["genres"].L)); } } public static string GetDdbListAsString(List<AttributeValue> strList) { StringBuilder sb = new StringBuilder(); string str = null; AttributeValue av; for (int i = 0; i < strList.Count; i++) { av = strList[i]; if (av.S != null) str = av.S; else if (av.N != null) str = av.N; else if (av.SS != null) str = string.Join(commaSep, av.SS.ToArray()); else if (av.NS != null) str = string.Join(commaSep, av.NS.ToArray()); if (str != null) { if (i > 0) sb.Append(commaSep); sb.Append(str); } } return (sb.ToString()); } public static AmazonDynamoDBClient GetLocalClient() { // First, set up a DynamoDB client for DynamoDB Local AmazonDynamoDBConfig ddbConfig = new AmazonDynamoDBConfig(); ddbConfig.ServiceURL = "http://localhost:8000"; AmazonDynamoDBClient client; try { client = new AmazonDynamoDBClient(ddbConfig); } catch (Exception ex) { Console.WriteLine("\n Error: failed to create a DynamoDB client; " + ex.Message); return (null); } return (client); } public static Table GetTableObject(AmazonDynamoDBClient client, string tableName) { Table table = null; try { table = Table.LoadTable(client, tableName); } catch (Exception ex) { Console.WriteLine("\n Error: failed to load the 'Movies' table; " + ex.Message); return (null); } return (table); } public static void PauseForDebugWindow() { // Keep the console open if in Debug mode... Console.Write("\n\n ...Press any key to continue"); Console.ReadKey(); Console.WriteLine(); } } }

    注意

    • 在第一次查询中,要查找 1985 年发行的所有电影,空表达式表示不需要按主键的排序键部分进行筛选。

    • 在第二次查询中,使用 适用于 .NET 的 AWS 开发工具包 文档模型查询 1992 年发行并且标题以字母 A 到 L 开头的所有电影,我们只能查询顶级属性,因此必须检索整个 info 属性。然后,我们的显示代码将访问我们感兴趣的嵌套属性。

    • 在第三次查询中,我们使用低级 适用于 .NET 的 AWS 开发工具包 API,从而提高对返回内容的控制力。这次我们可以仅检索 info 属性中我们感兴趣的那些嵌套属性,也就是 info.genresinfo.actors[0]

  2. 编译并运行程序。

注意

前面的程序演示了如何按主键属性对表进行查询。在 DynamoDB 中,您也可以选择在表上创建一个或多个二级索引,并采用查询表的方法来查询这些索引。二级索引允许对非键属性进行查询,从而为您的应用程序带来额外的灵活性。有关更多信息,请参阅 Amazon DynamoDB 开发人员指南 中的二级索引

步骤 4.2:扫描

Scan 方法可读取整个表中的每个项目,并返回表中的所有数据。您可提供一个可选的 filter_expression,以便仅返回符合条件的项目。但是请注意,筛选条件仅在扫描整个表后进行应用。

以下程序将扫描整个 Movies 表,表中包含约 5000 个项目。扫描时可指定可选筛选条件,以便仅检索 20 世纪 50 年代以来的电影 (约 100 个项目),同时舍弃所有其他项目。

  1. 将以下程序复制到 Program.cs 文件中,替代其当前内容。

    Copy
    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Amazon; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.Model; using Amazon.DynamoDBv2.DocumentModel; namespace DynamoDB_intro { class Program { static void Main(string[] args) { // Get an AmazonDynamoDBClient for the local DynamoDB database AmazonDynamoDBClient client = GetLocalClient(); // Get a Table object for the table that you created in Step 1 Table table = GetTableObject(client, "Movies"); if (table == null) { PauseForDebugWindow(); return; } /*----------------------------------------------------------------------- * 4.2a: Call Table.Scan to return the movies released in the 1950's, * displaying title, year, lead actor and lead director. *-----------------------------------------------------------------------*/ ScanFilter filter = new ScanFilter(); filter.AddCondition("year", ScanOperator.Between, new DynamoDBEntry[] { 1950, 1959 }); ScanOperationConfig config = new ScanOperationConfig { AttributesToGet = new List<string> { "year, title, info" }, Filter = filter }; Search search = table.Scan(filter); // Display the movie information returned by this query Console.WriteLine("\n\n Movies released in the 1950's (Document Model):" + "\n--------------------------------------------------"); List<Document> docList = new List<Document>(); Document infoDoc; string movieFormatString = " \"{0}\" ({1})-- lead actor: {2}, lead director: {3}"; do { try { docList = search.GetNextSet(); } catch (Exception ex) { Console.WriteLine("\n Error: Search.GetNextStep failed because: " + ex.Message); break; } foreach (var doc in docList) { infoDoc = doc["info"].AsDocument(); Console.WriteLine(movieFormatString, doc["title"], doc["year"], infoDoc["actors"].AsArrayOfString()[0], infoDoc["directors"].AsArrayOfString()[0]); } } while (!search.IsDone); /*----------------------------------------------------------------------- * 4.2b: Call AmazonDynamoDBClient.Scan to return all movies released * in the 1960's, only downloading the title, year, lead * actor and lead director attributes. *-----------------------------------------------------------------------*/ ScanRequest sRequest = new ScanRequest { TableName = "Movies", ExpressionAttributeNames = new Dictionary<string, string> { { "#yr", "year" } }, ExpressionAttributeValues = new Dictionary<string, AttributeValue> { { ":y_a", new AttributeValue { N = "1960" } }, { ":y_z", new AttributeValue { N = "1969" } }, }, FilterExpression = "#yr between :y_a and :y_z", ProjectionExpression = "#yr, title, info.actors[0], info.directors[0]" }; ScanResponse sResponse; try { sResponse = client.Scan(sRequest); } catch (Exception ex) { Console.WriteLine("\n Error: Low-level scan failed, because: " + ex.Message); PauseForDebugWindow(); return; } // Display the movie information returned by this scan Console.WriteLine("\n\n Movies released in the 1960's (low-level):" + "\n-------------------------------------------"); foreach (Dictionary<string, AttributeValue> item in sResponse.Items) { Dictionary<string, AttributeValue> info = item["info"].M; Console.WriteLine(movieFormatString, item["title"].S, item["year"].N, info["actors"].L[0].S, info["directors"].L[0].S); } } public static AmazonDynamoDBClient GetLocalClient() { // First, set up a DynamoDB client for DynamoDB Local AmazonDynamoDBConfig ddbConfig = new AmazonDynamoDBConfig(); ddbConfig.ServiceURL = "http://localhost:8000"; AmazonDynamoDBClient client; try { client = new AmazonDynamoDBClient(ddbConfig); } catch (Exception ex) { Console.WriteLine("\n Error: failed to create a DynamoDB client; " + ex.Message); return (null); } return (client); } public static Table GetTableObject(AmazonDynamoDBClient client, string tableName) { Table table = null; try { table = Table.LoadTable(client, tableName); } catch (Exception ex) { Console.WriteLine("\n Error: failed to load the 'Movies' table; " + ex.Message); return (null); } return (table); } public static void PauseForDebugWindow() { // Keep the console open if in Debug mode... Console.Write("\n\n ...Press any key to continue"); Console.ReadKey(); Console.WriteLine(); } } }

    在代码中,请注意以下情况:

    • 第一次扫描使用 适用于 .NET 的 AWS 开发工具包 文档模型扫描 Movies 表并返回 20 世纪 50 年代发行的电影。由于文档模型不支持 AttributesToGet 字段中的嵌套属性,所以我们必须下载整个 info 属性才能访问男主角和导演信息。

    • 第二次扫描使用 适用于 .NET 的 AWS 开发工具包 低级 API 扫描 Movies 表并返回 20 世纪 60 年代发行的电影。在这种情况下,我们可以仅下载 info 中我们感兴趣的那些属性值,也就是 info.actors[0]info.directors[0]

  2. 编译并运行程序。

注意

您还可以对已在表上创建的任意二级索引使用 Scan 操作。有关更多信息,请参阅 Amazon DynamoDB 开发人员指南 中的二级索引