Building a Search UI

November 14, 2023

 

Augmented Search being a GraphQL API at its core, it can be used by any front-end technology (and even backend-end ones, see the Java service page).

Jahia does not provide front-end production ready search components, but rather lets customers develop their own components, in the technology of their choice, to better fit their project. It is then mandatory to understand how the GraphQL API works to search and retrieve content in order to build a search UI.

We have two examples:

  • A taglib, to build your search UI inside JSPs
  • Augmented Search UI: a react library, to build a modern search UI

We do recommend using the react library, as it is more modern and more powerful.

In any case, we suggest you fork the corresponding repositories, and then adapt the code to your needs.

Taglib example

The taglib example can be retrieved is available in the augmented-search-taglib github repo. You can find out more about this library in the Java service documentation page

Augmented Search UI

The augmented-search-ui module is an easy and quick way to get a search interface up and running on a Jahia site.

It is meant to be forked, and adapted to meet custom needs.

This module uses some of the reusable react components provided by Elasticsearch in their search-ui library. Please note that search-ui-jahia-connector is the interface between the Augmented Search GraphQL API and the react Search UI components.

Using Function Score with Augmented Search UI

Function Score can be used with Augmented Search UI. To do so

  1. You will need to provide the function to use in the src/javascript/app/App.jsx file:
    ...
    function configureConnector(dxContext) {
        let connector = new JahiaSearchAPIConnector({
            apiToken: 'none',
            baseURL: dxContext.baseURL + dxContext.ctx,
            siteKey: dxContext.siteKey,
            language: dxContext.language,
            workspace: dxContext.workspace === 'default' ? 'EDIT' : 'LIVE',
            functionScore: dxContext.functionScore
        });
        return {
    ...
  2.  Then you need to specify which function to use in the src/main/resources/sui_augmentedSearch/html/augmentedSearch.jsp view file:
    ...
    <script>
        (function () {
            var context = {
                ctx: "${url.context}",
                language: "${currentResource.locale}",
                uiLanguage: "${renderContext.UILocale.language}",
                siteUUID: "${renderContext.site.identifier}",
                siteName: "${renderContext.site.name}",
                siteKey: "${renderContext.site.siteKey}",
                workspace: "${renderContext.workspace}",
                baseURL: window.location.protocol + '//' + window.location.host,
                functionScore: "MyFunctionScoreID"
            };
            window.augmentedSearchUIApp("${appId}", context);
        })();
    </script>
    ...
  3.  You can also go further, and make the function score configurable, by updating the definition and adding such property:
    [sui:augmentedSearch] > jnt:content, jmix:queryContent
     - functionScore (string)

    And then, simply use this property in the previous view:

    functionScore: "${currentNode.properties['functionScore'].string}"

    You will then simply have to fill this property in the Augmented Search component.

    To go further, you can implement a choice list initializer that would provide a list of the functions you want to use in the UI search component

Styling

How can I customize the styling of the Augmented Search UI? 

You can customize the Augmented Search UI module by applying CSS from another template that defines the styling that you want to use. We recommend forking the Augmented Search UI module to adapt it to your requirements (from a styling and functional point of view).

Instant Search

How can avoid many API calls while visitors are typing their search criteria?

In the Augmented Search UI module and in the SearchView.jsx file, modify the value for the debounceLength parameter in the SearchBox component. This parameter defined the number of miliseconds to wait after the last keystroke before submitting the query. If another keystroke occurs during that time, only the lastest query is submitted.

<SearchBox
   searchAsYouType
   debounceLength={100}
/>

See search-ui SearchBox documentation for more information on the SearchBox component and parameters.

How can I deactivate instant search?

Just remove searchAsYouType from the SearchBox component in the SearchView.jsx file.

<SearchBox/>

See search-ui SearchBox documentation for more information on the SearchBox component and parameters.

Facets

Can I use hierarchical facets with categories?

Yes, this feature was introduced in Augmented Search 3.0. Please note that the current UI implementation fetches the entire tree at once. This works well for small datasets but is not recommended if the tree is expected to be large or deep.

Are facets conjunctive or disjunctive?

Facets are disjunctive by default. Note that disjunctive facets enable users to select one or more facets to filter search results and conjunctive facets allow users to select only one.

Can I index custom properties of type categories?

Yes, this feature was introduced in Augmented Search 3.0

Can I display more than 5 elements in a facet?

Augmented Searches uses Elastic's search-ui react components for displaying content, all of which are detailed in search-ui repository.

Displaying more than 5 elements is done through the "show" parameter.

Using this file as an example: src/javascript/app/SearchView/SearchView.jsx

  <facet 
    field="jcr:categories.keyword" 
    label="Categories" 
    show={10} 
  />

This will display up to 10 elements.

Search box

Can I use quotes to search for exact matches (for example, “my exact search”)?

No, using quotes to get an exact match is not supported by Augmented Search. However, if a search result matches the exact order of the searched words, it will be boosted automatically. 

Can I use boolean operators in the search box, for example AND, OR, or NOT?

No, boolean operators are not supported by Augmented Search.

Is autocomplete supported on terms that are most searched?

No, autocomplete is usually performed on terms that are the most relevant, rather than terms that are most used. 

Conditional facets

Conditional facets are facets that display when other facets are selected. For example, you can display a "city facet" when countries are selected in a "country facet". You can use conditional facets to create complex hierarchies and dependencies of facets.

A conditional facet is a JavaScript object where key is name of the facet field (for example jcr:lastModifiedBy) that you want to display based on a condition. value is a function that accepts the filters object as a parameter and returns true to display the facet or false not to display the facet. In the example below, the author facet (lastModifiedBy) only displays to a user when they filter by lastModified date.


conditionalFacets: {
    'jcr:lastModifiedBy': filters => filters.filters.some(filter => filter.field === 'jcr:lastModified')
}

Note: The key for a conditional facet object must exactly match the key of the facets objects.