The first beta of Hibernate Search 3.3 is out. We had several goals in mind.
One of them is to morph the project into a more independent piece of software for Infinispan. We have a lot of exciting developments around Infinispan, search and persistence. But that's the subject of another post. On to the meat now.
Probably the most visible feature is the new Hibernate Search query DSL.
Writing Lucene queries is not easy, either you use the query parser limiting yourself to fairly simple queries and manipulating strings or you use the Lucene programmatic query API which is quite verbose and contains a myriad of settings and alternatives.
On top of that, you need to make sure you apply the same magic at query and indexing time: if you don't the index key you look for will not match and you will return no result. This is particularly true in an object world where two transformations occur:
- the object is transformed in a string via the Hibernate Search FieldBridge
- the string is transformed into terms via the analyzer
Each property can have different combinations of field bridge and analyzer.
Hibernate Search solves these problems by transparently applying the appropriate FieldBridge and analyzer of a given researched property. It's also built around a fluent API to make queries very easy to write and more importantly easier to read.
QueryBuilder mythQB = searchFactory.buildQueryBuilder().forEntity( Myth.class ).get(); //look for popular modern myths that are not urban Date twentiethCentury = ...; Query luceneQuery = mythQB .bool() .must( mythQB.keyword().onField("description_stem").matching("urban").createQuery() ) .not() .must( mythQB .range() .onField("starred") .from(3).excludeLimit() .to(5) .createQuery() ) .must( mythQB .range() .onField("creationDate") .above(twentiethCentury) .createQuery() ) .createQuery();
This example shows many things:
- the fluent API in action (you've got to admit that it's more readable than a raw Lucene query)
- you pass objects and not string representations (Date and number in this case)
- description_stem uses a stemming analyzer (eg. transforming loving in its root word love): no need to apply it yourself before passing the matching string, the query DSL does that for you.
I will blog in more details about Hibernate Seach query DSL shortly.
This release is compatible with Hibernate Core 3.6 (in Beta3 at the time of writing). A side effect is that manual configuration of the event listeners is no longer necessary even when only using hbm.xml files.
Hardy has been busy designing a statistics API (available from the SearchFactory). It gives you a lot of information about Hibernate Search:
- average and max time for a Lucene query execution
- average and max time for the object loading process following a Lucene query execution
- slowest query
- number of entities indexed of a given type
- and many more
Again, a more detailed blog post should come soon.
We have added integration tests for both Spring Framework and JTA. On the JTA side, we are testing against Bitronix and JBoss Transactions standalone.
While not a public feature yet, Hibernate Search now has the ability to add new entity types on the fly.
From the ground up, we have made sure that Hibernate Search is extremely fast and efficient at runtime. To achieve that we have been using an immutable design for the SearchFactory: we pre-compute and store metadata to make indexing and querying efficient. and that forced us to know the list of indexed entity types ahead of time.
Infinispan, however, does not know necessarily knows the list of entities ahead of time. The new design uses a copy-on-change approach to keep the benefits of the immutable model while offering the ability to add new entities. As a user, you won't notice it but as a framework using Hibernate Search, you will :)
Of course we also fix bugs :)
Check out the new release on JBoss.org's Maven repository or download the distribution. You can also read the documentation here. Be aware that this version breaks a couple of SPIs, make sure to check the migration guide.