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

查询表和索引:Java

您可以使用 Query 操作查询表或二级索引。您必须提供分区键值和相等条件。如果表或索引具有排序键,则可通过提供排序键值和条件来优化结果。

注意

适用于 Java 的开发工具包 还提供一个对象持久化模型,可用来将客户端类映射到 DynamoDB 表。该方法可以减少您必须编写的代码数量。有关更多信息,请参阅 Java:DynamoDBMapper

下面是使用 AWS SDK for Java 文档 API 检索项目的步骤。

  1. 创建 DynamoDB 类的实例。

  2. 创建 Table 类的实例来代表要处理的表。

  3. 调用 Table 实例的 query 方法。您必须指定要检索的项目的分区键值,以及任何可选的查询参数。

响应包括可以提供由查询返回的所有项目的 ItemCollection 对象。

以下 Java 代码段演示了上述任务。该代码段假定您有一个 Reply 表来存储论坛话题的回复。有关更多信息,请参阅 创建表并加载示例数据

Reply ( Id, ReplyDateTime, ... )

每个论坛话题都有一个唯一 ID,并且可以有 0 个或更多个回复。因此,Reply 表的 Id 属性由论坛名称和论坛主题构成。表的复合主键由 Id (分区键) 和 ReplyDateTime (排序键) 组成。

以下查询检索特定话题主题的所有回复。执行此查询需要使用表名称和主题值。

Copy
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 方法支持多个可选参数。举例来说,您可以通过指定条件来缩小之前查询中的结果范围以返回过去两周内的回复。这一条件称为排序键条件,因为 DynamoDB 会根据主键的排序键来评估您指定的查询条件。您可以指定其他可选参数以便只检索查询结果项目中特定的属性列表。

以下 Java 代码段检索过去 15 天内发布的论坛话题回复。该代码段使用以下实例和方法指定可选参数:

  • KeyConditionExpression,用于检索来自特定开发论坛的回复 (分区键) 以及该组项目内过去 15 天内发布的回复 (排序键)。

  • 一个 FilterExpression,用于仅返回来自特定用户的回复。在处理查询后并在结果返回该用户之前应用筛选器。

  • 一个 ValueMap,用于定义 KeyConditionExpression 占位符的实际值。

  • 一个 ConsistentRead,在设置为 true 时将请求强一致性读取。

此代码段使用 QuerySpec 对象,该对象提供对所有低级查询输入参数的访问。

Copy
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。然后,您可以逐步处理结果,每次处理一页,直至完成所有页面。

以下 Java 代码段修改上面显示的查询规范。此时,查询规范使用 withMaxPageSize 方法。Page 类提供了迭代器,允许代码处理每一页上的项目。

Copy
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 进行查询

下面的表存储关于论坛集合的信息。有关更多信息,请参阅 创建表并加载示例数据

注意

适用于 Java 的开发工具包 还提供一个对象持久化模型,可用来将客户端类映射到 DynamoDB 表。该方法可以减少您必须编写的代码数量。有关更多信息,请参阅 Java:DynamoDBMapper

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

在该 Java 代码示例中,您执行各种操作来查找论坛“'DynamoDB”中“DynamoDB Thread 1”这一话题的回复。

  • 查找话题的回复。

  • 在回复中查找线索,指定结果中每页上项目的数量限制。如果结果集中的项目数超过了页面大小,则您只能获得第一页的结果。此编码模式可确保您的代码处理查询结果中的所有页面。

  • 查找过去 15 天内的回复。

  • 查找特定日期范围内的回复。

    之前的两个查询都演示了如何指定排序键条件来缩小查询结果范围以及如何使用其他可选查询参数。

注意

此代码示例假定您已按照 创建表并加载示例数据 部分的说明,为您的账户将数据加载到了 DynamoDB 中。

有关运行以下示例的分步说明,请参阅 Java 代码示例

Copy
// Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Apache License, Version 2.0. 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()); } } }