Turn off Automatic Filtering and Boosting with InstantSearch.js
On this page
Automatic Filtering and Boosting applies a category filter when users enter a query. You can use Query Categorization to predict categories for your most popular queries. If you enable Automatic Filtering and Boosting the categories are automatically applied as filters.
Controlling Automatic Filtering and Boosting in your UI
If you want to have Automatic Filtering and Boosting on or off for all searches, you only need to enable the feature to filter the results automatically.
If you want to let users turn Automatic Filtering and Boosting on or off, you can build an InstantSearch widget. This widget should inform users that the results are filtered. The widget should also let users remove any applied filters.
Building a widget for Automatic Filtering and Boosting
There are three steps to building an Automatic Filtering and Boosting widget:
Check the search response. The search response includes the following properties if Automatic Filtering and Boosting is enabled:
Copy1 2 3 4 5 6 7 8 9 10
{"extensions":{"queryCategorization":{"autofiltering":{"facetFilters":[],"optionalFilters":[]}}}}
If filters are applied to the query, they’re listed in the
facetFilters
property.Copy1 2 3 4 5 6 7
{"facetFilters":["category.level0:Fresh products","category.level1:Fresh vegetables","category.level2:Tomatoes"]}
Let users remove applied filters. To remove filters applied with Automatic Filtering and Boosting, you need to turn the feature off for the current query using the
enableAutoFiltering
API parameter.Copy1 2 3 4 5 6 7
{"extensions":{"queryCategorization":{"enableAutoFiltering":false}}}
Turn on Automatic Filtering and Boosting for new queries. To keep Automatic Filtering and Boosting for other queries, you must first check for a query change and then set
enableAutoFiltering
totrue
.
Implementing the widget
The following custom connector implements all steps to let users turn off Automatic Filtering and Boosting for a search query.
The connector requires the Algolia search helper.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
//connectAutoFiltering.js// util function to set the query parameter (step 2)functionsetAutoFiltering(value,helper){returnhelper.setQueryParameter('extensions',{queryCategorization:{enableAutoFiltering:value,},});}exportfunctionconnectAutoFiltering(renderFn,unmountFn=()=>{}){returnfunctionautoFiltering(widgetParams){constconnectorState={};return{$$type:'algolia.beta.autoFiltering',init(initOptions){const{instantSearchInstance}=initOptions;renderFn({...this.getWidgetRenderState(initOptions),instantSearchInstance,},true);},render(renderOptions){const{instantSearchInstance}=renderOptions;renderFn({...this.getWidgetRenderState(renderOptions),instantSearchInstance,},false);},dispose(){unmountFn();},getWidgetSearchParameters(searchParameters){returnsearchParameters;},getRenderState(renderState,renderOptions){return{...renderState,autoFiltering:this.getWidgetRenderState(renderOptions),};},// this is where the logic happensgetWidgetRenderState({results,helper,state}){if(!connectorState.cancelAutoFiltering){// exposing a function to disable autofilteringconnectorState.cancelAutoFiltering=()=>{// Disable auto filtering for next searchsetAutoFiltering(false,helper);helper.search();// storing in the state the disabled queryconnectorState.disabledQuery=helper.getQuery().query;};}// empty results caseif(!results){return{appliedFilters:[],cancelAutoFiltering:()=>{},widgetParams,};}// enabling back auto filtering if the query has changed (step 3)if(// "state" stores the current query parametersstate.extensions&&state.extensions.queryCategorization.enableAutoFiltering===false&&connectorState.disabledQuery&&results.query!==connectorState.disabledQuery){setAutoFiltering(true,helper);if(results.extensions&&results.extensions.queryCategorization.normalizedQuery){// if the current query has predicted categories, we refine the search with autofiltering enabledhelper.search();}}// Retrieving the applied filters (step 1)constfacetFilters=(results.extensions&&results.extensions.queryCategorization.autofiltering&&results.extensions.queryCategorization.autofiltering.facetFilters)||[];return{appliedFilters:facetFilters.map((facetFilter)=>({name:facetFilter.split(':')[0],value:facetFilter.split(':')[1],})),cancelAutoFiltering:connectorState.cancelAutoFiltering,widgetParams,};},};};}
Use this InstantSearch connector to create a widget.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
// autofiltering.jsimport{connectAutoFiltering}from'./connectAutoFiltering';exportfunctionautoFiltering(widgetParams){const{container:containerSelector}=widgetParams;if(!containerSelector){console.error('The `container` option is required.');}constcontainer=document.querySelector(containerSelector);// the widget render functionconstrenderer=(renderOptions,isFirstRender)=>{const{appliedFilters,cancelAutoFiltering}=renderOptions;/** * Here we choose to display the applied filters in a banner with a button to disable autofiltering * We are displaying only the last filter of the hierarchy, but you can chose to display all of them if you want to * It is entirely up to you how you choose to render the filters */container.innerHTML=appliedFilters.length?` <div style="border: 1px solid lightgray; border-radius: 4px; margin: 1rem 0; padding: 1rem;"> <span><strong>Applied filter:</strong></span> <span>${appliedFilters.pop().value}</span> <button>×</button> </div> `:'';constbutton=container.querySelector('button');if(button){// attaching our cancel function to our buttonbutton.addEventListener('click',()=>{cancelAutoFiltering();});}};constmakeWidget=connectAutoFiltering(renderer,()=>{container.innerHTML='';});return{...makeWidget({}),$$widgetType:'algolia.beta.autoFiltering',};}
If you copy the code snippets into your implementation, check the widget render function to adapt to your design.
You can add the widget to your UI:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import{autoFiltering}from'./autoFiltering';// ...constsearch=instantsearch({indexName,searchClient,});search.addWidgets([// ...autoFiltering({container:'#autofiltering-container',}),]);