【问题标题】:How can I do DynamoDB limit after filtering?过滤后如何进行 DynamoDB 限制?
【发布时间】:2020-11-17 22:19:01
【问题描述】:

我想使用以下逻辑实现 DynamoDB 扫描:

扫描 -> 过滤(布尔值 true 或 false) -> 限制(用于分页)

但是,我只能用这个逻辑实现扫描:

扫描 -> 限制(用于分页)-> 过滤(布尔值 true 或 false)

我怎样才能做到这一点?

以下是我编写的实现第二个扫描逻辑的示例:

    var parameters = {
        TableName: this.tableName,
        Limit: queryStatement.limit
    };
    if ('role' in queryStatement) {
        parameters.FilterExpression = '#role = :role';
        parameters.ExpressionAttributeNames = {
            '#role': 'role'
        };
        parameters.ExpressionAttributeValues = {
            ':role': queryStatement.role
        };
    }
    if ('startKey' in queryStatement) {
        parameters.ExclusiveStartKey = { id: queryStatement.startKey};
    }

    this.documentClient.scan(parameters, (errorResult, result) => {
        if (errorResult) {
            errorResult._status = 500;
            return reject(errorResult);
        }

        return resolve(result);
    });

此代码与第二个代码一样。

扫描 -> 限制 -> 过滤

【问题讨论】:

  • 您能告诉我您是如何解决 GSI 问题的吗?
  • 哦,我制作了 GSI,它总是返回没有过滤器的过滤值。因此,扫描 -> 限制 -> 过滤正在改变 GSI 扫描(与过滤器相同的效果)-> 限制。 GSI 可以做任何事情,但要小心,GSI 数据不能同步更新。因此,如果您处理实时数据,这将不是一个正确的答案。
  • @Wooyoung Tyler Kim 如果您在此处发布最终解决方案作为答案,那就太好了。看起来很多人都很好奇。
  • @Gem 是的,原文在公司里,所以我会尽快单独写这部分。

标签: node.js amazon-dynamodb


【解决方案1】:

DynamoDB LIMIT 的工作原理如下所述(即您帖子中的第二种方法)设计。由于它是按设计工作的,因此没有解决方案。

LastEvaluatedKey 应该用于获取后续扫描的数据。

扫描 -> 限制(用于分页)-> 过滤(布尔值 true 或 false)

在请求中,将 Limit 参数设置为您希望的项目数 希望 DynamoDB 在返回结果之前进行处理。

在响应中,DynamoDB 返回 限值的范围。例如,如果您发出查询或扫描 限制值为 6 且没有过滤器表达式的请求, DynamoDB 返回表中与 请求中指定的关键条件(或仅前六项 在没有过滤器的扫描的情况下)。如果您还提供 FilterExpression 值,DynamoDB 将返回第一个中的项目 六个也符合过滤器要求(结果数 返回将小于或等于 6)。

对于查询或扫描操作,DynamoDB 可能会返回 如果操作未返回所有匹配项,则为 LastEvaluatedKey 值 表中的项目。要获得匹配项的完整计数,请采取 上一个请求中的 LastEvaluatedKey 值并将其用作 下一个请求中的 ExclusiveStartKey 值。重复这个直到 DynamoDB 不再返回 LastEvaluatedKey 值。

【讨论】:

  • 哦,你的意思是,没有办法解决这个问题(?)对吧?因为这就是 DynamoDB 的意图。我使用 LastEvaluatedKey 进行分页,例如 blabla.com/users/?limit=10&startKey='' startKey 从 LastEvaluatedKey 获取。我想每个 http 响应获取 10 个数据,因为我设置了 limit=10,但由于上述原因它不能吗?
  • 感谢您的回复,我得想办法解决这个问题。
  • 好。是的,由于上述原因(即括号中的第二段最后一句)。您需要使用 LastEvaluatedKey,直到您获得 10 条预期的记录。与 RDBMS 相比,Dynamodb 中的限制的工作方式不同。
  • 谢谢,我用全局二级索引解决了这个问题。
  • @101110101100111111101101 您能在此处发布如何通过 GSI 解决此问题吗?
【解决方案2】:

使用--max-items=2代替--limit=2,过滤后max-items会做限制。

max-items 的示例查询:

aws dynamodb query --table-name=limitTest --key-condition-expression="gsikey=:hash AND gsisort>=:sort"  --expression-attribute-values  '{ ":hash":{"S":"1"},    ":sort":{"S":"1"}, ":levels":{"N":"10"}}'   --filter-expression="levels >= :levels"  --scan-index-forward  --max-items=2  --projection-expression "levels,key1" --index-name=gsikey-gsisort-index

limit 的示例查询:

aws dynamodb query --table-name=limitTest --key-condition-expression="gsikey=:hash AND gsisort>=:sort"  --expression-attribute-values  '{ ":hash":{"S":"1"},    ":sort":{"S":"1"}, ":levels":{"N":"10"}}'   --filter-expression="levels >= :levels"  --scan-index-forward  --limit=2  --projection-expression "levels,key1" --index-name=gsikey-gsisort-index

【讨论】:

  • 这个方法怎么用?
  • DynamoDB SDK 支持这个吗?
【解决方案3】:

如果只有一个字段对分页感兴趣,您可以创建一个以该字段作为键的索引。那么你就不需要对限制中的项目数进行递归了。

【讨论】:

  • 是的,我是这样实现的,但是现在不需要这样了。请参阅下面的答案。
【解决方案4】:

现在在 dynamodb 中添加限制

var params = {
        TableName: "message",
        IndexName: "thread_id-timestamp-index",
        KeyConditionExpression: "#mid = :mid",
        ExpressionAttributeNames: {
            "#mid": "thread_id"
        },
        ExpressionAttributeValues: {
            ":mid": payload.thread_id
        },
        Limit:  (3 , 2 ,3),
        LastEvaluatedKey: 1,
        ScanIndexForward: false
    };
    req.dynamo.query(params, function (err, data) {
console.log(err, data);
})

【讨论】:

  • ScanIndexForward: false - 这是什么意思?
  • @DmitryGrinko 它反转扫描的数据。
  • 是的,没错。不再需要添加索引。 @DmitryGrinko 它通常用于实现 RDBMS 排序。 'DESC','ASC'
  • @WooyoungTylerKim 你好。 LastEvaluatedKey 现在不能作为参数传递给查询。你有答案吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-28
  • 2019-10-13
  • 2022-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多