当前位置: 首页 > 知识库问答 >
问题:

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

杜志
2023-03-14

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

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

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

分页工作正常,即。我有5000张唱片。我查询并接收一组500个结果和一个LastEvalue atedKey。使用这个键,我得到下一组500个结果等。

该钥匙由以下部件组成:

  • 分区键instanceId在后续页面请求中始终相同。
  • 范围键"id"这是什么改变下一页请求

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

实际行为是什么:

如果我提供id=“rrrrrrrrrrrrr”之类的内容,我将获得零结果,正如预期的那样。
如果我提供id=“aaaaaaaaaaaaaaaa”之类的内容,我将获得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中),所以返回的结果比我伪造的“aaaaaaaaaa”更大。对于“rrrrrrrrrrrrrrrr”,它不起作用,因为没有键的排序会大于“rrrrrrrrrrrrrrrr”。

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

我还发现:DynamoDB全局二级索引具有独占的开始键

在那里,解决方案是将表和索引的主键和范围键设置为ExclusiveStartKey。然而,在我的情况下,两者都在那里,它们只是相反:

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

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

共有1个答案

曹光霁
2023-03-14

按设计工作。。。

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

排他性,意思是使用大于,而不是包含大于或等于。

 类似资料:
  • 我正在尝试为我的API实现分页。我有一个带有简单主键的DynamoDB表。 由于DynamoDB扫描()操作中的ExclusiveStartKey只不过是扫描操作中读取的最后一项的主键,所以我想知道如果我使用表中不存在的ExclusiveStartKey执行扫描(),DynamoDB会返回什么? 我希望DynamoDB不会返回任何项目(如果我的假设是错误的,请纠正我),即扫描应该从Exclusiv

  • 问题内容: 我的视图中有一个按钮和文本文本字段。当我单击文本字段时,会出现一个键盘,并且我可以在文本字段上书写,并且还可以通过添加以下内容单击按钮来关闭键盘: 现在我要启用键盘的返回键。当我按键盘时,键盘会消失,并且会发生某些事情。我怎样才能做到这一点? 问题答案: 确保“自我”订阅并初始化inputText: 将以下方法添加到“自身”: 或在Swift中:

  • 我正在使用IPP协议与CUPS通信。我的打印机的所有驱动程序都安装在CUPS中(使用.ppd文件),打印机得到了最新的固件。 当我查询一个打印机正在打印的作业时,它表示该作业的状态在打印机完成打印之前就已经“完成”。CUPS似乎在完成文件“上传”后将作业标记为“完成”。 我不希望出现这种行为,我基本上需要知道打印机何时打印出作业的最后一张纸。代码如下所示。自身。打印机()。ippPrinter()

  • 我使用LiveData从DB中选择信息,并将其传递给我的活动(通过DAO、Repository&Viewmodel),依赖于一段时间的日期。当我更改timespan时,我希望删除LiveData上的旧观察者,并为新的timespan创建新的观察者。 但是,在调用和(其中timespan是之前的另一个时间戳)之后,两个观察器都调用了方法,尽管旧的方法不再活动(我使用和检查了这一点) 有什么建议吗?

  • 我正在使用Spring boot2.2.9。RELEASE和Spring Cloud Hoxton。SR7。我正在使用Spring Cloud Bus向docker群堆栈中的所有容器发出信号,并且当在生产环境中使用正在运行的RabbitMQ集群部署时,事情会完美运行! 我通过spring cloud starter总线amqp spring Boot starter使用RabbitMQ实现。我们偶

  • 我有一个扩展<code>HandlerThread<code>的类,它看起来像这样: 如上所示, 函数启动线程 在另一个类中,我创建了< code>MyHandlerThread的一个实例 控制台中显示的日志: 为什么在<code>prepare()