首页 > 解决方案 > DynamoDB QueryResultPage 仍然在伪造的独占开始键上返回结果

问题描述

tldr; - 当使用伪造的 LastEvaluatedKey 和 DynamoDB 查询进行分页时,在某些情况下仍会返回结果。

我正在为一个相当直接的 CRUD 存储库实现分页。该实施基于: https ://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.Pagination.html和
使用 DynamoDBMapper Java AWS SDK的分页

我有一个 DynamoDB 表,并且该查询在该表的全局二级索引上运行。

分页工作正常,即我有 5000 条记录。我查询并收到一组 500 个结果和一个 LastEvaluatedKey。使用这个键,我得到下一组 500 个结果等。

该密钥由以下部分组成:

现在我编写了一个测试,以确保如果提供了虚假的 LastEvaluatedKey,我应该得到零结果。

实际行为是什么:

如果我提供类似 id = "rrrrrrrrrrrrrr" 的内容,我会得到零结果,正如预期的那样。
如果我提供类似 id = "aaaaaaaaaaaaa" 的内容,我会得到 500 个结果!

值得注意的是,“id”是 UUID 字符串,因此字母 'r' 不会出现在任何 id 的任何位置。

我的 LastEvaluatedKey 是这样组成的(instanceId 与后续页面查询相同):

        var startKeyMap = new HashMap<String, AttributeValue>();

        var idValue = new AttributeValue();
        idValue.setS(startKey);
        startKeyMap.put("id", idValue);

        var instanceIdValue = new AttributeValue();
        instanceIdValue.setS(instanceId);
        startKeyMap.put("instanceId", instanceIdValue);

        queryExpression.setExclusiveStartKey(startKeyMap);

我怀疑正在发生的事情是因为“id”是一个排序键(在 GSI 中),所以返回的结果大于我的虚假“aaaaaaaaaaaaaa”。对于“rrrrrrrrrrrr”,它不起作用,因为没有键会排序大于“rrrrrrrrrrrr”。

我希望 DDB 能够完全匹配唯一的开始键,并从那里返回下一组结果,但似乎它只是匹配任何接近的东西并返回后面的任何键。

我还发现: DynamoDB Global Secondary Index with Exclusive Start Key

在那里,解决方案是将表和索引的主键和范围键设置为 ExclusiveStartKey。但是,就我而言,两者都存在,它们只是颠倒了:

在表上,id 是主要的,instanceId 是次要的。在 GSI 上,情况正好相反。

有人可以解释发生了什么或我做错了什么吗?

标签: javaamazon-web-servicesamazon-dynamodbdynamodb-queries

解决方案


按设计工作...

ExclusiveStartKey只是意味着以大于您传入的任何值的键开始。

独占,意思是使用大于,而不是包含大于或等于。


推荐阅读