How do I use boolean operators with Hibernate Search

NobodyMan picture NobodyMan · Apr 19, 2012 · Viewed 8.3k times · Source

I'm learning the Hibernate Search Query DSL, and I'm not sure how to construct queries using boolean arguments such as AND or OR.

For example, let's say that I want to return all person records that have a firstName value of "bill" or "bob".

Following the hibernate docs, one example uses the bool() method w/ two subqueries, such as:

QueryBuilder b = fts.getSearchFactory().buildQueryBuilder().forEntity(Person.class).get();
Query luceneQuery = b.bool()
    .should(b.keyword().onField("firstName").matching("bill").createQuery())
    .should(b.keyword().onField("firstName").matching("bob").createQuery())
    .createQuery();

logger.debug("query 1:{}", luceneQuery.toString());

This ultimately produces the lucene query that I want, but is this the proper way to use boolean logic with hibernate search? Is "should()" the equivalent of "OR" (similarly, does "must()" correspond to "AND")?.

Also, writing a query this way feels cumbersome. For example, what if I had a collection of firstNames to match against? Is this type of query a good match for the DSL in the first place?

Answer

Sanne picture Sanne · Apr 25, 2012

Yes your example is correct. The boolean operators are called should instead of OR because of the names they have in the Lucene API and documentation, and because it is more appropriate: it is not only influencing a boolean decision, but it also affects scoring of the result.

For example if you search for cars "of brand Fiat" OR "blue", the cars branded Fiat AND blue will also be returned and having an higher score than those which are blue but not Fiat.

It might feel cumbersome because it's programmatic and provides many detailed options. A simpler alternative is to use a simple string for your query and use the QueryParser to create the query. Generally the parser is useful to parse user input, the programmatic one is easier to deal with well defined fields; for example if you have the collection you mentioned it's easy to build it in a for loop.