Elasticsearch+Kendo UI Grid:虚拟滚动替代无限滚动的实现疑问
嘿,刚好我之前在Kendo UI Grid里结合Elasticsearch做虚拟滚动的时候踩过类似的坑,给你分享几个实用的解决方案:
方案1:用Point in Time (PIT) + Search After 替代Scroll API
这是Elasticsearch 7.10+推出的特性,完美解决Scroll API无法灵活控制请求范围的问题,同时还能保持会话级的数据一致性(就像Scroll的快照机制一样)。
- 核心逻辑:先创建一个PIT(索引数据的快照会话),之后所有查询都绑定到这个PIT上,用
search_after参数基于上一页最后一条数据的排序值来获取下一页,也可以结合size控制每页数量。相比Scroll,它支持你在同一个会话里灵活调整查询范围,甚至实现跳页(只要你能拿到对应位置的排序值)。 - 具体步骤:
- 初始化时创建PIT,设置
keep_alive(会话存活时间,比如1分钟):
接口会返回一个POST /your_index/_pit?keep_alive=1mpit_id,后续所有查询都要带上这个ID。 - 第一次查询数据,指定
size和唯一排序字段(比如业务ID,避免排序冲突):GET /_search { "size": 50, "query": { "match": { "your_field": "your_value" } }, "sort": [ { "id": "asc" } ], "pit": { "id": "YOUR_PIT_ID", "keep_alive": "1m" } } - 拿到返回结果后,记录最后一条数据的
sort值,下次查询用search_after参数定位:GET /_search { "size": 50, "query": { "match": { "your_field": "your_value" } }, "sort": [ { "id": "asc" } ], "pit": { "id": "YOUR_PIT_ID", "keep_alive": "1m" }, "search_after": [LAST_RECORD_SORT_VALUE] } - 会话结束后记得删除PIT,避免占用ES资源:
DELETE /_pit { "id": "YOUR_PIT_ID" }
- 初始化时创建PIT,设置
- 结合Kendo UI Grid虚拟滚动:你可以在Grid的
dataSource.transport.read方法里处理PIT的创建、查询参数拼接,以及search_after的更新。Grid的虚拟滚动会自动触发数据加载事件,你只需要根据当前需要加载的位置传递对应参数即可。
方案2:直接用
from + size(适合小数据量场景) 如果你的数据总量不大(比如少于10000条),直接用ES的from和size参数是最简单的方案,完全不需要额外的会话机制。
- 核心逻辑:Kendo UI Grid的虚拟滚动会自动传递
skip(对应ES的from)和take(对应ES的size)参数,你只需要把这两个参数映射到ES的查询里就行。 - 示例代码(Kendo UI部分):
$("#yourGrid").kendoGrid({ virtual: true, scrollable: { virtual: true }, dataSource: { transport: { read: function(options) { const esQuery = { from: options.data.skip, size: options.data.take, query: { "match_all": {} } // 替换成你的实际查询条件 }; // 发送请求到ES fetch('/_search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(esQuery) }) .then(res => res.json()) .then(response => { options.success({ data: response.hits.hits.map(hit => hit._source), total: response.hits.total.value }); }); } }, schema: { data: 'data', total: 'total' }, pageSize: 50 } }); - 注意事项:ES默认限制
from + size不能超过10000,如果你的数据量超过这个值,要么修改索引的index.max_result_window参数(不推荐大数据量修改,会影响查询性能),要么就改用方案1。
为什么不推荐继续用Scroll API?
Scroll API的设计初衷是批量导出全量数据,它创建快照后只能按顺序遍历,无法跳转到指定位置(也就是没法控制from),完全不适合虚拟滚动场景——用户可能直接拖动滚动条到中间位置,这时候Scroll API根本没法快速定位到对应数据段。
总结一下:如果数据量大或者需要严格的数据一致性,优先选PIT + Search After;如果数据量小,直接用from + size最省事。
内容的提问来源于stack exchange,提问作者Meyra
相关产品推荐
相关产品推荐

