【问题标题】:How do I query by only part of a composite key in DynamoDB?如何仅通过 DynamoDB 中的复合键的一部分进行查询?
【发布时间】:2020-10-01 07:14:54
【问题描述】:

比方说,我有 Users 写评论 Products。

User 和 Product 是具有各自 ID 的独立实体。

Review 是一个由userIdproductId 组成的复合id 的实体。

我在 DynamoDB 中创建了一个表 review,其中 userIdproductId 作为 HASH 键。

aws dynamodb create-table --table-name review \
  --attribute-definitions \
      AttributeName=user_id,AttributeType=S \
      AttributeName=product_id,AttributeType=S \
  --key-schema \
      AttributeName=user_id,KeyType=HASH \
      AttributeName=product_id,KeyType=RANGE \
  --provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5 

从而使userId+productId成为复合键。

评论数据对象是针对该键保存的。

查询用户和产品的评论很好。

但是如何查询用户的所有评论或产品的所有评论?

使用单个参数,例如如果我只使用 "#user_id = :userId" 或仅使用 "#product_id = :productId" 通过单键条件表达式进行查询

我收到表单错误

Query condition missed key schema element: user_id

Query condition missed key schema element: product_id

【问题讨论】:

  • 你能显示给你错误的完整查询吗?

标签: amazon-dynamodb dynamodb-queries


【解决方案1】:

我在 DynamoDB 中创建了一个表审查,其中 userId 和 productId 作为 HASH 键。

您已经为您的评论表创建了一个复合主键,它由一个 userId 的分区键和一个 'productId' 的排序键和一个排序键组成。您确实没有创建了两个 HASH 键。

从逻辑上讲,您的评论表将如下所示(我编造了一些数据用于说明目的):

这种表结构可以很容易地按用户获取评论。这是一个查询USER#ABC的所有评论的示例

ddbClient.query(
  "TableName": "<YOUR TABLE NAME>",
  "KeyConditionExpression": "#userId = :userId",
  "ExpressionAttributeValues": {
    ":userId": {
      "S": "USER#ABC"
    }
  },
  "ExpressionAttributeNames": {
    "#userId": "userId"
  }
)

这将返回由 USER#ABC 审查的项目集合。

DynamoDB允许您通过指定排序键(例如productId)来获取项目。您总是需要提供分区密钥。那么如何获得评论过给定产品的用户列表呢?

如果您想搜索评论过单个产品的所有用户,您可以引入一个全局二级索引来交换表的分区键和排序键。这种模式称为inverted index。使用上面的示例,倒排索引如下所示:

这将允许您按 productId 获取用户:

ddbclient.query(
{
  "TableName": "<YOUR TABLE NAME>",
  "IndexName": "reviews_by_product_index",
  "KeyConditionExpression": "#productId = :productId",
  "ExpressionAttributeValues": {
    ":productId": {
      "S": "PRODUCT#456"
    }
  },
  "ExpressionAttributeNames": {
    "#productId": "productId"
  }
}
)

此查询将返回代表PRODUCT#456 评论的两个项目的集合。

使用复合主键时,可以根据排序键的条件进行搜索,只要您还指定了分区键。这很拗口,但它允许您执行类似(在伪代码中)的查询

查询分区键 = "USER#ABC" 和排序键 begin_with "PRODUCT"

【讨论】:

  • 很棒的答案。谢谢。
猜你喜欢
  • 2018-10-31
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-03
相关资源
最近更新 更多