Plugins — InstantSearch.js
Combine the excellence of Miso's accurate search and Algolia's flexible InstantSearch.js UI framework.
With Miso's InstantSearch.js plugin, you can easily work with:
Installation
Install the npm modules:
npm install --save @miso.ai/client-sdk @miso.ai/client-sdk-algolia
In your app, import and setup the plugin:
import MisoClient from '@miso.ai/client-sdk';
import { AlgoliaPlugin } from '@miso.ai/client-sdk-algolia';
MisoClient.plugins.use(AlgoliaPlugin);
Basic Usage
This plugin provides a compatible InstantSearch.js search client interface from Miso's SDK client.
const client = new MisoClient('...');
const search = instantsearch({
searchClient: client.algolia.searchClient(),
indexName: '',
});
Using InstantSearch.js
With InstantSearch.js properly setup, you can connect it to Miso SDK easily:
- Install Miso client-side SDK for Javascript and the InstantSearch.js plugin.
- Substitute Algolia's search client with the one generated from Miso SDK client.
Miso's philosophy promotes a submit-based search paradigm, accomplished with an autocomplete UI pattern.
Example
//const searchClient = algoliasearch(...);
const client = new MisoClient('...');
const search = instantsearch({
//searchClient: searchClient,
searchClient: client.algolia.searchClient(),
indexName: '' // empty string for default Miso engine
});
search.addWidgets([
instantsearch.widgets.configure({
hitsPerPage: 8
}),
instantsearch.widgets.searchBox({
container: '#search-box',
autofocus: true,
searchAsYouType: false,
showSubmit: true
}),
instantsearch.widgets.hits({
container: '#hits',
templates: { /* ... */ }
})
]);
search.start();
Using Autocomplete
You can combine the power of Miso with InstantSearch.js and Autocomplete.
- Install the Miso client-side SDK for Javascript and the InstantSearch.js plugin.
- Install Autocomplete.
- Follow the guide to integrate InstantSearch.js and Autocomplete.
- Use the autocomplete client from Miso in place of Algolia's original search client (demo).
Example
Setup InstantSearch.js:
const client = new MisoClient('...');
const indexName = ''; // empty string for your default Miso engine
const search = instantsearch({
// use Miso's search client
searchClient: client.algolia.searchClient(),
indexName: indexName
});
search.addWidgets([
instantsearch.widgets.configure({
hitsPerPage: 8
}),
// remove the original search box widget
/*
instantsearch.widgets.searchBox({
container: '#search-box',
autofocus: true,
searchAsYouType: false,
showSubmit: true,
}),
*/
// mount a virtual search box to manipulate InstantSearch's `query` UI state parameter
instantsearch.connectors.connectSearchBox(() => {})({}),
instantsearch.widgets.hits({
container: '#hits',
templates: { /* ... */ }
})
]);
search.start();
Make a tool function to sync Autocomplete's query to InstantSearch.js's query state:
function setInstantSearchQueryState(query = '') {
search.setUiState(uiState => ({
...uiState,
[indexName]: {
...uiState[indexName],
page: 1,
query: query
}
}));
}
Setup Autocomplete:
autocomplete({
container: '#autocomplete',
initialState: {
query: ''
},
onSubmit: ({ state }) => {
setInstantSearchQueryState(state.query);
},
onReset: () => {
setInstantSearchQueryState();
},
/*
// for a submit-based search paradigm, comment out this part
onStateChange: ({ prevState, state }) => {
const { query: prevQuery } = prevState;
const { query } = state;
if (prevQuery !== query) {
setInstantSearchQueryState(query);
}
},
*/
autoFocus: true,
getSources: ({ query }) => {
// this is triggered on every user input
return [{
getItems: () => getAlgoliaResults({
// use Miso's autocomplete client
searchClient: client.algolia.autocompleteClient(),
queries: [{
query: query,
params: {
hitsPerPage: 5,
attributesToHighlight: ['suggested_queries'],
}
}]
}),
onSelect: ({ setQuery, item }) => {
const query = item._text;
setQuery(query);
setInstantSearchQueryState(query);
},
templates: {
item: ({ item, components, html }) => html`
<div class="aa-ItemWrapper">
<div class="aa-ItemContent">
<div class="aa-ItemContentBody">
<div class="aa-ItemContentTitle">
${components.Highlight({
hit: item,
attribute: 'suggested_queries',
})}
</div>
</div>
</div>
</div>
`
}
}];
}
});
Compatibility
The following section elaborates on the compatibility between Algolia's API and Miso's implementation.
Index Name — In InstantSearch.js and Autocomplete, you have to pass a mandatory parameter for index name to their init functions. We use this parameter to correspond to Miso's engine ID:
const client = new MisoClient('...');
const engineId = '...'; // empty string for default Miso engine
const search = instantsearch({
//searchClient: searchClient,
searchClient: client.algolia.searchClient(),
indexName: engineId
});
Search Parameters
Pagination — Both kinds of Algolia’s pagination paradigm are supported.
For example, the following parameters:
searchClient.search([{ hitsPerPage: 10, page: 5 /* ... */ }]);
are mapped to Miso's parameters like this:
client.api.search.search({ rows: 10, start: 10 * 5 /* ... */ });
Filters — Algolia's filter expressions are translated to Miso's syntax.
Facets
Highlighting
Customization
Custom search handler — You can fully control how InstantSearch.js's search request is processed by passing a handler function:
const client = new MisoClient('...');
const searchClient = client.algolia.searchClient({
handleSearch: async ({ misoApiName, mapRequest, callMisoApi, mapResponse }, request, options) => {
// this is equivalent to the default behavior
const payload = mapRequest(misoApiName, request);
const misoResponse = await callMisoApi(misoApiName, payload, options);
return mapResponse(misoApiName, request, misoResponse);
}
});