如何在dynamodb中查询主键值数组

时间:2018-11-21 16:08:11

标签: node.js amazon-web-services amazon-dynamodb dynamodb-queries

我在AWS Dynamodb中有一张表有100万条记录。是否可以在dynamodb中使用附加排序键条件在一个查询中查询主键值数组?我正在使用我的服务器端逻辑。

这里是参数

var params = {
TableName: "client_logs",
KeyConditionExpression: "#accToken = :value AND ts between :val1 and 
:val2", 
ExpressionAttributeNames: {
"#accToken": "acc_token"
},
ExpressionAttributeValues: {
        ":value": clientAccessToken,
        ":val1": parseInt(fromDate),
        ":val2": parseInt(toDate),
        ":status":confirmStatus
},
FilterExpression:"apiAction = :status"


};

这里acc_token是主键,我想在一个查询中查询access_token值的数组。

2 个答案:

答案 0 :(得分:0)

否,这是不可能的。单个查询只能搜索一个特定的哈希键值。 (请参见DynamoDB – Query。)

但是,您可以并行执行多个查询,这将达到您想要的效果。

编辑(2018-11-21)

由于您说的是要查找的200多个哈希键,因此这里有两种可能的解决方案。这些解决方案不需要对DynamoDB进行无限制的并行调用,但是它们将使您花费更多的RCU。它们可能更快或更慢,具体取决于表中数据的分布。

我不知道您的数据分布,所以我不能说哪个数据最适合您。在所有情况下,我们都不能使用acc_token作为GSI的排序键,因为您不能在KeyConditionExpression中使用IN运算符。 (请参见DynamoDB – Condition。)

解决方案1 ​​

此策略基于Global Secondary Index Write Sharding for Selective Table Queries

步骤:

  1. 向您写入表的项目添加新属性。此新属性可以是数字或字符串。我们称之为index_partition
  2. 当您向表中写入新项目时,请为0赋予一个从Nindex_partition的随机值。 (在这里,N是您选择的任意常数。9可能是一个不错的值。)
  3. 使用哈希键index_partition和排序键ts创建一个GSI。您需要将apiActionacc_token投影到GSI。
  4. 现在,您只需要执行N个查询。使用关键条件表达式index_partition = :n AND ts between :val1 and :val2和过滤条件表达式apiAction = :status AND acc_token in :acc_token_list

解决方案2

此解决方案与上一个类似,但是我们将使用基于日期的分区作为GSI,而不是使用随机GSI分片。

步骤:

  1. 向您写入表的项目添加新的字符串属性。我们称之为ts_ymd
  2. 将新项目写入表时,仅使用yyyy-mm-dd的{​​{1}}部分来设置ts的值。 (您可以使用任何喜欢的粒度。这取决于您对ts_ymd的典型查询范围。如果ts:val1通常彼此仅相隔一个小时,则可以使用合适的GSI分区密钥可以是yyyy-mm-dd-hh。)
  3. 使用哈希键:val2和排序键ts_ymd创建一个GSI。您需要将tsapiAction投影到GSI。
  4. 假设您使用yyyy-mm-dd作为GSI分区键,则只需在acc_token:val1内每天执行一次查询。使用关键条件表达式:val2和过滤条件表达式ts_ymd = :ymd AND ts between :val1 and :val2

解决方案3

我不知道apiAction = :status AND acc_token in :acc_token_list有多少个不同的值以及这些值是如何分布的,但是如果有多个以上的值,并且它们具有大致相等的分布,则可以根据以下内容对GSI进行分区那个价值。 apiAction的值越多,此解决方案越适合您。这里的限制因素是,您需要具有足够的值,以免GSI的10GB分区限制不足。

步骤:

  1. 使用哈希键apiAction和排序键apiAction创建一个GSI。您需要将ts投影到GSI。
  2. 您只需要执行一个查询。在:acc_token_list`中使用acc_token acc_token的关键条件表达式。

对于所有这些解决方案,您应考虑GSI分区键的分布均匀程度,以及查询中apiAction = :status AND ts between :val1 and :val2" and a filter expression of的典型范围的大小。您必须在ts上使用过滤器表达式,所以您应该尝试选择一种解决方案,以最大程度地减少将与关键条件表达式匹配的项的总数,但是同时,您需要了解可以一个分区键(用于表或GSI)的数据量不超过10GB。您还需要记住,只能作为最终一致的读取来查询GSI。

答案 1 :(得分:0)

借助PartiQL SELECT query,您可以有效地执行分区键的查询范围和对排序键应用附加条件。官方 DDB 文档说:

<块引用>

确保SELECT语句不会产生全表 扫描,WHERE 子句条件必须指定一个分区键。使用 等式或 IN 运算符。

文档没有特别提到排序键,但它说对非键属性的额外过滤仍然不会导致完整扫描。因此,我几乎可以肯定,带有 supported operators 之一的排序键条件不会导致表扫描、执行速度快并消耗尽可能少的容量单位。

因此您的查询可能如下所示:

SELECT * FROM client_logs WHERE acc_token IN (t1, t2, ...) AND ts BETWEEN t1 AND t2

可以在 here 中找到 PartiQL API 使用的 Node.js 示例。