Bootstrap a Query Using the Fluent Search API

Info: Available since brXM 11.1.0.

Overview

This page describes how to initialize a search query using the Fluent Query API in the delivery tier of Bloomreach Content.

When to Use

Use the Fluent Search API when you need to construct and execute search queries in the delivery tier (HST) of Bloomreach Content, either within HST components or JAX-RS service resources.

Prerequisites

  • brXM 11.1.0 or later
  • Familiarity with HST components or JAX-RS resources
  • Access to the delivery tier codebase

Implementation

Create an HstQuery Using HstQueryBuilder

You can create an HstQuery instance from the current request context using HstQueryBuilder. This approach works in both HST components and JAX-RS Service Resources.

In an HST Component

public class LatestItems extends BaseComponent { @Override public void doBeforeRender(HstRequest request, HstResponse response) { final HippoBean scope = RequestContextProvider.get().getSiteContentBaseBean(); final HstQuery hstQuery = HstQueryBuilder.create(scope) .ofTypes(BaseDocument.class) .build(); // ... } }

In a JAX-RS Service Resource

ProductPlainResource extending AbstractResource:

@Path("/products/") public class ProductPlainResource extends AbstractResource { @GET @Path("/{productType}/") public List<ProductRepresentation> getProductResources(....) { final HippoBean scope = RequestContextProvider.get().getSiteContentBaseBean(); final HstQuery hstQuery = HstQueryBuilder.create(scope) .ofTypes(BaseDocument.class) .build(); // ... } }

Without a HstRequestContext

If you do not have a HstRequestContext (for example, in background processes or external integrations), use the HstQueryManager to build an HstQuery. Call HstQueryBuilder#build(HstQueryManager):

Repository repo = HstServices.getComponentManager().getComponent(Repository.class.getName()); Credentials creds = HstServices.getComponentManager().getComponent(Credentials.class.getName() + ".default"); ContentBeansTool cbt = HstServices.getComponentManager().getComponent(ContentBeansTool.class.getName()); Session session = null; try { session = repo.login(creds); HstQueryManager queryManager = cbt.createQueryManager(session); final Node scope = JcrUtils.getNodeIfExists("/content/documents/myproject", session); final HstQuery hstQuery = HstQueryBuilder.create(scope) .ofTypes("myproject:news") .build(queryManager); // ... } finally { if (session != null) session.logout(); }

Define Query Scope with HstQueryBuilder

An HstQuery searches content within one or more scopes. Set scopes using HstQueryBuilder#create(HippoBean ... scopeBeans) or HstQueryBuilder#create(Node ... scopeNodes). Both methods accept one or more arguments.

Example: Multiple Scopes with HippoBeans

final HippoBean base = RequestContextProvider.get().getSiteContentBaseBean(); final HippoBean newsFolder = base.getBean("news"); final HippoBean eventsFolder = base.getBean("events"); // Search within both news/ and events/ folders. final HstQuery hstQuery = HstQueryBuilder.create(newsFolder, eventsFolder) .ofTypes(BaseDocument.class) .build();

Example: Multiple Scopes with JCR Nodes

final Session session = RequestContextProvider.get().getSession(); final Node newsFolderNode = JcrUtils.getNodeIfExists("/content/documents/myproject/news", session); final Node eventsFolderNode = JcrUtils.getNodeIfExists("/content/documents/myproject/events", session); // Search within both news/ and events/ folders. final HstQuery hstQuery = HstQueryBuilder.create(newsFolderNode, eventsFolderNode) .ofTypes(BaseDocument.class) .build();

Important:
HstQueryBuilder#create(...) requires at least one non-null argument. If all arguments are null, a RuntimeQueryException is thrown.

Exclude Scopes

You can exclude specific scopes using HstQueryBuilder#excludeScopes(HippoBean ... excludeScopeBeans) or HstQueryBuilder#excludeScopes(Node ... excludeScopeNodes). Both methods accept one or more arguments.

Example: Exclude a HippoBean Scope
final HippoBean base = RequestContextProvider.get().getSiteContentBaseBean(); final HippoBean eventsFolder = base.getBean("events"); // Search base, but exclude events/ folder. final HstQuery hstQuery = HstQueryBuilder.create(base) .excludeScopes(eventsFolder) .ofTypes(BaseDocument.class) .build();
Example: Exclude a Node Scope
final Session session = RequestContextProvider.get().getSession(); final Node baseNode = JcrUtils.getNodeIfExists("/content/documents/myproject", session); final Node eventsFolderNode = JcrUtils.getNodeIfExists("/content/documents/myproject/events", session); // Search base, but exclude events/ folder. final HstQuery hstQuery = HstQueryBuilder.create(baseNode) .excludeScopes(eventsFolderNode) .ofTypes(BaseDocument.class) .build();

Note:
If a bean or node is present in both the scopes (via #create(...)) and in the exclusions (via #excludeScopes(...)), the exclusion takes precedence. All excluded scopes are omitted from the search.

Set Limit and Offset

Always set a limit for your query. If you do not specify a limit, HST defaults to 1000 results, which may impact performance. Set the limit to the number of items you want to retrieve (for example, pageSize). Use an offset to implement pagination.

Example: Pagination

If pageSize = 10 and you want to display the third page (pageIndex = 3):

final HippoBean base = RequestContextProvider.get().getSiteContentBaseBean(); final HstQuery hstQuery = HstQueryBuilder.create(base) .ofTypes(BaseDocument.class) .limit(pageSize) .offset(pageSize * (pageIndex - 1)) .build();

To determine the total number of results (for example, to calculate the number of pages), use HstQueryResult#getTotalSize(). The getSize() method returns the number of results in the current page (up to the limit).

Recommendation:
Always set a limit to the number of items you need. Avoid relying on the default limit for performance reasons.

Sort Results

You can sort query results by one or more properties, in ascending or descending order. Sorting is performed in the order the properties are added. Only properties stored directly on the document can be used for sorting. Properties within Compounds cannot be used for sorting.

Example: Multi-level Sorting

final HippoBean scope = RequestContextProvider.get().getSiteContentBaseBean(); final HstQuery hstQuery = HstQueryBuilder.create(scope) .ofTypes(BaseDocument.class) // Sort by "example:date" descending (newest first) .orderByDescending("example:date") // Then by "example:title" ascending, case insensitive .orderByAscendingCaseInsensitive("example:title") // Then by "hippostdpubwf:publicationDate" descending .orderByDescending("hippostdpubwf:publicationDate") .build(); // ...

The following methods accept one or more field names (varargs):

  • orderByDescending(String... fieldNames)
  • orderByDescendingCaseInsensitive(String... fieldNames)
  • orderByAscending(String... fieldNames)
  • orderByAscendingCaseInsensitive(String... fieldNames)

Passing multiple field names to one of these methods is equivalent to calling the method multiple times with each field name.

Limitation:
You can only sort on properties that are stored directly on the document. For details, see Sorting search results in a query can only be done on direct properties of Documents.

Verification

  • Confirm that queries return the expected results for the defined scopes, limits, offsets, and sorting.
  • Use HstQueryResult#getTotalSize() to verify total result count for pagination.
Share Feedback
Page: /build/search/fluent-search-api/fluent-hstquerybuilder-bootstrapping
Section: Build
Category *
Bootstrap a Query using the Fluent Search API | Bloomreach Content Documentation