使用项目和属性 - Amazon DynamoDB
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

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

使用项目和属性

在 Amazon DynamoDB 中,项目是属性的集合。每个属性都有各自的名称和值。属性值可以为标量、集或文档类型。有关更多信息,请参阅Amazon DynamoDB:如何使用

DynamoDB 提供了用于基本的创建、读取、更新和删除 (CRUD) 功能的四项操作:

  • PutItem— 创建项目。

  • GetItem— 读取项目。

  • UpdateItem— 更新项目。

  • DeleteItem— 删除项目。

其中每项操作均需要您指定要处理的项目的主键。例如,要使用 GetItem 读取项目,您必须指定该项目的分区键和排序键 (如果适用)。

除了四项基本 CRUD 操作之外,DynamoDB 还提供了以下操作:

  • BatchGetItem— 从一个或多个表中读取多达 100 个项目。

  • BatchWriteItem— 在一个或多个表中创建或删除多达 25 个项目。

这些批处理操作可将多项 CRUD 操作组合成一个请求。此外,批处理操作还可并行读取和写入项目以最大程度地减少响应延迟。

本节将介绍如何使用这些操作并包含了相关主题,例如有条件更新和原子计数器。本节还包括使用Amazon开发工具包。

读取项目

要从 DynamoDB 表中读取项目,请使用GetItemoperation. 必需提供表的名称和所需项目的主键。

以下 Amazon CLI 示例将演示如何从 ProductCatalog 表读取项目。

aws dynamodb get-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}'
注意

使用 GetItem 时,您必须指定整个 主键,而不仅仅是部分主键。例如,如果某个表具有复合主键(分区键和排序键),您必须为分区键和排序键分别提供一个值。

默认情况下,GetItem 请求将执行最终一致性读取。您可以改用 ConsistentRead 参数来请求强一致性读取。(这会占用额外的读取容量单位,但会返回该项目的最新版本。)

GetItem 返回项目的所有属性。您可以使用投影表达式 来仅返回一部分属性。有关更多信息,请参阅投影表达式

要返回由 GetItem 占用的读取容量单位数,请将 ReturnConsumedCapacity 参数设置为 TOTAL

以下 Amazon Command Line Interface (Amazon CLI) 示例将演示一些可选的 GetItem 参数。

aws dynamodb get-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}' \ --consistent-read \ --projection-expression "Description, Price, RelatedItems" \ --return-consumed-capacity TOTAL

写入项目

要创建、更新或删除 DynamoDB 表中的项目,请使用以下操作之一:

  • PutItem

  • UpdateItem

  • DeleteItem

对于这些操作中的每一项,您必须指定完整的主键,而不仅仅是部分主键。例如,如果某个表具有复合主键(分区键和排序键),您必须为分区键和排序键分别提供一个值。

要返回其中任何操作占用的写入容量单位数,请将 ReturnConsumedCapacity 参数设置为以下项之一:

  • TOTAL— 返回占用的写入容量单位总数。

  • INDEXES— 返回占用的写入容量单位总数,其中包含表的小计和受该操作影响的任何二级索引。

  • NONE— 不返回任何写入容量详细信息。(这是默认值。)

PutItem

PutItem 创建新项目。如果表中已存在具有相同键的项目,它将被替换为新项目。

将新项目写入 Thread 表。Thread 的主键包含 ForumName(分区键)和 Subject(排序键)。

aws dynamodb put-item \ --table-name Thread \ --item file://item.json

--item 的参数存储在文件 item.json 中。

{ "ForumName": {"S": "Amazon DynamoDB"}, "Subject": {"S": "New discussion thread"}, "Message": {"S": "First post in this thread"}, "LastPostedBy": {"S": "fred@example.com"}, "LastPostDateTime": {"S": "201603190422"} }

UpdateItem

如果带指定键的项目不存在,则 UpdateItem 会创建一个新项目。否则,它会修改现有项目的属性。

您可使用更新表达式 指定要修改的属性及其新值。有关更多信息,请参阅更新表达式

在更新表达式内,您可使用表达式属性值作为实际值的占位符。有关更多信息,请参阅表达式属性值

修改 Thread 项目中的各种属性。可选 ReturnValues 参数按更新后的情况显示项目。有关更多信息,请参阅返回值

aws dynamodb update-item \ --table-name Thread \ --key file://key.json \ --update-expression "SET Answered = :zero, Replies = :zero, LastPostedBy = :lastpostedby" \ --expression-attribute-values file://expression-attribute-values.json \ --return-values ALL_NEW

--key 的参数存储在文件 key.json 中。

{ "ForumName": {"S": "Amazon DynamoDB"}, "Subject": {"S": "New discussion thread"} }

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

{ ":zero": {"N":"0"}, ":lastpostedby": {"S":"barney@example.com"} }

DeleteItem

DeleteItem 删除带指定键的项目。

下面的 Amazon CLI 示例说明如何删除 Thread 表。

aws dynamodb delete-item \ --table-name Thread \ --key file://key.json

返回值

在某些情况下,您可能希望 DynamoDB 按您修改特定属性值之前或之后的情况返回这些值。PutItemUpdateItemDeleteItem 操作均具有一个 ReturnValues 参数,您可使用该参数返回属性在修改前或修改后的值。

默认值ReturnValuesNONE,这表示 DynamoDB 不会返回有关已修改属性的任何信息。

以下是的其他有效设置ReturnValues,由 DynamoDB API 操作组织。

PutItem

  • ReturnValues: ALL_OLD

    • 如果您覆盖了现有项目,ALL_OLD 将按覆盖前的情况返回整个项目。

    • 如果您写入了不存在的项目,则 ALL_OLD 无效。

UpdateItem

UpdateItem 的最常见用途是更新现有项目。但是,UpdateItem 实际上会执行 upsert 操作,这意味着,如果项目尚不存在,upsert 将自动创建项目。

  • ReturnValues: ALL_OLD

    • 如果您更新了现有项目,ALL_OLD 将按更新前的情况返回整个项目。

    • 如果您更新了不存在的项目 (upsert),则 ALL_OLD 无效。

  • ReturnValues: ALL_NEW

    • 如果您更新了现有项目,ALL_NEW 将按更新后的情况返回整个项目。

    • 如果您更新了不存在的项目 (upsert),ALL_NEW 将返回整个项目。

  • ReturnValues: UPDATED_OLD

    • 如果您更新了现有项目,UPDATED_OLD 将仅返回已更新的属性 (按更新前的情况)。

    • 如果您更新了不存在的项目 (upsert),则 UPDATED_OLD 无效。

  • ReturnValues: UPDATED_NEW

    • 如果您更新了现有项目,UPDATED_NEW 将仅返回受影响的属性 (按更新后的情况)。

    • 如果您更新了不存在的项目 (upsert),UPDATED_NEW 将仅返回已更新的属性 (按更新后的情况)。

DeleteItem

  • ReturnValues: ALL_OLD

    • 如果您删除了现有项目,ALL_OLD 将按删除前情况返回整个项目。

    • 如果您删除了不存在的项目,ALL_OLD 不会返回任何数据。

批处理操作

对于需要读取或写入多个项目的应用程序,DynamoDB 提供了BatchGetItemBatchWriteItem运算。使用这些操作可减少从您的应用程序到 DynamoDB 的网络往返行程数。此外,DynamoDB 还可并行执行各个读取或写入操作。您的应用程序将受益于这种并行机制,并且无需管理并发度或线程。

批处理操作本质上是围绕多个读取或写入请求的包装程序。例如,如果BatchGetItem请求包含五个项目,DynamoDB 将执行五个GetItem操作。同样,如果BatchWriteItem请求包含两个放置请求和四个删除请求,DynamoDB 会执行两次PutItem和 4 个DeleteItem请求。

通常,除非一个批处理操作中的所有 请求都失败,否则批处理操作不会失败。例如,假设您执行了一个 BatchGetItem 操作,但该批处理中的单独的 GetItem 请求之一失败。在这种情况下,BatchGetItem 会返回来自失败的 GetItem 请求的键和数据。该批处理中的其他 GetItem 请求不会受影响。

BatchGetItem

单个BatchGetItem操作最多可以包含 100 个单独的GetItem请求且最多可检索 16 MB 的数据。此外,一个 BatchGetItem 操作可从多个表中检索项目。

Thread 表中检索两个项目,并使用投影表达式仅返回一部分属性。

aws dynamodb batch-get-item \ --request-items file://request-items.json

--request-items 的参数存储在文件 request-items.json 中。

{ "Thread": { "Keys": [ { "ForumName":{"S": "Amazon DynamoDB"}, "Subject":{"S": "DynamoDB Thread 1"} }, { "ForumName":{"S": "Amazon S3"}, "Subject":{"S": "S3 Thread 1"} } ], "ProjectionExpression":"ForumName, Subject, LastPostedDateTime, Replies" } }

BatchWriteItem

这些区域有:BatchWriteItem操作最多可以包含 25 个单独的PutItemDeleteItem请求且最多可写入 16 MB 的数据。(单个项目的最大大小为 400 KB。) 此外,一个 BatchWriteItem 操作可在多个表中放置或删除项目。

注意

BatchWriteItem 不支持 UpdateItem 请求。

它向 ProductCatalog 表中写入两个项目。

aws dynamodb batch-write-item \ --request-items file://request-items.json

--request-items 的参数存储在文件 request-items.json 中。

{ "ProductCatalog": [ { "PutRequest": { "Item": { "Id": { "N": "601" }, "Description": { "S": "Snowboard" }, "QuantityOnHand": { "N": "5" }, "Price": { "N": "100" } } } }, { "PutRequest": { "Item": { "Id": { "N": "602" }, "Description": { "S": "Snow shovel" } } } } ] }

原子计数器

可以使用UpdateItem操作来实现原子计数器-无条件递增的数字属性,不会干扰其他写入请求。(所有写入请求的应用顺序跟接收顺序相同。) 使用原子计数器时,更新不是幂等的。换言之,该数字值在您每次调用 UpdateItem 时递增。

您可使用原子计数器跟踪网站的访问者的数量。在这种情况下,您的应用程序将以某个数字值递增,无论其当前值如何。如果 UpdateItem 操作失败,该应用程序只需重试该操作即可。这会产生更新两次计数器的风险,但您可能能够容忍对网站访问者的计数稍微偏多或偏少。

在无法容忍计数偏多或偏少的情况下(例如,在银行应用程序中),原子计数器将不适用。在此情况下,使用有条件更新比使用原子计数器更安全。

有关更多信息,请参阅对数值属性进行加减

以下 Amazon CLI 示例以 5 为递增量提高产品的 Price。(由于 UpdateItem 不是幂等的,Price 在您每次运行此示例时增加。)

aws dynamodb update-item \ --table-name ProductCatalog \ --key '{"Id": { "N": "601" }}' \ --update-expression "SET Price = Price + :incr" \ --expression-attribute-values '{":incr":{"N":"5"}}' \ --return-values UPDATED_NEW

有条件写入

默认情况下,DynamoDB 写入操作 (PutItemUpdateItemDeleteItem) 是无条件:每项操作都会覆盖带指定主键的现有项目。

DynamoDB 可以选择性地对这些操作支持条件写入。有条件写入仅在项目属性满足一个或多个预期条件时才会成功。否则,它会返回错误。有条件写入在很多情况下很有用。例如,您可能希望 PutItem 操作仅在尚不存在具有相同主键的项目时成功。或者,如果某个项目的其中一个属性具有一个特定值,您可以阻止 UpdateItem 操作修改该项目。

有条件写入在多个用户尝试修改同一项目的情况下很有用。请考虑下图,其中两位用户(Alice 和 Bob)正在处理 DynamoDB 表中的同一项目。

假设 Alice 使用 Amazon CLI 将 Price 属性更新为 8。

aws dynamodb update-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}' \ --update-expression "SET Price = :newval" \ --expression-attribute-values file://expression-attribute-values.json

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

{ ":newval":{"N":"8"} }

现在假设 Bob 稍后发出一个相似的 UpdateItem 请求,但将 Price 更改为 12。对于 Bob,--expression-attribute-values 参数类似于以下形式。

{ ":newval":{"N":"12"} }

Bob 的请求成功,但 Alice 之前的更新丢失了。

要请求有条件 PutItemDeleteItemUpdateItem,请指定一个条件表达式。条件表达式 是一个包含属性名称、条件运算符和内置函数的字符串。整个表达式的求值结果必须为 true。否则,该操作将失败。

现在考虑下图,该图展示了有条件写入将如何阻止 Alice 的更新被覆盖。

Alice 首次尝试将 Price 更新为 8,但仅在当前 Price 为 10 时才执行此操作。

aws dynamodb update-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}' \ --update-expression "SET Price = :newval" \ --condition-expression "Price = :currval" \ --expression-attribute-values file://expression-attribute-values.json

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

{ ":newval":{"N":"8"}, ":currval":{"N":"10"} }

由于条件的计算结果为 true,Alice 的更新成功了。

接下来,Bob 尝试将 Price 更新为 12,但仅在当前 Price 为 10 时才执行此操作。对于 Bob,--expression-attribute-values 参数类似于以下形式。

{ ":newval":{"N":"12"}, ":currval":{"N":"10"} }

由于 Alice 之前已将 Price 更改为 8,因此条件表达式的计算结果为 false,Bob 的更新失败。

有关更多信息,请参阅条件表达式

有条件写入幂等性

如果条件检查位于同一个要更新的属性上,则条件写入可以是幂等 的。这意味着,仅当项目中的某些属性值与您在请求时期望它们具有的值匹配时,DynamoDB 才执行给定的写入请求。

例如,假设您发出一个 UpdateItem 请求来以 3 为递增量提高某个项目的 Price,但仅在 Price 当前为 20 时才执行此操作。在已发送该请求但尚未获得返回的结果之间的时间内,网络出现了错误,您不知道该请求是否成功。由于此条件写入是幂等的,您可以重试同一UpdateItem请求,并且 DynamoDB 仅在Price目前为 20 个。

有条件写入占用的容量单位

如果ConditionExpression在条件写入过程中计算结果为 false,DynamoDB 仍占用表的写入容量:

  • 如果项目当前在表中不存在,DynamoDB 占用一个写入容量单位。

  • 如果项目已存在,则所占用的写入容量单位数将取决于项目的大小。例如,一个 1 KB 项目的一次失败的有条件写入将占用一个写入容量单位。如果项目增大一倍,则失败的有条件写入将占用两个写入容量单位。

注意

写入操作仅占用写入 容量单位。它们从不占用读取 容量单位。

失败的条件写入将返回 ConditionalCheckFailedException。发生这种情况时,您不会在响应中收到有关所占写入容量的任何信息。但是,您可以查看ConsumedWriteCapacityUnits指标中 Amazon CloudWatch。有关更多信息,请参阅 DynamoDB 指标 中的 DynamoDB 中的日志记录和监控

要返回有条件写入过程中占用的写入容量单位的数量,请使用 ReturnConsumedCapacity 参数:

  • TOTAL— 返回占用的写入容量单位总数。

  • INDEXES— 返回占用的写入容量单位总数,其中包含表的小计和受该操作影响的任何二级索引。

  • NONE— 不返回任何写入容量详细信息。(这是默认值。)

注意

与全局二级索引不同的是,本地二级索引与其表共享其预置吞吐量容量。本地二级索引上的读取和写入活动会占用表中的预置的吞吐容量。