Using Search in UI

Visual Components

The Search add-on provides two UI components: SearchField and FullTextFilter.

Search Strategies

A search strategy defines how the search term is processed. Basically, it configures a search request with a query.

The SearchField and FullTextFilter components support the following built-in search strategies:

  • startsWith

    This strategy is only available when @ExtendedSearch is enabled on at least one index definition.

    Performs prefix-based search using pre-indexed Edge N-Gram subfields:

  • phrase

    Performs exact phrase matching:

    • Documents must contain all search terms in the exact order within a single field.

    • Equivalent to a traditional phrase query in search engines.

    • Ideal for name, title, or exact wording searches.

  • anyTermAnyField

    Performs disjunctive term matching across all fields:

    • Documents matching any of the input terms in any indexed field are returned.

    • Terms are combined with OR logic.

    • Default strategy for backward compatibility.

    This strategy is set by default.

allTermsAnyField and allTermsSingleField are deprecated and hidden from UI but can be reimplemented if needed.

You can set the proper strategy by using the searchStrategy attribute, for example:

<search:fullTextFilter dataLoader="ordersDl"
                       autoApply="true"
                       searchStrategy="anyTermAnyField"/>

To override the default strategy, add the following property to your application.properties file:

jmix.search.default-search-strategy = phrase

Custom Search Strategies

Additionally, you can create a custom search strategy. Create a Spring bean that extends one of the platform-specific base classes:

  • AbstractOpenSearchStrategy - if you use OpenSearch.

  • AbstractElasticSearchStrategy - if you use Elasticsearch.

Implement getName() and configureRequest(SearchRequestContext):

@Component
public class CustomOpenSearchSearchStrategy extends AbstractOpenSearchStrategy {

    public CustomOpenSearchSearchStrategy(OpenSearchQueryConfigurer queryConfigurer) {
        super(queryConfigurer); (1)
    }

    @Override
    public String getName() {
        return "CustomStrategy"; (2)
    }

    @Override
    public void configureRequest(SearchRequestContext<SearchRequest.Builder> requestContext) { (3)
        queryConfigurer.configureRequest( (4)
                requestContext,
                (queryBuilder, scope) -> (5)
                        queryBuilder.multiMatch(multiMatchQueryBuilder ->
                                multiMatchQueryBuilder
                                        .fields(scope.getFieldList()) (6)
                                        .query(requestContext.getSearchContext().getEscapedSearchText())
                                        .operator(Operator.Or)
                        )
        );
    }
}
1 The base class is initialized with the platform-specific query configurer (OpenSearchQueryConfigurer or ElasticSearchQueryConfigurer), available as the queryConfigurer field.
2 getName() returns a unique strategy name used to select the strategy.
3 configureRequest(SearchRequestContext) is the method the search engine invokes for the strategy — implement it to build the search request.
4 Build the query through queryConfigurer.configureRequest(). The configurer resolves the search scope - the target indexes and the fields the current user is permitted to read - and applies security policies.
5 The lambda receives the platform-specific query builder and the resolved IndexSearchRequestScope.
6 Use scope.getFieldList() to search only the permitted fields.

Always build the query through queryConfigurer. If you configure the request builder directly (for example, with fields("*")), the search scope is not resolved and attribute policies are not applied, which can make the search return no results.

After that, you can assign your custom strategy to the SearchField or FullTextFilter component using the strategy name.

Full-text Search Condition in GenericFilter Component

When the Search add-on is added to the project, a new condition appears in the Add condition dialog of the GenericFilter component:

add condition

Within the Full-text filter condition editor dialog, you can define a caption for the full-text filter and choose a search strategy. If no search strategy is selected, then the default one is used.

condition editor

Subsequently, the records in the list component linked to the filter will undergo filtering based on the outcome of the full-text search.

Using Search API in Views

You can use Search API in view controllers. Let’s look at the example:

@Autowired
private EntitySearcher entitySearcher;

@Autowired
private SearchResultProcessor searchResultProcessor;

@Subscribe(id = "searchBtn", subject = "clickListener") (1)
public void onSearchBtnClick(final ClickEvent<JmixButton> event) {
    SearchContext searchContext = new SearchContext("silver") (2)
            .setSize(20) (3)
            .setEntities("Order_"); (4)
    SearchResult searchResult = entitySearcher.search(searchContext); (5)
    Collection<Object> instances =
            searchResultProcessor.loadEntityInstances(searchResult); (6)
    // ...
}
1 API is called from the view when clicking on a button.
2 Defining the search string is mandatory: here, the query will look through all fields marked for indexing that contain the "silver" string.
3 Adds the conditions for the query: firstly, the max amount of records in the result set. Default value is 10.
4 Next, the list of entities to search within. By default, all indexed entities are included.
5 The EntitySearcher service is used to start searching.
6 SearchResultProcessor is used for fetching entities from the search result.