Real World Examples

The following code is exactly what is used to power the search at https://boldminded.com/support/search, except for some extra html markup that was remove for demo purposes. It is a good example of text based search with limited filtering options. If the filtering options were more complex I would have considered building the search in a custom React component or use the readily available InstantSearch components that work with Meilisearch or Algolia.

This example uses the URL Helper extension to grab the GET parameters as variables.

<form method="get" action="{site_url}support/search">
    <select name="support-add-on">
        <option></option>
    </select>
    <select name="support-type">
        <option></option>
    </select>
    <input type="text" name="keywords" id="keywords" value="{if url:param:keywords}{url:param:keywords}{/if}" />
</form>
{if url:param:keywords || url:param:support-add-on || url:param:support-type}
    <ul>
        {exp:dexter:search index="{dexter_env}_support" term='"{url:param:keywords}"' entry_ids_only="yes"}
            {search_filters}
                {
                    "limit": 50,
                    "sort": [
                        "entry_date:desc"
                    ],
                    "filter": [
                        {if url:param:support-add-on && url:param:support-type}
                            "categories = \"{url:param:support-add-on}\" AND categories = \"{url:param:support-type}\""
                        {if:elseif url:param:support-add-on}
                            "categories = \"{url:param:support-add-on}\""
                        {if:elseif url:param:support-type}
                            "categories = \"{url:param:support-type}\""
                        {/if}
                    ]
                }
            {/search_filters}

            {if no_results}
                <li>No results found.</li>
            {/if}

            {exp:channel:entries
                entry_id="{entry_ids}"
                dynamic="no"
                status="open|resolved|closed|backlog|with-customer|to-do"
            }
                {partial_tickets_list}
            {/exp:channel:entries}
        {/exp:dexter:search}
    </ul>
{if:else}
    <div>
        <p>Please enter search criteria.</p>
    </div>
{/if}

This is the config file for Meilisearch. It is very basic and almost all default values, nothing fancy going on. I did create a custom pipeline to merge the ticket details and all public comments into the __full_text field to improve search relevancy.

{
    "displayedAttributes": [
        "*"
    ],
    "searchableAttributes": [
        "title",
        "__full_text"
    ],
    "filterableAttributes": [
        "categories"
    ],
    "sortableAttributes": [
        "entry_date",
        "title"
    ],
    "rankingRules": [
        "words",
        "typo",
        "proximity",
        "attribute",
        "sort",
        "exactness",
        "entry_date:asc"
    ],
    "stopWords": [],
    "nonSeparatorTokens": [],
    "separatorTokens": [],
    "dictionary": [],
    "synonyms": [],
    "distinctAttribute": null,
    "proximityPrecision": "byWord",
    "typoTolerance": {
        "enabled": true,
        "minWordSizeForTypos": {
            "oneTypo": 5,
            "twoTypos": 9
        },
        "disableOnWords": [],
        "disableOnAttributes": []
    },
    "faceting": {
        "maxValuesPerFacet": 100,
        "sortFacetValuesBy": {
            "*": "alpha"
        }
    },
    "pagination": {
        "maxTotalHits": 1000
    },
    "embedders": [],
    "searchCutoffMs": null,
    "localizedAttributes": null,
    "facetSearch": true,
    "prefixSearch": "indexingTime"
}

Last updated

Was this helpful?