Add Constraints to a Query using the Fluent Search API
Introduction
Goal
Add constraints to a search query using the Fluent Search API.
Background
The Fluent Search API in Hippo's delivery tier (HST) provides an intuitive way to construct search queries. This page explains how to add constraints to a query.
Add Constraints using HstQueryBuilder
There are cases where you need to apply a constraint to a search query that is not available in the query builder bootstrapping. For example, when querying for the latest 10 news documents that contain some word in the entire document, or some word in the value of a property such as "example:title", you need to apply a constraint to the query.
String query = .... HippoBean scope = RequestContextProvider.get() .getSiteContentBaseBean() .getBean(relativePathToFolderX); final HstQuery hstQuery = HstQueryBuilder.create(scope) .ofTypes(NewsDocument.class) // create and set a constraint, // meaning to do full text search by query in the documents. .where(constraint(".").contains(query)) .limit(10) .orderByDescending("example:date") .build(); HstQueryResult result = hstQuery.execute();
In the example above, hstQuery.execute() will return documents that match the free text search query.
The repository indexes all text in a document, including all of its properties and all the properties of all descendant nodes. To search in all text in a document, specify a relative XPath "." like in the following line from the example above:
.where(constraint(".").contains(query))
You can also search in just a single property, for example:
Search for documents the title of which matches the query string:
// SNIP // only return hits that match the query in the title .where(constraint("example:title").contains(query)) // SNIP
Or in multiple properties, for example:
Search for documents that match query in title AND in summary:
// SNIP // only return hits that match the query in the title AND in the summary .where( and( constraint("example:title").contains(query), constraint("example:summary").contains(query) ) ) // SNIP
The two constraints are combined using a logical AND. The code snippet above therefore only returns hits for documents that match the query in the property "example:title" AND the property "example:summary".
Similarly, you can combine constraints using the logical OR as well like the following example:
Search for documents that match query in title OR in summary:
// SNIP // only return hits that match the query in the title OR in the summary .where( or( constraint("example:title").contains(query), constraint("example:summary").contains(query) ) ) // SNIP
The above example returns hits for documents that match the query in the property example:title OR the property example:summary.
The preceding examples searched in a property of a document. You can also search in a property of a descendant node (i.e. compound type field) of a document:
// SNIP .where(constraint("example:address/example:street").contains(query)) // SNIP
As an alternative, you can also specify the first argument as example:address/@example:street, adding @ to mark example:street as a property. Both versions are equivalent.
In addition to #contains(...), more constraints can be applied. The opposite of #contains(...) is #notContains(). These are the only two constraints that involve free text search. The other filter constraints pertain to equality or comparison to a given value.
import static org.hippoecm.hst.content.beans.query.builder.ConstraintBuilder.constraint; import static org.hippoecm.hst.content.beans.query.builder.ConstraintBuilder.and; import static org.hippoecm.hst.content.beans.query.builder.ConstraintBuilder.or;