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

Node.js 如何在dynamodb中查询主键值数组,node.js,amazon-web-services,amazon-dynamodb,dynamodb-queries,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_

我在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_令牌是主键,我想在一次查询中查询访问令牌值数组。

不,这是不可能的。单个查询只能搜索一个特定的哈希键值。(见附件。)

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

编辑(2018-11-21)

既然您说您正在寻找200多个哈希键,那么这里有两种可能的解决方案。这些解决方案不需要对DynamoDB进行无界的并行调用,但它们会使您花费更多的RCU。它们可能更快或更慢,这取决于表中数据的分布

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

解决方案1

这一战略基于

步骤:

  • 向写入表的项添加新属性。此新属性可以是数字或字符串。让我们称之为
    索引分区
  • 当您向表中写入新项时,为其指定一个从
    0
    N
    的随机值,用于
    索引分区
    。(这里,
    N
    是您选择的任意常数。
    9
    可能是一个合适的值。)
  • 创建一个GSI,哈希键为
    index\u partition
    ,排序键为
    ts
    。您需要将
    apiAction
    acc_令牌
    投影到GSI
  • 现在,您只需要执行
    N
    查询。使用
    index_partition=:n和ts介于:val1和:val2之间的键条件表达式和
    apiAction=:status和acc_token in:acc_token_list
  • 解决方案2

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

    步骤:

  • 向写入表的项添加新的字符串属性。让我们称之为
    t_ymd
  • 将新项目写入表时,只需使用
    ts
    yyyy-mm-dd
    部分设置
    ts_-ymd
    的值。(您可以使用任意粒度。这取决于
    ts
    的典型查询范围。如果
    :val1
    :val2
    通常相隔仅一小时,则合适的GSI分区键可以是yyyy-mm-dd-hh。)
  • 创建一个GSI,哈希键为
    ts_ymd
    ,排序键为
    ts
    。您需要将
    apiAction
    acc_令牌
    投影到GSI
  • 假设您使用yyyy-mm-dd作为GSI分区密钥,您每天只需要在
    :val1
    :val2
    范围内执行一个查询。使用键条件表达式
    ts_ymd=:ymd和ts介于:val1和:val2之间
    和过滤器表达式
    apiAction=:status和acc_token in:acc_token_list
  • 解决方案3

    我不知道有多少不同的
    apiAction
    值,以及这些值是如何分布的,但是如果有多个值,并且它们的分布大致相等,则可以基于该值对GSI进行分区。
    apiAction
    的可能值越多,此解决方案就越适合您。这里的限制因素是,您需要有足够的值,使您的GSI不会达到10GB分区限制

    步骤:

  • 创建一个GSI,哈希键为
    apiAction
    ,排序键为
    ts
    。您需要将
    acc_令牌
    投影到GSI
  • 您只需要执行一个查询。使用键条件表达式
    apiAction=:status AND ts between:val1 AND:val2”和过滤器表达式
    acc_token in:acc_token_list`

  • 对于所有这些解决方案,您应该考虑GSI分区密钥分布的均匀性以及查询中<>代码> TS的典型范围的大小。您必须在<代码> AccToMuth上使用筛选器表达式,因此您应该尝试选择一个最小化与密钥条件Exp匹配的项总数的解决方案。但是同时,您需要知道,一个分区键(表或GSI)的数据不能超过10GB。您还需要记住,GSI只能作为最终一致的读取进行查询。

    但我的数组中有近200个项目。而且这个数字将来可能会增加。我认为这不是查询200多次的正确方法。如果可以,请建议其他方法。这200个键是否始终相同?或者可以接受查询如果没有
    between
    函数?如果可以,或者您可以使用筛选表达式,那么可以使用全局二级索引来解决问题。谢谢您的回答。当然,200个键总是相同的。但是随着时间的推移,新键会被添加。不幸的是,完成初始开发的开发人员没有这样做创建任何索引,现在已经接近一百万了。在创建索引之后,我还有其他方法可以改变吗?或者dynamodb有没有其他功能可以将表复制到该区域内的另一个表?这样我就可以在新表上做这个实验,而不是在生产数据中做。我知道我们可以使用数据管道和s3,但我们没有为节省成本,我们是否可以在dynamo it self中复制其他服务?请提供建议