在亚马逊 DynamoDB 中处理 JSON 数据

Amazon DynamoDB 允许您将 JSON 对象存储到属性中,并对这些对象执行许多操作,包括筛选、更新和删除。这是一项非常强大的功能,因为它允许应用程序将对象(JSON 数据、数组)直接存储到 DynamoDB 表中,并且仍然能够在数据库操作中使用这些对象中的嵌套属性。在这篇文章中,我们将探讨您可以在 DynamoDB 中使用 JSON 对象做的一些事情。

正在安装 DynamoDB 外壳 (ddbsh)

你可以使用自制软件安装适用于 Mac 的 Dynamo DB shell (ddbsh ),也可以使用 github 上提供的预建二进制文件安装 Ubuntu。请参阅 “使用预建二进制文件” 部分。

解决方案概述

我们使用 DynamoDB 外壳 ( ddbsh ) 来说明这些功能。要了解更多信息,请参阅 使用 DynamoDB Shell 查询数据,这是亚马逊 DynamoDB 的命令行界面 ddbsh 的目标之一 是为 D ynamoDB 的新手提供一个简单直观的环境,让他们开始运行熟悉的类似 SQL 的命令。

ddbsh 中的查询语言源自 SQL,具有 特定于 D ynamoDB 的扩展名。

在这篇文章中,我们使用了一个简单的 DynamoDB 表来跟踪有关快餐订单的信息。以下代码是订单示例:

{ ono: 12, ino: 1, details: { entree: “burger”, sides: [ “fries”, “soda” ]}, status: “WIP” }

已完成的订单如下所示:

{ ono: 15, ino: 1, details: { entree: “salad”, sides: [ “apple”, “water” ]}, status: “DONE” }

包含三件商品的订单如下所示:

{ ono: 14, ino: 1, details: { entree: “salad”, sides: [ “apple”, “water” ]}, status: “WIP” }
{ ono: 14, ino: 2, details: { entree: “BLT sw”, sides: [ “water” ]}, status: “WIP” }

在以下部分中,我们将介绍如何创建表并插入一些示例数据、查询数据、更新项目以及添加和删除属性。我们还将讨论如何将 SQL 转换为来自应用程序的一组 API 调用。

先决条件

要开始使用,你需要安装 DynamoDB 外壳。有关更多信息,请参阅 使用 DynamoDB Shell 查询数据,这是亚马逊 DynamoDB 的命令行界面

准备好你的数据

使用以下代码创建 DynamoDB 表:

us-east-1> CREATE TABLE ORDERS ( ono number, ino number ) PRIMARY KEY (ono hash, ino range);
CREATE
us-east-1>

接下来,使用以下代码将这四行填充到 DynamoDB 中:

us-east-1> insert into ORDERS (ono, ino, details, status)
values (12, 1, {entree: "burger", sides: ["fries", "soda"]}, "WIP"),
(14, 1, {entree: "salad", sides: ["apple", "water"]}, "WIP"),
(14, 2, {entree: "BLT sw", sides: ["water"]}, "WIP"),
(15, 1, {entree: "salad", sides: ["apple", "water"]}, "DONE");
INSERT
INSERT
INSERT
INSERT
us-east-1> select * from ORDERS;
{details: {entree:salad, sides:[apple, water]}, ino: 1, ono: 14, status: WIP}
{details: {entree:"BLT sw", sides:[water]}, ino: 2, ono: 14, status: WIP}
{details: {entree:burger, sides:[fries, soda]}, ino: 1, ono: 12, status: WIP}
{details: {entree:salad, sides:[apple, water]}, ino: 1, ono: 15, status: DONE}
us-east-1>

现在,您可以开始查询数据了。

查询您的数据

您可以通过运行以下查询来找到顺序 14 中的第一项:

us-east-1> select * from ORDERS where ono = 14 and ino = 1;
{details: {entree:salad, sides:[apple, water]}, ino: 1, ono: 14, status: WIP}
us-east-1>

您还可以执行其他查询,例如查找所有包含水面但尚未完成的订单行:

us-east-1> select * from ORDERS where status != "DONE" and contains(details.sides, "water");
{details: {entree:salad, sides:[apple, water]}, ino: 1, ono: 14, status: WIP}
{details: {entree:"BLT sw", sides:[water]}, ino: 2, ono: 14, status: WIP}
us-east-1>

在这里,DynamoDB 解压缩 JSON 对象( 详情 ),找到了名为 s id es 的属性 ,并查看了该数组中是否有包含水的属性。

在以下查询中,一份薯条订单已准备就绪,我们想知道应该将其发送到哪个订单:

us-east-1> select ono, ino from ORDERS where contains(details.sides, "fries") and status = "WIP";
{ino: 1, ono: 12}
us-east-1>

同样,如果汉堡准备好了,我们可以决定应该将其附在哪个订单上:

us-east-1> select ono, ino from ORDERS where details.entree = "burger" and status = "WIP";
{ino: 1, ono: 12}
us-east-1>

更新物品

您也可以使用 DynamoDB 外壳更新这些订单。例如,下单 14(商品 1)的客户改变了主意,想要的是苏打水而不是水:

us-east-1> select * from ORDERS where ono = 14 and ino = 1;
{details: {entree:salad, sides:[apple, water]}, ino: 1, ono: 14, status: WIP}
us-east-1>

us-east-1> update ORDERS set details.sides[1] = "soda" where ono = 14 and ino = 1;
UPDATE (0 read, 1 modified, 0 ccf)
us-east-1>

us-east-1> select * from ORDERS where ono = 14 and ino = 1;
{details: {entree:salad, sides:[apple, soda]}, ino: 1, ono: 14, status: WIP}
us-east-1>

观察到更新按索引引用数组 details.sid es 中的项目。第二项(索引 1)在此处更新。

向嵌入式对象添加属性和删除嵌入式对象的属性

如果客户有特殊要求,您可以将其添加到订单中:

us-east-1> update ORDERS set details.notes = "extra dressing" where ono = 14 and ino = 1;
UPDATE (0 read, 1 modified, 0 ccf)
us-east-1> select * from ORDERS where ono = 14;
{details: {entree:salad, notes:"extra dressing", sides:[apple, water]}, ino: 1, ono: 14, status: WIP}
{details: {entree:"BLT sw", sides:[water]}, ino: 2, ono: 14, status: WIP}
us-east-1>

如果订购 BLT 三明治的顾客认为他们毕竟不想要水,我们可以使用以下代码:

us-east-1> update ORDERS remove details.sides where ono = 14 and ino = 2;
UPDATE (0 read, 1 modified, 0 ccf)
us-east-1> select * from ORDERS where ono = 14 and ino = 2;
{details: {entree:"BLT sw"}, ino: 2, ono: 14, status: WIP}
us-east-1>

将 SQL 转换为 DynamoDB API

在使用 DynamoDB 编写应用程序时,使用 SQL 快速创建要执行的操作原型很有用,但随后可能需要将其转换为来自应用程序的一组 API 调用。 ddhsh 可以帮助你了解如何使用 EXPLAIN 命令对前面显示的 UPDATE 语句进行编码:

us-east-1> explain update ORDERS set details.sides[1] = "soda" where ono = 14 and ino = 1;
UpdateItem({
   "TableName":   "ORDERS",
   "Key":   {
      "ino":   {
         "N":   "1"
      },
      "ono":   {
         "N":   "14"
      }
   },
   "UpdateExpression":   "SET #aTaa1.#aTaa2[1] = :vTaa1",
   "ConditionExpression":   "attribute_exists(#aTaa3)",
   "ExpressionAttributeNames":   {
      "#aTaa1":   "details",
      "#aTaa2":   "sides",
      "#aTaa3":   "ono"
   },
   "ExpressionAttributeValues":   {
      ":vTaa1":   {
         "S":   "soda"
      }
   }
})
us-east-1>

EXPLAIN 表明,查询(具有完整的主键 on o 和 ino )可以表示为 updateItem () API 调用。指定了表名和密钥。更新表达式的编码方式如下:

"UpdateExpression":   "SET #aTaa1.#aTaa2[1] = :vTaa1"

这样做是为了处理您的架构中可能存在的任何保留字。通过使用占位符替换属性名称,您可以安全地执行此更新。 在这里, ddbsh 细节 更改为 #aTaa1 并将侧面更改为 #aTaa2。 该值( 苏打 )已替换为占位符 : vtaA1。 由于 DynamoDB updateItem () 将在项目尚不存在的情况下插入该项目,因此 ddbsh 会 发出一个勾号,其中 #aTaa3 是属性 ono 的占位符:

"ConditionExpression": "attribute_exists(#aTaa3)"

因为键条件提供了完整的主键,所以如果存在匹配该主键的项目,则项目中 将存在 ono 属性。

以下代码是将请求转换为 API 调用的另一个示例:

us-east-1> explain update ORDERS remove details.sides where ono = 14 and ino = 2;
UpdateItem({
   "TableName":   "ORDERS",
   "Key":   {
      "ino":   {
         "N":   "2"
      },
      "ono":   {
         "N":   "14"
      }
   },
   "UpdateExpression":   "REMOVE #aeba1.#aeba2",
   "ConditionExpression":   "attribute_exists(#aeba3)",
   "ExpressionAttributeNames":   {
      "#aeba1":   "details",
      "#aeba2":   "sides",
      "#aeba3":   "ono"
   }
})
us-east-1>

清理

完成实验后,请记住删除您可能创建的所有表格,以避免产生费用。你可以使用 ddbsh 中的 DROP TABL E 来执行此操作:

us-east-1> drop table ORDERS;
DROP
us-east-1>

结论

DynamoDB 允许您将 JSON 数据存储到属性中。然后,您可以查询数据并对 JSON 对象内的属性执行限制和修改。

我们从客户和潜在客户那里听说,他们需要能够帮助他们学习 DynamoDB API 的资源。我们正在尝试一些解决方案,例如我们在本文中演示的 ddbsh 中的 EXPLAIN 命令。如果您对此工具提供反馈,我们将不胜感激。我们可以在 ddbsh 中添加什么来 使您更容易使用 DynamoDB?

最后,如果您希望在 ddbsh 中实现某些特定功能或功能,请输入支持请求或直接发送电子邮件至 amrithie (at) amazon.com 告知我们。


作者简介

Amrith Kumar 是亚马逊网络服务的高级首席工程师,在亚马逊 DynamoDB 上工作。


*前述特定亚马逊云科技生成式人工智能相关的服务仅在亚马逊云科技海外区域可用,亚马逊云科技中国仅为帮助您发展海外业务和/或了解行业前沿技术选择推荐该服务。