web-dev-qa-db-fra.com

Comment effacer l'index ElasticSearch?

Mon tests unitaires/d'intégration inclut des tests pour la fonctionnalité de recherche. 

Mon idée est d’avoir un index de recherche vide avant chaque test. Donc, j'essaie de supprimer tous les éléments de l'index sur la méthode setup (c'est du code 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()

On dirait que toutes les suppressions sont traitées de manière asynchrone. J'ai donc ajouté Thread.sleep(5000) après. Comme vous le voyez, j'essaie d'ouvrir/fermer une connexion plusieurs fois - cela ne sert à rien.

Le problème est que parfois, il faut plus de temps, plus de 5 secondes pour le supprimer, parfois, il ne peut pas trouver les données simplement ajoutées (du test précédent), etc., etc. Et le plus ennuyeux est que les tests d'intégration deviennent instables. Mettre Thread.sleep() partout où cela est possible ne semble pas être une si bonne solution.

Y at-il un moyen de commettre dernières modifications, ou de faire un verrouiller jusqu'à ce que toutes les données soient écrites?

27
Igor Artamonov

Solution trouvée:

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);
}

et 

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

après avoir mis de nouvelles données dans l'index.

34
Igor Artamonov

Tout d'abord, il n'est pas nécessaire d'effacer toutes les données en effectuant une suppression sur chaque ID de document. Vous pouvez simplement supprimer toutes les données avec suppression par requête correspondant à tous les documents http://www.elasticsearch.org/guide/reference/api/delete-by-query.html Cela dit, je ne le recommande pas non plus. , car il n’est pas recommandé de le faire souvent sur de grandes collections de documents (voir la documentation).

Ce que vous voulez vraiment faire, c'est supprimer tout l'index (c'est rapide) http://www.elasticsearch.org/guide/reference/api/admin-indices-delete-index.html , le recréer, le mettre dans data and this est important actualise l'index pour "valider" les modifications et les rendre visibles. http://www.elasticsearch.org/guide/reference/api/admin-indices-refresh.html

Je le fais dans mes tests et je n’ai jamais eu de problème.

29
johno
  1. ce n'est pas l'appel async (vous pouvez ajouter un écouteur et éviter actionGet pour obtenir l'appel async)
  2. supprimer tous les éléments via:

    client.prepareDeleteByQuery(indexName).
                setQuery(QueryBuilders.matchAllQuery()).
                setTypes(indexType).
                execute().actionGet();
    
  3. actualisez votre index pour voir les modifications (requis uniquement dans les tests unitaires)

5
Karussell

Mon idée est d'avoir un index de recherche vide avant chaque test

Créez donc un nouvel index au début du test, ne réutilisez pas l'ancien. Vous êtes alors assuré d'avoir un vide. Dans le démontage des tests, vous pouvez ensuite supprimer l'index de test.

Y at-il un moyen de valider les dernières modifications ou de verrouiller l’écran jusqu’à ce que toutes les données soient écrites?

Non, ElasticSearch n'a aucune transaction ou verrouillage.

Si vous ne voulez pas créer un nouvel index à chaque fois, essayez d'ajouter une boucle qui vérifie si l'index est vide, puis attend et tente à nouveau de le faire.

0
skaffman