Индекс ElasticSearch не работает/надежно

Я пишу простую оболочку Java вокруг клиента администратора ElasticSearch. Чтобы проверить его, у меня есть основной метод, который сначала проверяет, существует ли индекс (IndicesExistsRequest), если он его удаляет (DeleteIndexRequest) и снова создает индекс. См. Код ниже. Тем не менее я постоянно получаю исключение IndexAlreadyExistsException.

Кстати, я пытаюсь получить клиент для node, который вы запускаете из командной строки (просто набрав "эластичный поиск" ). Я пробовал каждую комбинацию методов на свободном интерфейсе nodeBuilder, но, похоже, я не могу ее получить.

public static void main(String[] args) {
    ElasticSearchJavaClient esjc = new ElasticSearchJavaClient("nda");
    if (esjc.indexExists()) {
        esjc.deleteIndex();
    }
    esjc.createIndex();
    URL url = SchemaCreator.class.getResource("/elasticsearch/specimen.type.json");
    String mappings = FileUtil.getContents(url);
    esjc.createType("specimen", mappings);
}

final Client esClient;
final IndicesAdminClient adminClient;
final String indexName;

public ElasticSearchJavaClient(String indexName) {
    this.indexName = indexName;
    esClient = nodeBuilder().clusterName("elasticsearch").client(true).node().client();
    adminClient = esClient.admin().indices();
}

public boolean deleteIndex() {
    logger.info("Deleting index " + indexName);
    DeleteIndexRequest request = new DeleteIndexRequest(indexName);
    try {
        DeleteIndexResponse response = adminClient.delete(request).actionGet();
        if (!response.isAcknowledged()) {
            throw new Exception("Failed to delete index " + indexName);
        }
        logger.info("Index deleted");
        return true;
    } catch (IndexMissingException e) {
        logger.info("No such index: " + indexName);
        return false;
    }
}

public boolean indexExists() {
    logger.info(String.format("Verifying existence of index \"%s\"", indexName));
    IndicesExistsRequest request = new IndicesExistsRequest(indexName);
    IndicesExistsResponse response = adminClient.exists(request).actionGet();
    if (response.isExists()) {
        logger.info("Index exists");
        return true;
    }
    logger.info("No such index");
    return false;
}

public void createIndex() {
    logger.info("Creating index " + indexName);
    CreateIndexRequest request = new CreateIndexRequest(indexName);
    IndicesAdminClient iac = esClient.admin().indices();
    CreateIndexResponse response = iac.create(request).actionGet();
    if (!response.isAcknowledged()) {
        throw new Exception("Failed to delete index " + indexName);
    }
    logger.info("Index created");
}

Ответ 1

ОК, я понял решение. Поскольку вызовы java-клиентов выполняются асинхронно, вы должны использовать вариант, который принимает прослушиватель действий. Решение все еще немного придумано, хотя:

// Inner class because it just used to be thrown out of
// the action listener implementation to signal that the
// index exists
private class ExistsException extends RuntimeException {
}

public boolean exists() {
    logger.info(String.format("Verifying existence of index \"%s\"", indexName));
    IndicesExistsRequest request = new IndicesExistsRequest(indexName);
    try {
        adminClient.exists(request, new ActionListener<IndicesExistsResponse>() {
            public void onResponse(IndicesExistsResponse response) {
                if (response.isExists()) {
                    throw new ExistsException();
                }
            }
            public void onFailure(Throwable e) {
                ExceptionUtil.smash(e);
            }
        });
    }
    catch (ExistsException e) {
        return true;
    }
    return false;
}

Ответ 2

Вы также можете выполнить синхронный запрос следующим образом:

boolean exists = client.admin().indices()
    .prepareExists(INDEX_NAME)
    .execute().actionGet().isExists();

Ответ 3

ответ skgemini одобрен, если вы хотите проверить, доступен ли индекс по фактическому имени индекса или любому из его псевдонимов.

Если вы хотите проверить только по имени индекса, вот как.

public boolean checkIfIndexExists(String index) {

    IndexMetaData indexMetaData = client.admin().cluster()
            .state(Requests.clusterStateRequest())
            .actionGet()
            .getState()
            .getMetaData()
            .index(index);

    return (indexMetaData != null);

}

Ответ 4

У меня была такая же проблема, но мне не понравилось решение, которое использует ActionListener. ElasticSearch также предлагает вариант Future (по крайней мере, в версии 6.1.0).

Здесь фрагмент кода:

public boolean doesIndexExists(String indexName, TransportClient client) {
    IndicesExistsRequest request = new IndicesExistsRequest(indexName);
    ActionFuture<IndicesExistsResponse> future = client.admin().indices().exists(request);
    try {
        IndicesExistsResponse response = future.get();
        boolean result = response.isExists();
        logger.info("Existence of index '" + indexName + "' result is " + result);
        return result;
    } catch (InterruptedException | ExecutionException e) {
        logger.error("Exception at waiting for IndicesExistsResponse", e);
        return false;//do some clever exception handling
    }
}

Может быть, это тоже помогает кому-то другому. Ура!