@meilisearch/instant-meilisearch
Version:
The search client to use Meilisearch with InstantSearch.
124 lines • 6.59 kB
JavaScript
import { MeiliSearch } from 'meilisearch';
import { getApiKey, getInstantMeilisearchConfig, validateInstantMeiliSearchParams, } from './config/index.js';
import { adaptSearchResults, adaptSearchParams, SearchResolver, } from '../adapter/index.js';
import { createSearchContext, createFacetSearchContext, } from '../contexts/index.js';
import { SearchCache, initFacetDistribution, getParametersWithoutFilters, fillMissingFacets, } from '../cache/index.js';
import { constructClientAgents } from './agents.js';
/**
* Instantiate SearchClient required by instantsearch.js.
*
* @param {string} hostUrl
* @param {string | ApiKeyCallback} [apiKey=''] Default is `''`
* @param {InstantMeiliSearchOptions} [instantMeiliSearchOptions={}] Default is
* `{}`
* @returns {InstantMeiliSearchObject}
*/
export function instantMeiliSearch(hostUrl, apiKey = '', instantMeiliSearchOptions = {}) {
// Validate parameters
validateInstantMeiliSearchParams(hostUrl, apiKey, instantMeiliSearchOptions);
// Resolve possible function to get apiKey
apiKey = getApiKey(apiKey);
const clientAgents = constructClientAgents(instantMeiliSearchOptions.clientAgents);
const meilisearchConfig = {
host: hostUrl,
apiKey,
clientAgents,
};
if (instantMeiliSearchOptions.httpClient !== undefined) {
meilisearchConfig.httpClient = instantMeiliSearchOptions.httpClient;
}
if (instantMeiliSearchOptions.requestInit !== undefined) {
meilisearchConfig.requestInit = instantMeiliSearchOptions.requestInit;
}
const meilisearchClient = new MeiliSearch(meilisearchConfig);
const searchCache = SearchCache();
// create search resolver with included cache
const searchResolver = SearchResolver(meilisearchClient, searchCache);
let initialFacetDistribution = {};
const instantMeilisearchConfig = getInstantMeilisearchConfig(instantMeiliSearchOptions);
return {
meiliSearchInstance: meilisearchClient,
setMeiliSearchParams: (params) => {
const { meiliSearchParams } = instantMeiliSearchOptions;
instantMeiliSearchOptions.meiliSearchParams =
meiliSearchParams === undefined
? params
: {
...meiliSearchParams,
...params,
indexesOverrides: {
...(meiliSearchParams.indexesOverrides || {}),
...(params.indexesOverrides || {}),
},
};
},
searchClient: {
clearCache: () => searchCache.clearCache(),
/**
* @param {readonlyAlgoliaMultipleQueriesQuery[]} instantSearchRequests
* @returns {Array}
*/
search: async function (instantSearchRequests) {
try {
const meilisearchRequests = [];
const instantSearchPagination = [];
const initialFacetDistributionsRequests = [];
for (const searchRequest of instantSearchRequests) {
const searchContext = createSearchContext(searchRequest, instantMeiliSearchOptions);
// Adapt the search parameters provided by instantsearch to
// search parameters that are compliant with Meilisearch
const meilisearchSearchQuery = adaptSearchParams(searchContext);
meilisearchRequests.push(meilisearchSearchQuery);
// Create a parameter without any filters to be able to store the default facet distribution
const defaultSearchQuery = getParametersWithoutFilters(searchContext);
initialFacetDistributionsRequests.push(defaultSearchQuery);
// Keep information about the pagination parameters of instantsearch as
// they are needed to adapt the search response of Meilisearch
instantSearchPagination.push(searchContext.pagination);
}
initialFacetDistribution = await initFacetDistribution(searchResolver, initialFacetDistributionsRequests, initialFacetDistribution);
// Search request to Meilisearch happens here
const meilisearchResults = await searchResolver.multiSearch(meilisearchRequests, instantSearchPagination // Create issue on pagination
);
// Fill the missing facet values if keepZeroFacets is true
initialFacetDistribution = fillMissingFacets(initialFacetDistribution, meilisearchResults);
const instantSearchResponse = adaptSearchResults(meilisearchResults, initialFacetDistribution, instantMeilisearchConfig);
return instantSearchResponse;
}
catch (e) {
console.error(e);
throw new Error(e);
}
},
searchForFacetValues: async function (requests) {
const results = [];
for (const request of requests) {
const searchContext = createFacetSearchContext(request, instantMeiliSearchOptions);
const meilisearchSearchQuery = adaptSearchParams(searchContext);
const meilisearchRequest = {
...meilisearchSearchQuery,
facetQuery: request.params.facetQuery,
facetName: request.params.facetName,
};
delete meilisearchRequest.indexUid;
const meilisearchResponse = await meilisearchClient
.index(searchContext.indexUid)
.searchForFacetValues(meilisearchRequest);
const facetHits = meilisearchResponse.facetHits.map((facetHit) => ({
...facetHit,
// not currently supported
highlighted: facetHit.value,
}));
const result = {
facetHits,
exhaustiveFacetsCount: false,
processingTimeMS: meilisearchResponse.processingTimeMs,
};
results.push(result);
}
return results;
},
},
};
}
//# sourceMappingURL=instant-meilisearch-client.js.map