Amazon DynamoDB
开发人员指南 (API Version 2012-08-10)
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。请点击 Amazon AWS 入门,可查看中国地区的具体差异

使用查询

Query 操作基于主键值查找项目。您可查询具有复合主键 (分区键和排序键) 的任何表或二级索引。

您必须提供分区键属性的名称以及该属性的一个值。Query 将返回具有该分区键值的所有项目。您可以选择提供排序键属性,并使用比较运算符来优化搜索结果。

键条件表达式

要指定搜索条件,请使用键条件表达式 - 用于确定要从表或索引中读取的项目的字符串。您必须指定分区键名称和值作为等式条件。您可选择为排序键提供另一个条件(如果有)。排序键条件必须使用下列比较运算符之一:

  • a = b - 如果属性 a 等于值 b,则为 true

  • a < b - 如果 a 小于 b 则为 true

  • a <= b - 如果 a 小于或等于 b 则为 true

  • a > b - 如果 a 大于 b 则为 true

  • a >= b - 如果 a 大于或等于 b 则为 true

  • a BETWEEN b AND c - 如果 a 大于或等于 b 且小于或等于 c,则为 true。

以下函数也受支持:

  • begins_with (a, substr) - 如果属性 a 的值以特定子字符串开头,则为 true。

以下 AWS CLI 示例将演示键条件表达式的用法。请注意,这些表达式使用占位符(例如 :name:sub)而不是实际的值。有关更多信息,请参阅表达式属性名称表达式属性值

Thread 表中查询特定的 ForumName(分区键)。具有 ForumName 值的所有项目将由查询进行读取,因为排序键 (Subject) 未包括在 KeyConditionExpression 中。

Copy
aws dynamodb query \ --table-name Thread \ --key-condition-expression "ForumName = :name" \ --expression-attribute-values '{":name":{"S":"Amazon DynamoDB"}}'

Thread 表中查询特定的 ForumName(分区键),但这一次仅返回具有给定 Subject(排序键)的项目。

Copy
aws dynamodb query \ --table-name Thread \ --key-condition-expression "ForumName = :name and Subject = :sub" \ --expression-attribute-values file://values.json

--expression-attribute-values 的参数存储在文件 values.json 中:

Copy
{ ":name":{"S":"Amazon DynamoDB"}, ":sub":{"S":"DynamoDB Thread 1"} }

Reply 表中查询特定的 Id(分区键),但仅返回其 ReplyDateTime(排序键)以特定字符开头的项目。

Copy
aws dynamodb query \ --table-name Reply \ --key-condition-expression "Id = :id and begins_with(ReplyDateTime, :dt)" \ --expression-attribute-values file://values.json

--expression-attribute-values 的参数存储在文件 values.json 中:

Copy
{ ":id":{"S":"Amazon DynamoDB#DynamoDB Thread 1"}, ":dt":{"S":"2015-09"} }

您可以在键条件表达式中使用任意属性名称,前提是第一个字符是 a-zA-Z,第二个字符(如果有)是 a-zA-Z0-9。此外,属性名称不得为 DynamoDB 保留关键字。(有关这些保留关键字的完整列表,请参阅DynamoDB 中的保留关键字。)如果属性名称不满足这些要求,则需要将表达式属性名称定义为占位符。有关更多信息,请参阅 表达式属性名称

对于具有给定分区键值的项目,DynamoDB 会将这些项目存储在紧邻位置并按照排序键值对其进行排序。在 Query 操作中,DynamoDB 按照排序顺序检索项目,然后使用 KeyConditionExpression 和可能存在的任何 FilterExpression 处理项目。只有在此时才会将 Query 结果发送回客户端。

Query 操作始终返回结果集。如果未找到完全匹配项目,则结果集将为空。

Query 结果始终按排序键值排序。如果排序键的数据类型是数字,则会按数字顺序返回结果;否则,会按 UTF-8 字节的顺序返回结果。默认情况下,系统按升序排序。要颠倒顺序,请将 ScanIndexForward 参数设置为 false

单个 Query 操作最多可检索 1 MB 的数据。在向结果应用任何 FilterExpression 之前,将应用此限制。如果 LastEvaluatedKey 包含在响应中且为非 null 值,则您将需要为结果集分页(请参阅为结果分页)。

Query 的筛选表达式

如果您需要进一步优化 Query 结果,您可以选择性地提供筛选表达式。筛选表达式 可确定 Query 结果中应返回给您的项目。所有其他结果将会丢弃。

筛选表达式在 Query 已完成但结果尚未返回时应用。因此,无论是否存在筛选表达式,Query 都将占用同等数量的读取容量。

Query 操作最多可检索 1 MB 的数据。此限制在计算筛选表达式之前应用。

筛选表达式不得包含分区键或排序键属性。您需要在关键字条件表达式而不是筛选表达式中指定这些属性。

筛选表达式的语法与条件表达式的相同。筛选表达式可使用的比较运算符、函数和逻辑运算符与条件表达式可使用的相同。有关更多信息,请参阅 条件表达式

以下 AWS CLI 示例在 Thread 表中查询特定 ForumName (分区键) 和 Subject (排序键)。在找到的项目中,仅返回最热门的讨论线索 - 换言之,仅返回 Views 数量超过特定值的线索。

Copy
aws dynamodb query \ --table-name Thread \ --key-condition-expression "ForumName = :fn" \ --filter-expression "#v >= :num" \ --expression-attribute-names '{"#v": "Views"}' \ --expression-attribute-values file://values.json

--expression-attribute-values 的参数存储在文件 values.json 中:

Copy
{ ":fn":{"S":"Amazon DynamoDB#DynamoDB Thread 1"}, ":num":{"N":"3"} }

请注意,Views 在 DynamoDB 中是一个保留关键字 (请参阅 DynamoDB 中的保留关键字),因此本示例使用 #v 作为占位符。有关更多信息,请参阅 表达式属性名称

注意

筛选表达式将从 Query 结果集中删除项目。在您预计会检索到大量项目并且还需要丢弃其中大多数项目的情况下,请尽量避免使用 Query

限制结果集中的项目数

Query 操作可让您限制结果中返回的项目数。为此,请将 Limit 参数设置为您需要的最大项目数。

例如,假设您对某个表进行 QueryLimit 值为 6,并且没有筛选表达式。Query 结果将包含表中与请求中的键条件表达式匹配的前 6 个项目。

现在假设您向 Query 添加了一个筛选表达式。在这种情况下,DynamoDB 将向返回的前 6 个项目应用筛选表达式,并放弃不匹配的项目。最终的 Query 结果将包含 6 个或更少的项目,具体取决于筛选出的项目数。

为结果分页

DynamoDB 将对来自 Query 操作的结果进行分页。利用分页,Query 结果将分成若干“页”大小为 1 MB (或更小) 的数据。应用程序可以先处理第一页结果,然后处理第二页结果,依此类推。

单次 Query 只会返回符合 1 MB 大小限制的结果集。要确定是否存在更多结果,并一次检索一页结果,应用程序应执行以下操作:

  1. 检查低级别 Query 结果:

    • 如果结果包含 LastEvaluatedKey 元素,请继续步骤 2。

    • 如果结果中没有 LastEvaluatedKey,则表示没有其他要检索的项目。

  2. 使用与上一个 Scan 请求相同的参数构造新的 Query 请求 - 但这一次,请选取步骤 1 中的 LastEvaluatedKey 值并将其用作新的 Query 请求中的 ExclusiveStartKey 参数。

  3. 运行新的 Query 请求。

  4. 前往步骤 1。

换言之,Query 响应中的 LastEvaluatedKey 应该用作下一 Query 请求的 ExclusiveStartKey。如果 Query 响应中没有 LastEvaluatedKey 元素,则表示您已检索最后一页结果。(检查是否没有 LastEvaluatedKey 是确定您是否已到达结果集末尾的唯一方式。)

您可以使用 AWS CLI 查看此行为。CLI 向 DynamoDB 反复发送低级别 Query 请求,直到结果中不再有 LastEvaluatedKey。考虑以下 AWS CLI 示例,此示例检索特定年份的电影标题:

Copy
aws dynamodb query --table-name Movies \ --projection-expression "title" \ --key-condition-expression "#y = :yyyy" \ --expression-attribute-names '{"#y":"year"}' \ --expression-attribute-values '{":yyyy":{"N":"1989"}}' \ --page-size 5 \ --debug

通常,AWS CLI 将自动处理分页;但在此示例中,CLI 的 --page-size 参数将限制每页的项目数。--debug 参数输出有关请求和响应的低级别信息。

如果您运行该示例,DynamoDB 的首次响应类似如下内容:

Copy
2017-07-07 11:13:15,603 - MainThread - botocore.parsers - DEBUG - Response body: b'{"Count":5,"Items":[{"title":{"S":"Always"}},{"title":{"S":"Back to the Future Part II"}}, {"title":{"S":"Batman"}},{"title":{"S":"Bill & Ted\'s Excellent Adventure"}},{"title":{"S":"Black Rain"}}], "LastEvaluatedKey":{"year":{"N":"1989"},"title":{"S":"Black Rain"}}, "ScannedCount":5}

响应中的 LastEvaluatedKey 指示并未检索所有项目。随后,AWS CLI 会将另一个 Query 请求发送到 DynamoDB。此请求和响应模式继续,直到收到最终响应:

Copy
2017-07-07 11:13:16,291 - MainThread - botocore.parsers - DEBUG - Response body: b'{"Count":2,"Items":[{"title":{"S":"Uncle Buck"}},{"title":{"S":"Weekend at Bernie\'s"}}], "ScannedCount":2}'

如果不存在 LastEvaluatedKey,则表示没有其他要检索的项目。

注意

AWS 开发工具包处理低级别的 DynamoDB 响应 (包括是否存在 LastEvaluatedKey),并提供各种抽象概念对 Query 结果进行分页。例如,适用于 Java 的开发工具包 文档接口提供 java.util.Iterator 支持,以便您能够一次处理一个结果。

对于各种编程语言的代码示例,请参阅本地化的 Amazon DynamoDB 入门指南 和 AWS 开发工具包文档。

对结果中的项目进行计数

除了与您的条件匹配的项目之外,Query 响应还包含以下元素:

  • ScannedCount - 在应用筛选表达式 (如果有) 之前 与关键字条件表达式匹配的项目的数量。

  • Count - 在应用筛选表达式 (如果有) 之后 剩余的项目的数量。

注意

如果您不使用筛选表达式,那么 ScannedCountCount 将具有相同的值。

如果 Query 结果集的大小大于 1 MB,则 ScannedCountCount 将仅表示项目总数的部分计数。您需要执行多次 Query 操作才能检索所有结果 (请参阅为结果分页)。

所有 Query 响应都将包含由该特定 Query 请求处理的项目的 ScannedCountCount。要获取所有 Query 请求的总和,您可以对 ScannedCountCount 记录流水账。

Query 占用的容量单位

您可对任何表或二级索引运行 Query,前提是它具有复合主键 (分区键和排序键)。Query 操作将占用读取容量单位,如下所示:

如果对...进行 Query DynamoDB 将占用...的读取容量单位
Table 表的预置读取容量。
Global secondary index 索引的预置读取容量。
本地二级索引 基表的预置读取容量。

默认情况下,Query 操作不会返回任何有关它占用的读取容量大小的数据。但是,您可在 Query 请求中指定 ReturnConsumedCapacity 参数以获取此信息。下面是 ReturnConsumedCapacity 的有效设置:

  • NONE - 未返回任何已占用容量数据。(这是默认值。)

  • TOTAL - 响应包含占用的读取容量单位的总数。

  • INDEXES - 响应显示占用的读取容量单位的总数,以及访问的每个表和索引的占用容量。

DynamoDB 将基于项目大小而不是返回到应用程序的数据量来确定占用的读取容量单位数。因此,无论您是请求所有属性 (默认行为) 还是只请求部分属性 (使用投影表达式),占用的容量单位数都是相同的。无论您是否使用筛选表达式,该数量也是相同的。

Query 的读取一致性

默认情况下,Query 操作将执行最终一致性读取。这意味着 Query 结果可能无法反映由最近完成的 PutItemUpdateItem 操作导致的更改。有关更多信息,请参阅 读取一致性

如果您需要强一致性读取,请在 Query 请求中将 ConsistentRead 参数设置为 true