UNPKG

@ecomplus/search-engine

Version:

JS lib to handle products search with E-Com Plus stores

125 lines (116 loc) 3.69 kB
import { search } from '@ecomplus/client' import * as cloneDeep from 'lodash.clonedeep' import dslMiddlewares from './../lib/dsl-middlewares' export default (self, isSimpleSearch, axiosConfig) => { // mount axios req options for complex or simpĺe search const { storeId } = self const reqOptions = { url: '/items.json', storeId, axiosConfig } // prepare search DSL let dsl = cloneDeep(self.dsl) dslMiddlewares.forEach(fn => { if (typeof fn === 'function') { const _dsl = fn(dsl) if (_dsl) { dsl = _dsl } } }) if (isSimpleSearch === true) { // https://www.elastic.co/guide/en/elasticsearch/reference/6.3/search-uri-request.html const { query } = dsl reqOptions.url += '?q=' if (query && query.bool && Array.isArray(query.bool.filter)) { // parse query filters to string let queryString = '' query.bool.filter.forEach(({ term, terms }, i) => { if (i > 0) { queryString += ' AND ' } const condition = term || terms if (condition) { const field = Object.keys(condition)[0] const value = condition[field] queryString += `${field}:${(Array.isArray(value) ? `("${value.join('" "')}")` : value)}` } }) reqOptions.url += encodeURIComponent(queryString) } // handle pagination ;['from', 'size'].forEach(field => { if (dsl[field]) { reqOptions.url += `&${field}=${dsl[field]}` } }) } else { reqOptions.method = 'post' reqOptions.data = dsl if (isSimpleSearch && !axiosConfig) { // fallback for old reference with `fetch(axiosConfig)` reqOptions.axiosConfig = isSimpleSearch } } // request Search API and return promise return search(reqOptions).then(({ data }) => { // save last result on instance self.result = data const { dsl, history, localStorage, storageKey } = self if (data.hits.total && dsl && dsl.suggest) { const { text } = dsl.suggest if (text) { // add search term to history const index = history.indexOf(text) if (index > -1) { // prevent duplicated term history.splice(index, 1) } history.unshift(text) if (localStorage && storageKey) { localStorage.setItem(storageKey, history.slice(0, 20).join('||')) } } } // resolving with response data return data }) } /** * @typedef {object} result * @property {object} hits - Elasticsearch hits object * @property {number} hits.total - Total number of products found * @property {array<object>} hits.hits - List of resultant items * @property {object} aggregations - Elasticsearch aggregations results * @property {object} suggest - Search term suggestions object * @property {number} took - Request time in milliseconds */ /** * @method * @name EcomSearch#fetch * @description Send POST request to * [E-Com Plus Search API]{@link https://developers.e-com.plus/docs/api/#/search/items/items} * and returns promise resolved with search result. * * @param {boolean} [isSimpleSearch=false] - Handle simple (and faster) search without sort and aggregations * @param {object} [axiosConfig] - Additional * [axios config]{@link https://github.com/axios/axios#request-config} object * * @returns {Promise<result|error>} * * @example // Run search request search.fetch() .then(result => { console.log(result.took) console.log(`${result.hits.total} items found:`) console.log(result.hits.hits) }) .catch(error => { console.error(error) if (error.response) { console.log(error.response) } }) */