Parent/Child relationships in spring-data-elastic-search

stanislav.chetvertkov picture stanislav.chetvertkov · May 19, 2014 · Viewed 10k times · Source

I'm using Spring-Data-Elastic-Search for searching/caching purposes. I need to execute a query which uses child(TermCache) and parent(ConceptCache) properties and return instances of child objects(this means i can't use nested objects).

i have the following structure:

@Document(indexName = "termweb" , type = "term")
public class TermCache {

  @Id
  private String id;
  private String name;
  private LanguageDTO language;
  private String status;
  private String definition;

  @Field(type = FieldType.String, store = true)
  @Parent(type = "concept")
  private Long conceptId;

  private String displayId;
  private Map<Long, String> fields = new HashMap<>();
  //todo think about storing it as a collection of nested objects

}


@Document( indexName = "termweb" , type = "concept")
public class ConceptCache implements ConceptDTO{

 @Id
 private String id;

 private String displayId;
 private Long dictionaryId;
 private String dictionaryName;

 private Map<Long, String> fields = new HashMap<>();
}

I need a hint on how to handle this type of tasks; should i use two separate queries or should i somehow fetch properties of a parent or maybe something else?

Answer

Mohsin Husen picture Mohsin Husen · May 28, 2014

Agreed, We are lacking on documentation which we will be improving with upcoming release.

If you have any question about spring data elasticsearch stackoverflow probably is not best way to get answer(as we wont be notified for new thread), we have separate google group for question/queries https://groups.google.com/forum/#!forum/spring-data-elasticsearch-devs

Without having any idea about what exactly you are trying to achieve with above entities, i can give you an example of sample parent child entities as below

@Document(indexName = "parent-child", type = "parent-entity")
public class ParentEntity {

   @Id
   private String id;

   @Field(type = FieldType.String, index = FieldIndex.analyzed, store = true)
   private String name;
   // setter/getter

   public ParentEntity() {
   }

   public ParentEntity(String id, String name) {
      this.id = id;
      this.name = name;
   }
}


@Document(indexName = "parent-child", type = "child-entity")
public class ChildEntity {

   @Id
   private String id;

   @Field(type = FieldType.String, store = true)
   @Parent(type = "parent-entity")
   private String parentId;

   @Field(type = FieldType.String, index = FieldIndex.analyzed, store = true)
   private String name;

   public ChildEntity() {
   }

   public ChildEntity(String id, String parentId, String name) {
      this.id = id;
      this.parentId = parentId;
      this.name = name;
   }
}

// indexing parent (you can use many other ways to index that includes using repositories)

   ParentEntity parent1 = new ParentEntity("parent1", "First Parent");
   IndexQuery parentIndex1 = new IndexQuery();
   parentIndex1.setId(parent1.getId());
   parentIndex1.setObject(parent1);
   elasticsearchTemplate.index(parentIndex1);

   ParentEntity parent2 = new ParentEntity("parent2", "Second Parent");
   IndexQuery parentIndex2 = new IndexQuery();
   parentIndex2.setId(parent2.getId());
   parentIndex2.setObject(parent2);
   elasticsearchTemplate.index(parentIndex2);

// indexing child

   ChildEntity child1 = new ChildEntity("child1", parent1.getId(), "First");
   IndexQuery childIndex1 = new IndexQuery();
   childIndex1.setId(child1.getId());
   childIndex1.setObject(child1);
   childIndex1.setParentId(child1.getParentId());
   elasticsearchTemplate.index(childIndex1);

   ChildEntity child2 = new ChildEntity("child2", parent1.getId(), "Second");
   IndexQuery childIndex2 = new IndexQuery();
   childIndex2.setId(child2.getId());
   childIndex2.setObject(child2);
   childIndex2.setParentId(child2.getParentId());
   elasticsearchTemplate.index(childIndex2);

// searching

there are several available option while searching on Parent/Child entities, that includes has children, has parent and top children queries.

   QueryBuilder query = topChildrenQuery("child-entity", QueryBuilders.termQuery("name", child1name.toLowerCase()));
   SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).build();

   List<ParentEntity> parents = elasticsearchTemplate.queryForList(searchQuery, ParentEntity.class);

Hope this small example will give you basic understanding how to use parent child. have a look at ParentChildTests for more.

If you still have more question please feel free to contact us.