web-dev-qa-db-fra.com

Les mises à jour d'ElasticSearch ne sont pas immédiates, comment attendez-vous qu'ElasticSearch termine la mise à jour de son index?

J'essaie d'améliorer les performances d'une suite qui teste contre ElasticSearch.

Les tests prennent beaucoup de temps car Elasticsearch ne met pas à jour ses index immédiatement après la mise à jour. Par exemple, le code suivant s'exécute sans déclencher une erreur d'assertion.

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

Actuellement, la solution piratée à ce problème supprime un time.sleep appeler le code, pour donner à ElasticSearch un peu de temps pour mettre à jour ses index.

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

Évidemment, ce n'est pas génial, car il est plutôt sujet aux échecs, hypothétiquement si ElasticSearch prend plus d'une seconde pour mettre à jour ses index, malgré le peu probable, le test échouera. De plus, il est extrêmement lent lorsque vous exécutez des centaines de tests comme celui-ci.

Ma tentative pour résoudre le problème a été d'interroger le travaux de cluster en attente pour voir s'il reste des tâches à effectuer. Cependant, cela ne fonctionne pas et ce code s'exécutera sans erreur d'assertion.

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

Donc, fondamentalement, revenons à ma question d'origine, les mises à jour d'ElasticSearch ne sont pas immédiates, comment attendez-vous qu'ElasticSearch termine la mise à jour de son index?

18
Rollo

Depuis la version 5.0.0, elasticsearch a une option:

 ?refresh=wait_for

sur les API Index, Update, Delete et Bulk. De cette façon, la demande ne recevra pas de réponse tant que le résultat ne sera pas visible dans ElasticSearch. (Yay!)

Voir https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-refresh.html pour plus d'informations.

edit: Il semble que cette fonctionnalité fasse déjà partie de la dernière Python elasticsearch api: https://elasticsearch-py.readthedocs.io/en/master/api.html# elasticsearch.Elasticsearch.index

Changez votre elasticsearch.update pour:

elasticsearch.update(
     index='blog',
     doc_type='blog'
     id=1,
     refresh='wait_for',
     body={
        ....
    }
)

et vous ne devriez pas avoir besoin de sommeil ni de sondages.

22
TinkerTank

Semble fonctionner pour moi:

els.indices.refresh(index)
els.cluster.health(wait_for_no_relocating_shards=True,wait_for_active_shards='all')
4
Héctor Sánchez

Si vous utilisez des assistants groupés, vous pouvez le faire comme ceci:

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

Vous pouvez également appeler elasticsearch.Refresh ('blog') si vous ne voulez pas attendre l'intervalle d'actualisation du cluster

0
sramalingam24