2015-03-18 1 views
3

Je suis nouveau à ELastic Search.Elastic Search API de recherche de données parent-enfant Java

Les données de recherche élastique sont dans le modèle parent-enfant.Je veux effectuer une recherche dans ces données en utilisant java api. Le type parent contient les détails de l'auteur et le type de l'enfant contient les détails du livre comme le nom du livre, l'éditeur du livre, la catégorie du livre. Pendant que j'effectue une recherche sur les détails de l'enfant, je dois également obtenir les détails du parent et vice versa. Parfois, les conditions de recherche seront sur le type parent ainsi que sur l'enfant. par exemple rechercher des livres écrits par author1 et taper Fiction.

Comment puis-je l'implémenter dans java? J'ai mentionné la documentation de recherche élastique mais pas en mesure d'obtenir une solution

S'il vous plaît aider

Répondre

6

d'abord votre index avec la cartographie parent/child. Dans le mappage ci-dessous, j'ai également ajouté un champ non-identifié pour categories afin que vous puissiez exécuter des requêtes de filtre sur ce champ. (Pour créer l'index et les documents, j'utilise l'API JSON et non l'API Java car cela ne faisait pas partie de la question.)

POST /test 
{ 
    "mappings": { 
     "book": { 
      "_parent": { 
       "type": "author" 
      }, 
      "properties":{ 
       "category":{ 
        "type":"string", 
        "fields":{ 
         "raw":{ 
          "type":"string", 
          "index": "not_analyzed" 
         } 
        } 
       } 
      } 
     } 
    } 
} 

Créer des documents author:

POST /test/author/1 
{ 
    "name": "jon doe" 
} 


POST /test/author/2 
{ 
    "name": "jane smith" 
} 

Créer des documents book, en précisant la relation entre book et author dans la demande.

POST /test/book/12?parent=1 
{ 
    "name": "fictional book", 
    "category": "Fiction", 
    "publisher": "publisher1" 
} 

POST /test/book/16?parent=2 
{ 
    "name": "book of history", 
    "category": "historical", 
    "publisher": "publisher2" 
} 

POST /test/book/20?parent=2 
{ 
    "name": "second fictional book", 
    "category": "Fiction", 
    "publisher": "publisher2" 
} 

La classe Java ci-dessous: 3 requêtes exécute

  1. Recherche sur tous les books qui ont le terme 'livre' dans le titre et le retour authors.
  2. Rechercher sur tous authors qui ont les termes 'jon doe' dans le nom et renvoient le books.
  3. Rechercher books écrit par 'jane smith' et qui sont de type Fiction.

Vous pouvez exécuter la classe à partir de la ligne de commande ou l'importer dans Eclipse et cliquer avec le bouton droit de la souris sur la classe, puis sélectionner «Exécuter en tant qu'application Java». (Vous aurez besoin d'avoir la bibliothèque ElasticSearch dans le classpath.)

import java.util.concurrent.ExecutionException; 

import org.elasticsearch.action.search.SearchRequestBuilder; 
import org.elasticsearch.action.search.SearchResponse; 
import org.elasticsearch.client.Client; 
import org.elasticsearch.client.transport.TransportClient; 
import org.elasticsearch.common.settings.ImmutableSettings; 
import org.elasticsearch.common.settings.Settings; 
import org.elasticsearch.common.transport.InetSocketTransportAddress; 
import org.elasticsearch.index.query.FilterBuilders; 
import org.elasticsearch.index.query.HasChildQueryBuilder; 
import org.elasticsearch.index.query.HasParentQueryBuilder; 
import org.elasticsearch.index.query.QueryBuilders; 
import org.elasticsearch.index.query.TermFilterBuilder; 

public class ParentChildQueryExample { 

    public static void main(String args[]) throws InterruptedException, ExecutionException { 

    //Set the Transport client which is used to communicate with your ES cluster. It is also possible to set this up using the Client Node. 
    Settings settings = ImmutableSettings.settingsBuilder() 
     .put("cluster.name", "elasticsearch").build(); 
    Client client = new TransportClient(settings) 
     .addTransportAddress(new InetSocketTransportAddress(
     "localhost", 
     9300)); 

    //create the searchRequestBuilder object. 
    SearchRequestBuilder searchRequestBuilder = new SearchRequestBuilder(client).setIndices("test"); 

    //Query 1. Search on all books that have the term 'book' in the title and return the 'authors'. 
    HasChildQueryBuilder bookNameQuery = QueryBuilders.hasChildQuery("book", QueryBuilders.matchQuery("name", "book")); 
    System.out.println("Exectuing Query 1"); 
    SearchResponse searchResponse1 = searchRequestBuilder.setQuery(bookNameQuery).execute().actionGet(); 
    System.out.println("There were " + searchResponse1.getHits().getTotalHits() + " results found for Query 1."); 
    System.out.println(searchResponse1.toString()); 
    System.out.println(); 

    //Query 2. Search on all authors that have the terms 'jon doe' in the name and return the 'books'. 
    HasParentQueryBuilder authorNameQuery = QueryBuilders.hasParentQuery("author", QueryBuilders.matchQuery("name", "jon doe")); 
    System.out.println("Exectuing Query 2"); 
    SearchResponse searchResponse2 = searchRequestBuilder.setQuery(authorNameQuery).execute().actionGet(); 
    System.out.println("There were " + searchResponse2.getHits().getTotalHits() + " results found for Query 2."); 
    System.out.println(searchResponse2.toString()); 
    System.out.println(); 

    //Query 3. Search for books written by 'jane smith' and type Fiction. 
    TermFilterBuilder termFilter = FilterBuilders.termFilter("category.raw", "Fiction"); 
    HasParentQueryBuilder authorNameQuery2 = QueryBuilders.hasParentQuery("author", QueryBuilders.matchQuery("name", "jane smith")); 
    SearchResponse searchResponse3 = searchRequestBuilder.setQuery(QueryBuilders.filteredQuery(authorNameQuery2, termFilter)).execute().actionGet(); 
    System.out.println("There were " + searchResponse3.getHits().getTotalHits() + " results found for Query 3."); 
    System.out.println(searchResponse3.toString()); 
    System.out.println(); 
    } 
} 
+0

Dans la deuxième requête, si l'auteur avait d'autres types de « enfant », il retournerait ceux aussi. – coolscitist

0

Vous pouvez utiliser Parent-Child documents pour cela. Créez un index bookstore avec des mappages simples pour les documents d'auteur et les documents de livre. Vous pouvez ajouter plus de champs selon vos besoins. Voir this pour plus d'informations sur l'indexation des documents parent/enfant.

PUT bookstore 
{ 
    "mappings": { 
     "author": { 
     "properties": { 
      "authorname": { 
       "type": "string" 
      } 
     } 
     }, 
     "book": { 
     "_parent": { 
      "type": "author" 
     }, 
     "properties": { 
      "bookname": { 
       "type": "string" 
      } 
     } 
     } 
    } 
} 

Maintenant, nous allons ajouter deux auteurs:

PUT bookstore/author/1 
{ 
    "authorname": "author1" 
} 

PUT bookstore/author/2 
{ 
    "authorname": "author2" 
} 

Maintenant, nous allons ajouter deux livres de l'auteur author1:

PUT bookstore/book/11?parent=1 
{ 
    "bookname": "book11" 
} 

PUT bookstore/book/12?parent=1 
{ 
    "bookname": "book12" 
} 

Maintenant, nous allons ajouter deux livres de l'auteur author2:

PUT bookstore/book/21?parent=2 
{ 
    "bookname": "book21" 
} 

PUT bookstore/book/22?parent=2 
{ 
    "bookname": "book22" 
} 

Nous avons fini d'indexer les documents. Maintenant, commençons à chercher.

Rechercher tous les livres écrits par l'auteur author1 (En savoir plus sur cette here)

POST bookstore/book/_search 
{ 
    "query": { 
     "has_parent": { 
     "type": "author", 
     "query": { 
      "term": { 
       "authorname": "author1" 
      } 
     } 
     } 
    } 
} 

Rechercher l'auteur du livre book11 (En savoir plus sur cette here)

POST bookstore/author/_search 
{ 
    "query": { 
     "has_child": { 
     "type": "book", 
     "query": { 
      "term": { 
       "bookname": "book11" 
      } 
     } 
     } 
    } 
} 

Rechercher les livres nommés book12 et rédigé par author1. Vous devez utiliser bool queries pour y parvenir. (Il peut y avoir un meilleur exemple pour ce scénario avec d'autres champs dans les documents)

POST bookstore/book/_search 
{ 
    "query": { 
     "bool": { 
     "must": [ 
      { 
       "has_parent": { 
        "type": "author", 
        "query": { 
        "term": { 
         "authorname": "author1" 
        } 
        } 
       } 
      }, 
      { 
       "term": { 
        "bookname": { 
        "value": "book12" 
        } 
       } 
      } 
     ] 
     } 
    } 
} 
0

Je l'ai fait quelque chose de similaire avec la bibliothèque « printemps-données-ElasticSearch ». Il y a des tas d'échantillons disponibles sur leur suite de tests.

Suivez ce lien sur git: https://github.com/spring-projects/spring-data-elasticsearch/blob/master/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java

List<Car> cars = new ArrayList<Car>(); 

    Car saturn = new Car(); 
    saturn.setName("Saturn"); 
    saturn.setModel("SL"); 

    Car subaru = new Car(); 
    subaru.setName("Subaru"); 
    subaru.setModel("Imprezza"); 

    Car ford = new Car(); 
    ford.setName("Ford"); 
    ford.setModel("Focus"); 

    cars.add(saturn); 
    cars.add(subaru); 
    cars.add(ford); 

    Person foo = new Person(); 
    foo.setName("Foo"); 
    foo.setId("1"); 
    foo.setCar(cars); 


    Car car = new Car(); 
    car.setName("Saturn"); 
    car.setModel("Imprezza"); 

    Person bar = new Person(); 
    bar.setId("2"); 
    bar.setName("Bar"); 
    bar.setCar(Arrays.asList(car)); 

    List<IndexQuery> indexQueries = new ArrayList<IndexQuery>(); 
    IndexQuery indexQuery1 = new IndexQuery(); 
    indexQuery1.setId(foo.getId()); 
    indexQuery1.setObject(foo); 

    IndexQuery indexQuery2 = new IndexQuery(); 
    indexQuery2.setId(bar.getId()); 
    indexQuery2.setObject(bar); 

    indexQueries.add(indexQuery1); 
    indexQueries.add(indexQuery2); 

    elasticsearchTemplate.putMapping(Person.class); 
    elasticsearchTemplate.bulkIndex(indexQueries); 
    elasticsearchTemplate.refresh(Person.class, true); 

    SearchQuery searchQuery = new NativeSearchQueryBuilder().build(); 
    List<Person> persons = elasticsearchTemplate.queryForList(searchQuery, Person.class);