DynamoDB QueryResultPage 仍然在伪造的独占开始键上返回结果

DynamoDB QueryResultPage still returning results on bogus exclusive start key

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

我正在为一个相当简单的 CRUD 存储库实现分页。 实施基于: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.Pagination.html

我有一个 DynamoDB table 并且此查询是 运行 在 table.

的全局二级索引上

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

此密钥由以下部分组成:

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

实际行为是什么:

如果我提供像 id = "rrrrrrrrrrrrr" 这样的东西,我会得到零结果,正如预期的那样。
如果我提供类似 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 中),结果 returned 用于任何大于我伪造的“aaaaaaaaaaaaaa”的东西。对于“rrrrrrrrrrrr”,它不起作用,因为没有键排序大于 'rrrrrrrrrrrr'。

我希望 DDB 能够 完全匹配 独占开始键,return 下一组结果,但它似乎只是匹配任何出现的结果关闭并 returning 后面的任何键。

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

那里的解决方案是将 table 和索引的主键和范围键设置为 ExclusiveStartKey。然而,在我的例子中,两者都存在,只是颠倒了:

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

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

按设计工作...

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

排除,意思是使用大于而不是包含,后者将大于或等于。