Hibernate Search - Query DSL-
Executing a search query
// Not shown: get the entity manager and open a transactionSearchSession searchSession = Search.session( entityManager );
SearchResult<Book> result = searchSession.search( Book.class )
.where( f -> f.match()
.field( "title" )
.matching( "robot" ) )
.fetch( 20 );
long totalHitCount = result.getTotalHitCount();
List<Book> hits = result.getHits();
// Not shown: commit the transaction and close the entity manager
Get a Hibernate Search session, called SearchSession, from the EntityManager.
Initiate a search query on the index mapped to the Book entity.
Define that only documents matching the given predicate should be returned. The predicate is created using a factory f passed as an argument to the lambda expression. See Predicate DSL for more information about predicates.
Build the query and fetch the results, limiting to the top 20 hits.
Retrieve the total number of matching entities.
Retrieve matching entities.
By default, the hits of a search query will be entities managed by Hibernate ORM, bound to the entity manager used to create the search session. This provides all the benefits of Hibernate ORM, in particular the ability to navigate the entity graph to retrieve associated entities if necessary.
The query DSL offers many features, detailed in the following sections. Some commonly used features include:
predicates, the main component of a search query, i.e. the condition that every document must satisfy in order to be included in search results.
fetching the results differently: getting the hits directly as a list, using pagination, scrolling, etc.
sorts, to order the hits in various ways: by score, by the value of a field, by distance to a point, etc.
projections, to retrieve hits that are not just managed entities: data can be extracted from the index (field values), or even from both the index and the database.
aggregations, to group hits and compute aggregated metrics for each group — hit count by category, for example.
Targeting multiple entity types
When multiple entity types have similar indexed fields, it is possible to search across these multiple types in a single search query: the search result will contain hits from any of the targeted types.Targeting multiple entity types in a single search query
SearchResult<Person> result = searchSession.search( Arrays.asList(Manager.class, Associate.class
) )
.where( f -> f.match()
.field( "name" )
.matching( "james" ) )
.fetch( 20 );
Initiate a search query targeting the indexes mapped to the Manager and Associate entity types. Since both entity types implement the Person interface, search hits will be instances of Person.
Continue building the query as usual. There are restrictions regarding the fields that can be used: see the note below.
Fetch the search result. Hits will all be instances of Person.
Targeting entity types by name
SearchResult<Person> result = searchSession.search(searchSession.scope(
Person.class,
Arrays.asList( "Manager", "Associate" )
)
)
.where( f -> f.match()
.field( "name" )
.matching( "james" ) )
.fetch( 20 );
Initiate a search query.
Pass a custom scope encompassing the indexes mapped to the Manager and Associate entity types, expecting those entity types to implement the Person interface (Hibernate Search will check that).
Continue building the query as usual.
Fetch the search result. Hits will all be instances of Person.
Fetching results
In Hibernate Search, the default search result is a little bit more complicated than just "a list of hits". This is why the default methods return a composite SearchResult object offering getters to retrieve the part of the result you want, as shown in the example below.
Getting information from a SearchResult
SearchResult<Book> result = searchSession.search( Book.class ).where( f -> f.matchAll() )
.fetch( 20 );
long totalHitCount = result.getTotalHitCount();
List<Book> hits = result.getHits();
// ...
Start building the query as usual.
Fetch the results, limiting to the top 20 hits.
Retrieve the total hit count, i.e. the total number of matching entities/documents, which could be 10,000 even if you only retrieved the top 20 hits. This is useful to give end users and idea of how many more hits they query produced.
Retrieve the top hits, in this case the top 20 matching entities/documents.
Other kinds of results and information can be retrieved from SearchResult. They are explained in dedicated sections, such as Aggregation DSL.
Getting the total hit count directly
long totalHitCount = searchSession.search( Book.class ).where( f -> f.matchAll() )
.fetchTotalHitCount();
The top hits can also be obtained directly, without going through a SearchResult, which can be handy if only the top hits are useful, and not the total hit count:
Getting the top hits directly
List<Book> hits = searchSession.search( Book.class ).where( f -> f.matchAll() )
.fetchHits( 20 );
If only zero to one hit is expected, it is possible to retrieve it as an Optional. An exception will be thrown if more than one hits are returned.
Getting the only hit directly
Optional<Book> hit = searchSession.search( Book.class ).where( f -> f.id().matching( 1 ) )
.fetchSingleHit();
Getting all hits in a SearchResult
SearchResult<Book> result = searchSession.search( Book.class ).where( f -> f.id().matchingAny( Arrays.asList( 1, 2 ) ) )
.fetchAll();
long totalHitCount = result.getTotalHitCount();
List<Book> hits = result.getHits();
Getting all hits directly
List<Book> hits = searchSession.search( Book.class ).where( f -> f.id().matchingAny( Arrays.asList( 1, 2 ) ) )
.fetchAllHits();
Comments
Post a Comment