no

How to implement a practical example of Hibernate Search Faceting

With the document available from Hibernate Search (https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#query-facetin...

With the document available from Hibernate Search (https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#query-faceting), we should be able to implement a faceting example that returns the faceting field and its count. In the example from Hibernate Search, our entity is CD, we create a facet on label field, so it will group the CD by label, and count all of each occurrence. But what if we want more info like the artist, sales, etc.

Going back to the previous example from hibernate where we have the following entities (Book, Author, Review). Let's say we want to group the books by author, how should we achieve that?


  1. Annotate Author.id with @facet.
    @Facets({ @Facet, @Facet(name = "id_facet", forField = "id_for_facet", encoding = FacetEncodingType.STRING) })
    @Fields({
    @Field(name = "id_for_facet", analyze = Analyze.NO, bridge = @FieldBridge(impl = org.hibernate.search.bridge.builtin.IntegerBridge.class)) })
    @Id
    @Column(name = "id")
    @GeneratedValue
    private Integer id;
    
  2. Create a class that will hold the desired entity and the facet result.
    public class EntityFacet implements Facet {
     private final Facet delegate;
     private final T entity;
    
     public EntityFacet(Facet delegate, T entity) {
      this.delegate = delegate;
      this.entity = entity;
     }
    
     @Override
     public String getFacetingName() {
      return delegate.getFacetingName();
     }
    
     @Override
     public String getFieldName() {
      return delegate.getFieldName();
     }
    
     @Override
     public String getValue() {
      return delegate.getValue();
     }
    
     @Override
     public int getCount() {
      return delegate.getCount();
     }
    
     @Override
     public Query getFacetQuery() {
      return delegate.getFacetQuery();
     }
    
     public T getEntity() {
      return entity;
     }
    
     @Override
     public String toString() {
      return "EntityFacet [delegate=" + delegate + ", entity=" + entity + "]";
     }
    }
    
  3. Let's query the facet and the entity that contains more of the information we want. In this case the author. Note that we need to add the faceted field in the includePaths property in the @IndexedEmbedded annotation of the main entity (Book), or don't specify a field so all annotated fields are included.
    FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
    QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Book.class).get();
    
    org.apache.lucene.search.Query luceneQuery = qb.all().createQuery();
    FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, Book.class);
    
    // define the facet
    FacetingRequest authorFacet = qb.facet().name("authorIdFacet").onField("authors.id_facet").discrete()
      .orderedBy(FacetSortOrder.COUNT_DESC).includeZeroCounts(false).maxFacetCount(5).createFacetingRequest();
    
    // retrieve facet manager and apply faceting request
    FacetManager facetManager = fullTextQuery.getFacetManager();
    facetManager.enableFaceting(authorFacet);
    
    // retrieve the faceting results
    List<Facet> facets = facetManager.getFacets("authorIdFacet");
    
    // collect all the ids
    List<Integer> vcIds = facets.stream().map(p -> Integer.parseInt(p.getValue())).collect(Collectors.toList());
    // query all the Authors given the id we faceted above, I think multiLoad has
    // been introduced in HS 5.x
    List<Author> authors = fullTextEntityManager.unwrap(Session.class).byMultipleIds(Author.class).multiLoad(vcIds);
    
    // fill our container object with the facet and author entity
    List<EntityFacet<Author>> entityFacets = new ArrayList<>(facets.size());
    for (int i = 0; i < facets.size(); i++) {
     entityFacets.add(new EntityFacet<Author>(facets.get(i), authors.get(i)));
    }
    
    entityFacets.stream().forEach(System.out::println);
For code reference you may check this repository: https://github.com/czetsuya/hibernate-search-demo

Got a question? Don't hesitate to ask :-)

Related

java 2279572274878094611

Post a Comment

item