Обновления 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 обновляет свои индексы дольше, чем секунда, несмотря на то, что маловероятно, что тест провалится. Кроме того, это очень медленно, когда вы запускаете сотни тестов, как это.
Моя попытка решить эту проблему состояла в том, чтобы запросить ожидающие задания кластера, чтобы узнать, есть ли еще задачи, которые нужно выполнить. Однако это не работает, и этот код будет работать без ошибки подтверждения.
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 ответов
Начиная с версии 5.0.0,asticsearch имеет опцию:
?refresh=wait_for
на Индекс, Обновление, Удалить и Массовые API. Таким образом, запрос не получит ответ, пока результат не будет виден в ElasticSearch. (Ура!)
См. https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-refresh.html для получения дополнительной информации.
редактировать: кажется, что эта функциональность уже является частью последнего API Python эластичного поиска: https://elasticsearch-py.readthedocs.io/en/master/api.html
Измените ваш asticsearch.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')
Elasticsearch выполняет . Обновленный/индексированный документ доступен для поиска не сразу, а только после следующей операции обновления. Обновление планируется каждую 1 секунду.
Чтобы получить документ после обновления/индексации, вместо этого следует использовать GET API. По умолчанию API получения работает в режиме реального времени и не зависит от частоты обновления индекса . Это означает, что если обновление/индекс было выполнено правильно, вы должны увидеть изменения в ответе на запрос GET.
Если вы настаиваете на использовании SEARCH API для извлечения документа после обновления/индексации. поиск практически в реальном времениТогда из документации есть 3 решения :
- Ожидание интервала обновления
- Установка параметра ?refresh в запросе на индексирование/обновление/удаление
- Использование Refresh API для явного завершения обновления (POST _refresh) после запроса индекса/обновления. Однако обратите внимание, что обновления требуют больших ресурсов.
Если вы используете массовые помощники, вы можете сделать это так:
from elasticsearch.helpers import bulk
bulk(client=self.es, actions=data, refresh='wait_for')
Вы также можете вызвать asticsearch.Refresh('blog'), если не хотите ждать интервала обновления кластера.