Как стереть индекс ElasticSearch? - PullRequest
28 голосов
/ 05 ноября 2011

Мои тесты модулей / интеграции включает в себя тесты для поиска.

Моя идея - иметь пустой поисковый индекс перед каждым тестом.Итак, я пытаюсь удалить все элементы в индексе по методу setup (это код Groovy):

Client client = searchConnection.client

SearchResponse response = client.prepareSearch("item")
    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
    .setQuery(termQuery('name', 'test')) //tried also matchAllQuery()
    .setFrom(0).setSize(100).setExplain(false).execute().actionGet()

List<String> ids = response.hits.hits.collect {
    return it.id
}
client.close()

client = searchConnection.client

ids.each {
    DeleteResponse delete = client.prepareDelete("item", "item", it)
        .setOperationThreaded(false)
        .execute().actionGet()
}

client.close()

Кажется, что он обрабатывает все удаления асинхронно, поэтому я добавил Thread.sleep(5000) после него,Как вы видите, я пытаюсь открыть / закрыть соединение несколько раз - это не помогает.

Проблема в том, что иногда требуется больше времени, иногда для удаления требуется более 5 секунд, иногда это можетнайти только добавленные данные (из предыдущего теста) и т. д., и т. д. И самое неприятное, что интеграционные тесты становятся нестабильными.Помещение Thread.sleep() везде, где это возможно, выглядит не очень хорошим решением.

Это может каким-либо образом зафиксировать последние изменения или сделать блокировку , пока все данные не будутбыть написано?

Ответы [ 4 ]

34 голосов
/ 04 июня 2012

Найденное решение:

IndicesAdminClient adminClient = searchConnection.client.admin().indices();
String indexName = "location";
DeleteIndexResponse delete = adminClient.delete(new DeleteIndexRequest(indexName)).actionGet()
if (!delete.isAcknowledged()) {
    log.error("Index {} wasn't deleted", indexName);
}

и

client.admin().indices().flush(new FlushRequest('location')).actionGet();

после помещения новых данных в индекс.

29 голосов
/ 06 ноября 2011

Прежде всего вам не нужно очищать все данные, выполнив удаление каждого идентификатора документа.Вы можете просто удалить все данные с помощью delete, выполнив запрос, соответствующий всем документам http://www.elasticsearch.org/guide/reference/api/delete-by-query.html С учетом вышесказанного я тоже не рекомендую этого делать, поскольку не рекомендуется делать это часто в больших коллекциях документов (см. Документы).

Что вы действительно хотите сделать, это удалить весь индекс (это быстро) http://www.elasticsearch.org/guide/reference/api/admin-indices-delete-index.html, воссоздать его, вставить данные и это важно обновить индекс, чтобы "зафиксировать" измененияи сделать их видимыми.http://www.elasticsearch.org/guide/reference/api/admin-indices-refresh.html

Я делаю это в своих тестах, и у меня никогда не было проблем.

5 голосов
/ 05 ноября 2011
  1. это не асинхронный вызов (вы можете добавить слушателя и избежать действия actionGet для получения асинхронного вызова)
  2. удалить все элементы с помощью:

    client.prepareDeleteByQuery(indexName).
                setQuery(QueryBuilders.matchAllQuery()).
                setTypes(indexType).
                execute().actionGet();
    
  3. обновить индекс, чтобы увидеть изменения (требуется только в модульных тестах)

0 голосов
/ 05 ноября 2011

Моя идея состоит в том, чтобы иметь пустой поисковый индекс перед каждым тестом

Поэтому создайте новый индекс в начале теста, не используйте старый повторно.Тебе гарантировано пустое место.В этом тесте вы можете удалить тестовый индекс.

Есть ли способ зафиксировать последние изменения или сделать блокировку до тех пор, пока не будут записаны все данные?* Нет, ElasticSearch не имеет транзакций или блокировки.

Если вы не хотите каждый раз создавать новый индекс, попробуйте добавить цикл, который проверяет, пустой ли индекс, затем ждет и пытается снова,пока это не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...