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

时间:2016-11-18 11:45:27

标签: python elasticsearch synchronization wait polling

我试图提高针对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

目前已解决此问题的解决方案是将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

显然这并不是很好,因为它很容易发生故障,假设ElasticSearch需要花费超过一秒的时间来更新它的索引,尽管不太可能,但测试会失败。当你运行100次这样的测试时,它也非常慢。

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

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

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

4 个答案:

答案 0 :(得分:16)

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

 ?refresh=wait_for
关于索引,更新,删除和批量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={
        ....
    }
)

你不应该进行任何睡眠或民意调查。

答案 1 :(得分:3)

似乎对我有用:

els.indices.refresh(index)
els.cluster.health(wait_for_no_relocating_shards=True,wait_for_active_shards='all')

答案 2 :(得分:0)

如果您不想等待群集刷新间隔,也可以调用elasticsearch.Refresh('blog')

答案 3 :(得分:0)

如果您使用批量助手,您可以这样做:

from elasticsearch.helpers import bulk    
bulk(client=self.es, actions=data, refresh='wait_for')