Hibernate Search Faceting
Tech-Today

Hibernate Search Faceting


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 :-)




- Hibernate - Get Classes That Referenced A Given Entity
There are times when we want to list the entities that referenced (via foreign keys) a given entity x. For example, when deleting entity x that is being referenced, it will throw a generic ConstraintViolationException. Oftentimes, we need to display this...

- How To Implement A Lazydatamodel With Size In Primefaces
This solution is ideal if you have a list of entities or a named queries that return a list of entities. For example let's say we have an entity user and we want to return all the users with role=x. @NamedQueries({ @NamedQuery(name = "User.listUsersByRoles",...

- How To Create A Custom Bean Validation In Javaee6
Bean validation has been mentioned on many articles online but I found few that explain the actual class that implements the constraint validator. For example: the bean validation article from  oracle javaee6 documentation: http://docs.oracle.com/javaee/6/tutorial/doc/gkfgx.html....

- Creating Your First Ejb3 Project In Eclipse On Jboss Server
This tutorial will teach you on how to setup and run an ejb application. What you need (noted are where I installed my versions): 1.) Jboss 5 (jboss-5.1.0.GA) 2.) eclipse-jee 3.) ojdbc14 (C:\jboss-5.1.0.GA\server\default\lib) Steps: 1.) Create a new EJB...

- How To Get Started With Hibernate In Java. Create A Simple Class And Database Schema For Demostration.
Since, I've always been using different database sometimes I get confused how to implement the others. Like hibernate, where the configuration must be properly set. *This help assumes that you have already created a java project in eclipse that has...



Tech-Today








.