I am trying to understand queries in general in Hibernate Search. I have some trouble understanding the forEntity(...)
method. This is what the documentation says:
Let's see how to use the API. You first need to create a query builder that is attached to a given indexed entity type. This QueryBuilder will know what analyzer to use and what field bridge to apply. You can create several QueryBuilders (one for each entity type involved in the root of your query). You get the QueryBuilder from the SearchFactory.
From section: 5.1.2. Building a Lucene query with the Hibernate Search query DSL
QueryBuilder mythQB = searchFactory.buildQueryBuilder().forEntity( Myth.class ).get();
From above you see that you have to name an entity. What are you supposed to to when you want to create an own querybuilder for creating a boolean query inside the "root" query? What should you bind that too?
Let say I want to have a boolean query that should match either "Apples" or "Pie". That is two different entity, so currently I have two different querybuilders for them. But I need a third one to create a boolean query. Should this be bound to Object
class?
If you want to be able to return multiple entities from a single query, you can use the QueryBuilder
as you stated, but you'll want to specify multiple entities in the createFullTextQuery
invocation. For example, if you have a Book
entity and a Movie
entity, and you want to find all books and movies whose titles start with d
, you could use the following query:
QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Book.class).get();
Query query = queryBuilder.keyword().wildcard().onField("title").matching("d*").createQuery();
org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery(query, Book.class, Movie.class);
Notice that the query builder is created with just the Book
entity, but both Book
s and Movie
s are specified in the createFullTextQuery
invocation.
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.
Collection<String> namesCollection = getNames(); // Contains "billy" and "bob", for example
StringBuilder names = new StringBuilder(100);
for(String name : namesCollection) {
names.append(name).append(" "); // Never mind the space at the end of the resulting string.
}
QueryBuilder b = fts.getSearchFactory().buildQueryBuilder().forEntity(Person.class).get();
Query luceneQuery = b.bool()
.should(
// Searches for multiple possible values in the same field
b.keyword().onField("firstName").matching( sb.toString() ).createQuery()
)
.must(b.keyword().onField("lastName").matching("thornton").createQuery())
.createQuery();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With