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 个结果等
此密钥由以下部分组成:
- 分区键“instanceId”在后续页面请求中始终相同。
- 范围键“id”,这是在下一个页面请求中发生的变化
现在我编写了一个测试,以确保如果提供了伪造的 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
只是意味着以大于您传入的任何值的键开始。
排除,意思是使用大于而不是包含,后者将大于或等于。
tldr; - 当使用伪造的 LastEvaluatedKey 和 DynamoDB 查询进行分页时,在某些情况下它仍然 returns 结果。
我正在为一个相当简单的 CRUD 存储库实现分页。
实施基于:
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.Pagination.html 和
我有一个 DynamoDB table 并且此查询是 运行 在 table.
的全局二级索引上分页工作正常,即我有 5000 条记录。我查询并收到一组 500 个结果和一个 LastEvaluatedKey。使用这个键,我得到下一组 500 个结果等
此密钥由以下部分组成:
- 分区键“instanceId”在后续页面请求中始终相同。
- 范围键“id”,这是在下一个页面请求中发生的变化
现在我编写了一个测试,以确保如果提供了伪造的 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
只是意味着以大于您传入的任何值的键开始。
排除,意思是使用大于而不是包含,后者将大于或等于。