web-dev-qa-db-ja.com

ElasticSearchの更新は即時ではありません。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

現在、この問題のハッキングソリューションは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がインデックスの更新に1秒以上かかる場合は、テストが失敗する可能性は非常に低いですが。また、このような数百のテストを実行しているときは、非常に遅くなります。

この問題を解決するための私の試みは、 保留中のクラスタージョブ をクエリして、実行する必要のあるタスクが残っているかどうかを確認することでした。ただし、これは機能せず、このコードはアサーションエラーなしで実行されます。

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がインデックスの更新を完了するのをどのように待つのですか?

18
Rollo

バージョン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={
        ....
    }
)

睡眠やポーリングは必要ありません。

22
TinkerTank

私のために働くようです:

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

バルクヘルパーを使用する場合は、次のように実行できます。

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

クラスターの更新間隔を待たない場合は、elasticsearch.Refresh( 'blog')を呼び出すこともできます。

0
sramalingam24