Algorithm 使用本地数据缓存的智能分页算法

Algorithm 使用本地数据缓存的智能分页算法,algorithm,pagination,Algorithm,Pagination,这是一个我思考了很长时间的问题,但我还没有编写任何代码,因为我首先想解决一些我正在努力解决的一般问题。这是主要的 背景 单页web应用程序向某个远程API(在我们的控制下)发出数据请求。然后,它将这些数据存储在本地缓存中,并从那里为页面提供服务。理想情况下,该应用程序在脱机时保持完全功能,包括创建新对象的能力 约束条件 假设服务器端产品数据库包含+-50000个产品(50Mb) 假设没有db类型,我们通过REST/GraphQL接口与之交互 假设单个产品记录小于1kB 假设结果集的最大有效负载

这是一个我思考了很长时间的问题,但我还没有编写任何代码,因为我首先想解决一些我正在努力解决的一般问题。这是主要的

背景 单页web应用程序向某个远程API(在我们的控制下)发出数据请求。然后,它将这些数据存储在本地缓存中,并从那里为页面提供服务。理想情况下,该应用程序在脱机时保持完全功能,包括创建新对象的能力

约束条件
  • 假设服务器端产品数据库包含+-50000个产品(50Mb)
  • 假设没有db类型,我们通过REST/GraphQL接口与之交互
  • 假设单个产品记录小于1kB
  • 假设结果集的最大有效负载为256kB
  • 假定客户端上的最大存储容量为5MB
  • 假设搜索结果集介于0。。。每次搜索5000个项目
挑战 挑战在于定义一种无状态但(网络)高效的从结果集中获取页面的方法,以便确定我们将获得哪些结果

例子 在传统分页中,当使用此url获取某个查询的下100个结果时:

https://example.com/products?category=shoes&firstResult=100&pageSize=100
搜索结果可能如下所示:

{
  "totalResults": 2458,
  "firstResult": 100,
  "pageSize": 100,
  "results": [
    {"some": "item"},
    {"some": "other item"},
    // 98 more ...
  ]
}
问题在于,基于这些信息,无法准确获取某个页面上的对象。因为当我们请求下一页时,结果集可能已经更改(由于数据库中的更改),从而影响哪些项是结果集的一部分。即使是很小的更改也会产生很大的影响:从数据库中删除的一个项目(恰好位于结果集的第0页)将更改我们在请求所有后续页面时得到的结果

目标 我正在寻找一种机制,使结果集的定义独立于未来的数据库更改,因此,如果有人正在寻找鞋子并得到一个包含2458项的结果集,他实际上可以可靠地获取该结果集的所有页面,即使它受到数据库中稍后更改的影响(为此,我计划不真正删除项目,但在其上设置删除标志)

迄今为止的想法 我看到了一个解决方案,其中结果集包含一个
“页面”
property,该属性是一个数组,其中包含该页面中项目的第一个和最后一个id。假设您的id不断增加,并且您从未真正从数据库中删除项目,则两个id之间的项目数是恒定的。这意味着应用程序可以获取这两个id之间的所有项目,并始终获取完全相同的项目。问题在于这个解决方案是,它只有在列表按ID顺序排序时才起作用…我需要自定义排序选项

目前我想到的唯一方法是只发送一个结果集中所有id的列表…这样就可以通过从id位于(3,4,6,9,…)的产品中执行
SELECT*来获取页面。
…但这感觉相当不雅


无论如何,我希望它不要太宽泛或过于理论化。我有一个基于web的DB,只是不知道如何使用它进行分页。我正在寻找帮助我学习的答案,而不是完整的解决方案。

版本化DB是结果集一致性的答案。 每个记录都有主id、修改计数器(版本号)和修改/创建的时间戳。不修改记录r,而是添加具有相同id、版本号+1和sysdate的新记录进行修改


在fetch响应中添加DB request_time(由于客户机/服务器之间可能存在时间差异,所以不要使用客户机时间戳)。第一个页面正常服务,但您返回sysdate作为请求时间。其他页面的服务方式不同:您添加修改时间之类的条件当查询第一次到达时,您可以在服务器端缓存ID的结果集,并将唯一ID返回前端。此唯一ID对应于该查询的结果集。因此,现在前端可以请求类似于
next\u page
的内容,并使用它第一次进行查询时获得的唯一ID。您仍然应该继续将
DELETE
操作更改为
removed
操作,因为这样可以确保不会删除结果集中的任何条目。您可以当前端到达结果集的末尾时,从缓存中丢弃查询的结果集,或者您可以设置缓存项生存期的时间限制。

我可能遗漏了一些内容,但是如果用户能够脱机创建新对象,则索引不能是连续的(除非您对脱机对象有不同的id)。通常情况下,人们并不关心这一点,只是获取项目。您的记录更新的速度有多快,从而成为一个问题?@fpg1503系统将使用一个分布式ID生成器,可以脱机工作。因此,客户端甚至在插入记录之前就知道该记录的ID。我正在寻找的是一种以这种方式捕获结果集的方法随着时间的推移,它是稳定的。单个项目的内容可能会发生变化,但我不希望项目的顺序或集合中的项目发生变化。这是因为我以“无限滚动列表”的形式呈现项目,尽可能保持一种错觉,即即使在虽然只有一小部分实际上同时出现在屏幕上。请看一个例子。我希望它可以扩展到10.000多个项目。@fpg1503我想直到现在我才理解您关于索引不连续的评论。您的意思是它不能保证只正确地上升?我想您是对的。我目前正在使用此手动生成程序:。服务器将ID块分发给客户端,客户端可以在脱机时缓存和使用。它会随着时间的推移而增加,但由于缓存,在使用了较高ID后,可以使用较低的ID。似乎我遇到的问题比我想象的要多……感谢您的回复!耶