Ceasar
Ceasar

Reputation: 23073

Algolia: How to pass refinements from a front-end to a backend?

I have a webpage that uses Algolia's React InstantSearch. It has a search bar and several refinements.

I want the user to be able to press a button and get a list of all matching results.

To get a list of all results, I need to use the Browse Index instead of the Search Index. The Browse Index allows retrieving all hits; the Search Index allows retrieval of only up to 1000 hits. However, the Browse Index should not be used in UIs. So I want to create an API endpoint my web server that uses the Browse Index in order return a list of matching hits given a search query.

I am able to successfully do this for a search query, but I can't figure out how to this for refinements.

Here is a sketch of what I have so far.

Back-end (in Ruby):

ALGOLIA_INDEX = Algolia::Index.new('Products')

class AlgoliaSearchController < ActionController::Base
  def get_search_results
    query = params['query']
    hits = []
    ALGOLIA_INDEX.browse({query: query}) do |hit|
      hits << hit
    end
    render json: hits
  end
end

Frontend:

import qs from 'qs';
import React, { useCallback, useState } from 'react';
import { InstantSearch } from 'react-instantsearch-dom';

function getSearchResults(query) {
  const queryString = qs.stringify({
    query,
  })
  return fetch(`/search_results?{queryString}`);
}


function App() {
  const [searchState, setSearchState] = useState(null);
  const onSearchStateChange = useCallback(searchState => {
    setSearchState(searchState);
  }, [searchState]);
  const onClick = useCallback(() => {
    console.log(getSearchResults(searchstate.query));
  });

  return (
    <InstantSearch ... onSearchStateChange={onSearchStateChange}>
      <button onClick={onClick}>Search</button>
    </InstantSearch>
  );
}

I can't find any resources that explain how to do search with refinements.

Things I've looked at so far:

Upvotes: 3

Views: 504

Answers (1)

Haroen Viaene
Haroen Viaene

Reputation: 1360

You are right that this is currently not exactly straightforward. The flow to get the raw search parameters you can use for "browse" is like this:

  1. give your custom component access to the last search results
  2. read the state from those results
  3. create a new helper using this state
  4. use helper.getQuery() to get the query parameters to apply

A sandbox that illustrates this is: https://codesandbox.io/s/extending-widgets-luqd9

import React, { Component } from 'react';
import algoliaHelper from 'algoliasearch-helper';
import { connectStateResults } from 'react-instantsearch-dom';

class Downloader extends Component {
  state = {
    instructions: '',
  };

  onDownloadClick = () => {
    // get the current results from "connectStateResults"
    const res = this.props.searchResults;
    // read the private "state" (SearchParameters) from the last results
    const state = res && res._state;
    // create a new "helper" with this state
    const helper = algoliaHelper({}, state.index, state);
    // get the query parameters to apply
    const rawQuery = helper.getQuery();
    this.setState({
      instructions:
        'Do a search backend with this:\n\nclient.browseAll(' +
        JSON.stringify(rawQuery, null, 2) +
        ')',
    });
  };

  render() {
    return (
      <React.Fragment>
        <button onClick={this.onDownloadClick}>download</button>
        <pre>{this.state.instructions}</pre>
      </React.Fragment>
    );
  }
}

export default connectStateResults(Downloader)

Upvotes: 2

Related Questions