The Hibernate team is pleased to announce Hibernate Search 3.4 which comes with couple of new features most notably faceting: we are continuing the trend of 3.3 where the focus was on simplifying queries). But the bulk of the work has been around performance optimization, you should see the benefits in your applications especially when the domain model is getting complex.

Oh and for people that don't know, Hibernate Search is a full-text search engine atop Hibernate Core (and Infinispan).


Faceting is a technique that divides the results of a query into multiple categories. Say you search for a car, categories could be:

  • Brand (Renault, Mercedes, Nissan, Ford)
  • Price range (below $5000, $5000 - $10000, $10000 - $20000, ...)

For each, category value, the faceting feature gives you the number of matching elements. You will then know that there are 20 Mercedes and 7 Nissan matching the query. On one side, you have the results of your query (typically at the center of the page) and on the other sde (typically on the left side), you have a list of categories with their repartition amongst the query results. Faceting is really a smart/contextual navigation tool.

Finally, you can drill down, ie select one or several category results to refine the query. It is hard to explain all this in words, but check out (do a query within a department - say in the Digital SLR department - query 'lenses' and you will see Department, Brand, Customer review, Condition facets on the left).

Hibernate Search now provides an API to implement Amazon style faceting for your queries. We make use of a DSL API to express a facet request that you can then attach to a query.

FacetingRequest priceFacetingRequest = qB
    .name( "priceFaceting" )
    .onField( "price" )
      .below( 1000 )
      .from( 1001 ).to( 1500 )
      .above( 1500 ).excludeLimit()

Check out the documentation for more info.

Retrieve entities from the second level cache first

Some people have a data set small enough to keep most of the living data in their second level cache. Up until now, Hibernate Search was favoring a database query. You can now customize how the data is retrieved and in particular force the second level cache:

FullTextQuery query = session.createFullTextQuery(luceneQuery, User.class);
List results = query.getResultList();

Many thanks to the customers that requested this feature, it turned out to be extremely useful in various situations :)

Lucene 3.1

Hibernate Search has been upgraded to the latest version of Lucene. While some APIs have changed in the Lucene area, Hibernate Search shields you for all code-breaking changes. Make sure to check our migration guide though as some Lucene configurations have changed.

Performance improvements

A lot of work has been put in this release on performance improvements. Of course, Lucene 3.1 comes with its lot of enhancements but we have also improved the Hibernate Search engine:

  • Update entities only when indexed properties have changed: if an entity changes in Hibernate Core but none of its indexed properties change, we won't trigger indexing anymore.
  • Mass Indexer now uses multiple threads during the text analysis phase: Mass Index runs as much work in parallel, we have added the actual text analysis phase to the mix.
  • Ability to use FieldCache and trade memory for performance improvement: loads a given field value in memory and avoid the Lucene index lookup later on. Check the reference documentation for more info.
  • Smarter indexing on collection update event: when we know a collection won't involve updating an indexed entity (recursively), we skip the event.

Internals and Infinispan

We have properly isolated Hibernate Search query engine from Hibernate Core. The engine is now reused in Infinispan 5 as part of its Query module. The good news is that Infinispan Query benefits from all the new Hibernate Search features including faceting.

How to try it

There are many more minor features and many bug fixes, be sure to check our changelog for all the details.

Hibernate Search 3.4 is compatible with the latest version of Hibernate Core (3.6.x). Check out the new release on's Maven repository or download the distribution. You can also read the documentation. Make sure to check out the migration guide if case you are migrating your application from a previous Hibernate Search version.

JUDCon and JBoss World

If you are interested in all things JBoss, you must come to JBoss World (May 3rd-May6th 2011 in Boston, MA, USA). Sanne and I will be speaking about Hibernate OGM and how to use JPA and store data on Infinispan. More info a bit later (hint, we use Hibernate Search :)).

If you cannot afford JBoss World (and even if you can), try and come to JUDCon which is the community conference (May 2nd-May3rd 2011 in Boston, MA, USA). Sanne will be speaking about search on Infinispan (hint, he will use Hibernate Search). More info and registration here.

19. Apr 2011, 04:44 CET | Link

just try out, look good !

that is a typo in code, object with s is the right one :)

query.initializeObjectsWith( ...

19. Apr 2011, 08:35 CET | Link

Typo fixed, thank you.

03. May 2011, 10:49 CET | Link

Are enum fields supported (by using the EnumBridge?). The documentation mentions the restrictions on the facet fields (String, Number subclasses or Date). To me, enum fields look like the ideal candidates for dicrete faceting. Also, is it possible to auto-detect ranges? For example, Daisy CMS supports facetted search and can detect ranges by a logarithmic spread. So you could do something like:

FacetingRequest priceFacetingRequest = qB
    .name( "priceFaceting" )
    .onField( "price" )

Which means Hibernate search determines the ranges based on the values of the field. For example you get 100-1000 (5), 1000-1200 (25), 1200-1300 (88), 1300-1900 (26), 1900-3000 (6). With this feature, you can avoid situations in which ranges contains too much items to be usable in a facet. Anyway, congratulations for you and your team on another great release!

Post Comment