我对Elasticsearch的滚动功能有点困惑。在弹性搜索中,每当用户滚动结果集时,是否可以调用搜索API?来自文件
"search_type" => "scan", // use search_type=scan
"scroll" => "30s", // how long between scroll requests. should be small!
"size" => 50, // how many results *per shard* you want back
这是否意味着它将每30秒执行一次搜索,并返回所有结果集,直到没有记录为止?
例如,我的ES总共返回500条记录。我从ES得到的数据是两组记录,每组250条记录。有没有什么方法可以先显示第一组250条记录,当用户滚动时,再显示第二组250条。请建议
您想要的是分页。
您可以通过查询固定大小并设置from
参数来实现目标。由于您希望以250个结果的批次设置显示,因此可以设置size = 250
,并且对于每个连续的查询,将from
的值增加250
。
GET /_search?size=250 ---- return first 250 results
GET /_search?size=250&from=250 ---- next 250 results
GET /_search?size=250&from=500 ---- next 250 results
相反,Scan & scroll
允许您通过一次搜索检索大量结果,非常适合将数据重新索引到新索引中等操作。不建议使用它来实时显示搜索结果。
为了简单地解释Scan & scroll
,它的本质是扫描扫描请求提供的查询的索引,并返回一个scroll_id
。这个scroll_id
可以被传递到下一个滚动请求,以返回下一批结果。
考虑以下示例-
# Initialize the scroll
page = es.search(
index = 'yourIndex',
doc_type = 'yourType',
scroll = '2m',
search_type = 'scan',
size = 1000,
body = {
# Your query's body
}
)
sid = page['_scroll_id']
scroll_size = page['hits']['total']
# Start scrolling
while (scroll_size > 0):
print "Scrolling..."
page = es.scroll(scroll_id = sid, scroll = '2m')
# Update the scroll ID
sid = page['_scroll_id']
# Get the number of results that we returned in the last scroll
scroll_size = len(page['hits']['hits'])
print "scroll size: " + str(scroll_size)
# Do something with the obtained page
在上面的例子中,发生了以下事件-
- 滚动条已初始化。这将返回第一批结果以及scroll_id
- 对于每个后续滚动请求,发送更新的
scroll_id
(在上一滚动请求中接收),并返回下一批结果 - 滚动时间基本上是搜索上下文保持活动的时间。如果下一个滚动请求没有在设定的时间范围内发送,则搜索上下文将丢失,并且不会返回结果。这就是为什么它不应该用于具有大量文档的索引的实时结果显示
您对scroll
属性的用途理解错误。这并不意味着弹性搜索将在30秒后获取下一页数据。当您进行第一次滚动请求时,您需要指定何时关闭滚动上下文。scroll
参数指示30秒后关闭滚动上下文。
完成第一次滚动请求后,您将返回scroll_id
参数作为响应。对于下一页,您需要传递该值以获得滚动响应的下一页。如果您在30秒内没有进行下一次滚动请求,则滚动请求将关闭,您将无法获得该滚动请求的下一页。
您所描述的示例用例实际上是搜索结果分页,它可用于任何搜索查询,并且受10k个结果的限制。当您需要超过10k的限制时,需要scroll
请求,使用scroll
查询,您甚至可以获取整个文档集合。
这里混淆的原因可能是scroll
术语不明确:它意味着查询的类型,也是此类查询的参数的名称(正如其他评论中所提到的,是时候让ES继续等待您获取下一个滚动块了)。
scroll
查询量很大,在绝对必要之前应该避免。事实上,在文档中上面写着:
滚动不是用于实时用户请求,而是用于处理大量数据。。。
现在关于您的另一个问题:
在弹性搜索中,每当用户滚动结果集时,是否可以调用搜索API?
是,甚至有几个并行滚动请求有可能:
每个滚动都是独立的,可以像任何滚动请求一样并行处理。
弹性的Scroll API文档也解释了这种行为。
10k的结果大小是默认值,如果需要,可以在运行时覆盖:
PUT { "index" : { "max_result_window" : 500000} }
滚动id的使用寿命在每个滚动请求中定义,参数为"滚动",例如
..
"scroll" : "5m"
..
在最新版本的Elasticsearch中,您将使用search_after。您在那里设置的keep_alive
与滚动中的timeout
非常相似,只是处理一页所需的时间。
这是因为Elasticsearch将保留您的";搜索上下文";存活了那么长时间,然后将其删除。此外,Elasticsearch不会自动为您获取下一页,您必须使用上一个请求中的ID发送请求。
使用滚动api是明智的,因为在弹性搜索中一次不能获得超过10K的数据。