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がインデックスの更新を完了するのをどのように待つのですか?
バージョン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={
....
}
)
睡眠やポーリングは必要ありません。
私のために働くようです:
els.indices.refresh(index)
els.cluster.health(wait_for_no_relocating_shards=True,wait_for_active_shards='all')
バルクヘルパーを使用する場合は、次のように実行できます。
from elasticsearch.helpers import bulk
bulk(client=self.es, actions=data, refresh='wait_for')
クラスターの更新間隔を待たない場合は、elasticsearch.Refresh( 'blog')を呼び出すこともできます。