ElasticSearch更新不是立竿见影的,你如何等待ElasticSearch完成更新它的索引?

Rol*_*llo 15 python synchronization polling wait elasticsearch

我正在尝试提高针对ElasticSearch进行测试的套件的性能.

测试需要很长时间,因为Elasticsearch在更新后不会立即更新它的索引.例如,以下代码运行时不会引发断言错误.

from elasticsearch import Elasticsearch
elasticsearch = Elasticsearch('es.test')

# Asumming that this is a clean and empty elasticsearch instance
elasticsearch.update(
     index='blog',
     doc_type=,'blog'
     id=1,
     body={
        ....
    }
)

results = elasticsearch.search()
assert not results
# results are not populated
Run Code Online (Sandbox Code Playgroud)

目前解决这个问题的解决方案是将time.sleep调用放入代码中,以便给ElasticSearch一些时间来更新它的索引.

from time import sleep
from elasticsearch import Elasticsearch
elasticsearch = Elasticsearch('es.test')

# Asumming that this is a clean and empty elasticsearch instance
elasticsearch.update(
     index='blog',
     doc_type=,'blog'
     id=1,
     body={
        ....
    }
)

# Don't want to use sleep functions
sleep(1)

results = elasticsearch.search()
assert len(results) == 1
# results are now populated
Run Code Online (Sandbox Code Playgroud)

显然这不是很好,因为它相当容易失败,假设ElasticSearch需要更长的时间来更新它的索引,尽管不太可能,测试会失败.当你运行100次这样的测试时,它也非常慢.

我尝试解决此问题的方法是查询待处理的群集作业,以查看是否还有任何任务要完成.但是这不起作用,并且此代码将在没有断言错误的情况下运行.

from elasticsearch import Elasticsearch
elasticsearch = Elasticsearch('es.test')

# Asumming that this is a clean and empty elasticsearch instance
elasticsearch.update(
     index='blog',
     doc_type=,'blog'
     id=1,
     body={
        ....
    }
)

# Query if there are any pending tasks
while elasticsearch.cluster.pending_tasks()['tasks']:
    pass

results = elasticsearch.search()
assert not results
# results are not populated
Run Code Online (Sandbox Code Playgroud)

所以基本上,回到我原来的问题,ElasticSearch更新不是立竿见影的,你如何等待ElasticSearch完成更新它的索引?

Tin*_*ank 21

从5.0.0版开始,elasticsearch有一个选项:

 ?refresh=wait_for
Run Code Online (Sandbox Code Playgroud)

关于索引,更新,删除和批量API.这样,在ElasticSearch中显示结果之前,请求不会收到响应.(好极了!)

有关详细信息,请参阅https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-refresh.html.

编辑:似乎这个功能已经是最新的Python elasticsearch api的一部分:https: //elasticsearch-py.readthedocs.io/en/master/api.html#elasticsearch.Elasticsearch.index

将elasticsearch.update更改为:

elasticsearch.update(
     index='blog',
     doc_type='blog'
     id=1,
     refresh='wait_for',
     body={
        ....
    }
)
Run Code Online (Sandbox Code Playgroud)

你不应该需要任何睡眠或投票.


小智 6

似乎对我有用:

els.indices.refresh(index)
els.cluster.health(wait_for_no_relocating_shards=True,wait_for_active_shards='all')
Run Code Online (Sandbox Code Playgroud)


Con*_* DO 5

Elasticsearch 进行近乎实时的搜索。更新/索引的文档不能立即搜索,只能在下一次刷新操作之后搜索。计划每 1 秒刷新一次。

要在更新/索引后检索文档,您应该使用 GET api。默认情况下,get API 是实时的,不受索引刷新率的影响。这意味着如果更新/索引正确完成,您应该在 GET 请求的响应中看到修改。

如果您坚持在更新/索引后使用 SEARCH api 检索文档。然后从文档来看,有3种解决方案:

  • 等待刷新间隔
  • 在索引/更新/删除请求中设置?refresh 选项
  • 在索引/更新请求后,使用刷新 API显式完成刷新 (POST _refresh)。但请注意,刷新会占用大量资源。