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?