Chapter 5. Querying
- Creating a
FullTextSession
- Creating a Lucene query
- Wrapping the Lucene query using a
org.hibernate.Query
- Executing the search by calling for example
list()
orscroll()
FullTextSession
. This Search specific session wraps a regular org.hibernate.Session
to provide query and indexing capabilities.
Example 5.1. Creating a FullTextSession
Session session = sessionFactory.openSession(); ... FullTextSession fullTextSession = Search.getFullTextSession(session);
Example 5.2. Creating a Lucene query
org.apache.lucene.queryParser.QueryParser parser =
new QueryParser("title", new StopAnalyzer() );
org.apache.lucene.search.Query luceneQuery = parser.parse( "summary:Festina Or brand:Seiko" );
org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );
List result = fullTextQuery.list(); //return a list of managed objects
org.hibernate.Query
, which means you are in the same paradigm as the other Hibernate query facilities (HQL, Native or Criteria). The regular list()
, uniqueResult()
, iterate()
and scroll()
methods can be used.
Example 5.3. Creating a Search query using the JPA API
EntityManager em = entityManagerFactory.createEntityManager();
FullTextEntityManager fullTextEntityManager =
org.hibernate.hibernate.search.jpa.Search.getFullTextEntityManager(em);
...
org.apache.lucene.queryParser.QueryParser parser =
new QueryParser("title", new StopAnalyzer() );
org.apache.lucene.search.Query luceneQuery = parser.parse( "summary:Festina Or brand:Seiko" );
javax.persistence.Query fullTextQuery = fullTextEntityManager.createFullTextQuery( luceneQuery );
List result = fullTextQuery.getResultList(); //return a list of managed objects
FullTextQuery
is retrieved.
5.1. Building queries
org.hibernate.Query
as your primary query manipulation API.
5.1.1. Building a Lucene query
5.1.2. Building a Hibernate Search query
5.1.2.1. Generality
Example 5.4. Wrapping a Lucene query into a Hibernate Query
FullTextSession fullTextSession = Search.getFullTextSession( session ); org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );
Example 5.5. Filtering the search result by entity type
org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Customer.class ); // or fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Item.class, Actor.class );
Customer
s, the second returns matching Actor
s and Item
s. The type restriction is fully polymorphic which means that if there are two indexed subclasses Salesman
and Customer
of the baseclass Person
, it is possible to just specify Person.class
in order to filter on result types.
5.1.2.2. Pagination
Example 5.6. Defining pagination for a search query
org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Customer.class ); fullTextQuery.setFirstResult(15); //start from the 15th element fullTextQuery.setMaxResults(10); //return 10 elements
Note
fulltextQuery.
getResultSize()
5.1.2.3. Sorting
Example 5.7. Specifying a Lucene Sort
in order to sort the results
org.hibernate.search.FullTextQuery query = s.createFullTextQuery( query, Book.class );
org.apache.lucene.search.Sort sort = new Sort(new SortField("title"));
query.setSort(sort);
List results = query.list();
FullTextQuery
interface which is a sub interface of org.hibernate.Query
. Be aware that fields used for sorting must not be tokenized.
5.1.2.4. Fetching strategy
Example 5.8. Specifying FetchMode
on a query
Criteria criteria = s.createCriteria( Book.class ).setFetchMode( "authors", FetchMode.JOIN ); s.createFullTextQuery( luceneQuery ).setCriteriaQuery( criteria );
setCriteriaQuery
if more than one entity type is expected to be returned.
5.1.2.5. Projection
Example 5.9. Using projection instead of returning the full domain object
org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
query.setProjection( "id", "summary", "body", "mainAuthor.name" );
List results = query.list();
Object[] firstResult = (Object[]) results.get(0);
Integer id = (Integer) firstResult[0];
String summary = (String) firstResult[1];
String body = (String) firstResult[2];
String authorName = (String) firstResult[3];
Object[]
. Projections avoid a potential database round trip (useful if the query response time is critical), but has some constraints:
- the properties projected must be stored in the index (
@Field(store=Store.YES)
), which increase the index size - the properties projected must use a
FieldBridge
implementingorg.hibernate.search.bridge.TwoWayFieldBridge
ororg.hibernate.search.bridge.TwoWayStringBridge
, the latter being the simpler version. All Hibernate Search built-in types are two-way. - you can only project simple properties of the indexed entity or its embedded associations. This means you cannot project a whole embedded entity.
- projection does not work on collections or maps which are indexed via
@IndexedEmbedded
Example 5.10. Using projection in order to retrieve meta data
org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
query.setProjection( FullTextQuery.SCORE, FullTextQuery.THIS, "mainAuthor.name" );
List results = query.list();
Object[] firstResult = (Object[]) results.get(0);
float score = (Float) firstResult[0];
Book book = (Book) firstResult[1];
String authorName = (String) firstResult[2];
- FullTextQuery.THIS: returns the initialized and managed entity (as a non projected query would have done).
- FullTextQuery.DOCUMENT: returns the Lucene Document related to the object projected.
- FullTextQuery.OBJECT_CLASS: returns the class of the indexed entity.
- FullTextQuery.SCORE: returns the document score in the query. Scores are handy to compare one result against an other for a given query but are useless when comparing the result of different queries.
- FullTextQuery.ID: the id property value of the projected object.
- FullTextQuery.DOCUMENT_ID: the Lucene document id. Careful, Lucene document id can change overtime between two different IndexReader opening (this feature is experimental).
- FullTextQuery.EXPLANATION: returns the Lucene Explanation object for the matching object/document in the given query. Do not use if you retrieve a lot of data. Running explanation typically is as costly as running the whole Lucene query per matching element. Make sure you use projection!