用多个标题分页查询结果

时间:2018-11-18 13:06:25

标签: algorithm pagination microservices relation

我们有一个微服务,用于对象之间的关系建模。在具有基数约束(例如1-1、1-N,N-N等)的主要对象和次要对象之间定义了一种关系。 该微服务提供了诸如创建关系,查找关系,获取辅助,获取主等之类的API。

查询API“获取次要对象”获取一个主要对象,并返回所有相关的次要对象。由于相关的次要对象可能很大,因此对结果进行分页。

我们还有另一个微服务,该微服务很好地利用了此关系微服务来处理关系。此使用服务接受了类似的分页选项(例如页面索引和编号),并将其传递给关系服务,然后将从关系服务获得的页面结果返回给调用应用程序。到目前为止一切都很好。

我们最近发现,消费微服务与关系微服务有点闲谈,因为考虑到有多个主要对象必须为其获取次要对象,因此它不得不多次调用“获取次要” API。

因此,我们认为通过使其接受多个主要对象作为输入,可以使“获取次要” API成为批量API。但是后来我们陷入了分页的工作方式。 该API将为每个主要对象返回相关的辅助对象,但像先前那样将辅助对象限制为页面大小。
第一次调用似乎很好,但是我们不确定随后的调用会如何。如果次要对象的数量少于一个或多个主要对象的页面大小,那么后续调用的输入应该是什么。我是否需要再次传递这些主要对象?

这是我们在寻找有关如何设计此批量API的建议的地方。欢迎任何输入。

1 个答案:

答案 0 :(得分:0)

基本上,您应该有某种方法来确保关系服务在接收到分页的请求时知道原始查询是什么。

关系服务处理此问题的一种简单且可维护的方法是通过以某种方式对请求的主要对象进行排序(即,按ID按字母顺序排序)来预处理请求,然后简单地遍历主要对象,添加次要对象直到响应已满。

客户要做的最简单的事情是始终使用相同的批处理请求,而只是向请求添加索引号或页面令牌。

我建议您使用一个页面令牌,该令牌提及最近一次看到的项目(例如lastSeen=primaryId,secondaryId(您应该以某种方式进行混淆以避免抽象的泄漏))。然后,该服务可以查看原始请求,并知道在哪里恢复对所有主要对象的迭代。

或者,您可以将足够的信息编码为页面令牌,以便可以从原始请求中重建所需的内容。这使您可以对后续请求的查询进行一些调整。 (例如,如果客户端请求主对象A-Z,而您在第一个响应中返回辅助对象A1 - J5,则可以将请求修改为J-Z; already seen J5,对其进行编码,这样您就可以不会泄漏您的实现详细信息,并将其作为页面令牌返回给客户端。)然后,客户端无需使用original request + page number进行响应,而是仅使用页面令牌进行响应。

无论哪种方式,关系服务的客户都应该从不必须“弄清楚”下一页的请求是什么。分页仅要求消费者增加一个数字或使用关系服务给予它的页面令牌进行响应。

另一个要考虑的是您正在使用的数据库。例如,在DynamoDB中,为select * from secondaries where primaryId='ABC'之类的查询获取第100个项目的方法要求您读取直到第100个项目的所有项目。如果您拥有NoSQL数据库,或者您认为将来可能会转移到NoSQL数据库,则可能会发现页面令牌使维护结果集中的位置更加容易(与索引号)。

当我自己学习分页时,我发现this article很有帮助,建议阅读。它主要处理UI的分页问题,​​但基本原理相同。

TLDR :不要让使用者做任何工作。消费者应使用添加的索引号或页面令牌重复原始请求,或者消费者应发送仅包含页面令牌的请求。