具体来说,我正在使用Elasticsearch进行分页,但这个问题可能适用于任何数据库。
Elasticsearch为paginate search results提供方便的from
和to
参数。
所以我运行了一个查询get me the most recent data from result 1 to 10
这很有效。
用户点击“下一页”,查询为:
get me the most recent data from result 11 to 20
问题是,在两个查询之间的时间内,后备数据库中添加了2个新记录,这意味着分页结果将重叠(第一页的最后2个显示为第二页上的前两个) )。
避免这种情况的最佳解决方案是什么?现在,我在查询中添加了一个过滤器,告诉它只包含比上一个查询的最后结果晚的结果。但它似乎只是hackish。
答案 0 :(得分:8)
如果您已经为相关时间戳编制索引,则过滤器不是一个糟糕的选择。您必须在客户端跟踪该时间戳才能正确准备查询。你还必须知道何时摆脱它。但这些并非难以克服的问题。
Scroll API是一个可靠的选项,因为它可以在Elasticsearch方面及时快速创建快照。 Scroll API的目的是为深度分页提供稳定的搜索查询,该查询必须处理您遇到的确切更改问题。
您通过提供查询和scroll
参数开始Scrolling Search,Elasticsearch为其返回scroll_id
。然后,您向提供该ID的/_search/scroll
发出请求,每个ID都返回一个结果页面,并为下一个请求返回新的scroll_id
。
(请注意,您不想要scan
搜索类型。这用于提取文档 en masse,并且不应用任何排序。 )
与过滤相比,您仍然需要跟踪一个值:scroll_id
用于下一页结果。这是否比跟踪时间戳更容易取决于您的应用。
还有其他潜在的缺点需要考虑。 Elasticsearch会在群集中的单个节点上保留搜索的上下文。可以想象,这些可能会累积在您的群集中,具体取决于您依赖滚动搜索的程度。您需要测试那里的性能影响。如果我没记错的话,滚动搜索也不会因节点故障或重启而持续存在。
Scroll API的ES文档提供了有关上述所有内容的详细信息。
底线:按时间戳过滤实际上并不是一个糟糕的选择。 Scroll API是另一个有效的选项,专为类似的用例而设计,但并非没有缺点。
答案 1 :(得分:2)
意识到这有点旧了,但是在ElasticSearch 6.3中,请求正文现在有了search_after
功能,它允许进行游标类型的分页:
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-search-after.html
它与滚动API非常相似,但与之不同的是,search_after参数是无状态的,始终会针对最新版本的搜索器进行解析。
答案 2 :(得分:-1)
您需要使用扫描API。扫描和滚动API让您进行时间点搜索和分页。 扫描API -