Guides / Building Search UI / Resources / UI and UX patterns

Multi Index Search

Overview

It might happen that you want to search across multiple indices at the same time. Vue InstantSearch has a built-in solution for searching into multiple indices with an autocomplete component. Another common use case is to display hits from multiple indices at the same time. We don’t have a proper API for this use case but we can synchronize two Vue InstantSearch instance to have the same behavior.

In this guide we will learn how to share a single ais-search-box to display multiple hits from different indices. We will also take a look at how to create an autocomplete that targets multiple indices. The source code of both examples can be found on GitHub.

Hits from multiple indices

For this first use case we share a single ais-search-box to search into multiple indices. For this behavior we use two ais-instant-search instances. Each of them target a specific index, the first one is instant_search and the second is instant_search_price_desc.

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
<template>
  <div>
    <ais-instant-search
      :search-client="searchClient"
      index-name="instant_search_price_desc"
    >
      <ais-search-box v-model="query" />
      <ais-configure
        :restrictSearchableAttributes="['name']"
        :hitsPerPage="8"
      />
      <ais-hits>
        <template slot="item" slot-scope="{ item }">
          <h3><ais-highlight :hit="item" attribute="name" /></h3>
          <img :src="item.image" />
        </template>
      </ais-hits>
    </ais-instant-search>
    <hr />
    <ais-instant-search
      :search-client="searchClient"
      index-name="instant_search"
    >
      <ais-configure
        :query="query"
        :restrictSearchableAttributes="['name']"
        :hitsPerPage="8"
      />
      <ais-hits>
        <template slot="item" slot-scope="{ item }">
          <h3><ais-highlight :hit="item" attribute="name" /></h3>
          <img :src="item.image" />
        </template>
      </ais-hits>
    </ais-instant-search>
  </div>
</template>

<script>
import algoliasearch from 'algoliasearch/lite';

export default {
  data() {
    return {
      searchClient: algoliasearch(
        'latency',
        '6be0576ff61c053d5f9a3225e2a90f76'
      ),
      query: '',
    };
  },
};
</script>

What’s to note here is that we make the ais-search-box “controlled”. We keep track of the query in the query data variable. Every time something changes in the first index, we will be notified via its change handler. Subsequently we apply that query to the other index, by making use of the ais-configure component.

Note that since this is two dedicated instances we can apply different parameters and widgets to the search. This can be done by passing different parameters to ais-configure or mounting different widgets in each of the ais-instant-search components.

You can find the complete example on GitHub.

autocomplete

For this second use case we are gonna build an autocomplete to search into multiple indices. We are not going to talk too much about the autocomplete part. You can find a complete guide on the subject in the documentation. The autocomplete is built with Vue Autosuggest and the ais-autocomplete component. The only difference with the previous guide is how we append the hits to the autocomplete.

The ais-autocomplete component takes indices as a prop. This is an array of additional indices to search into, in this case the instant_search_price_desc index. Just like in the other guide, we will need to transform the results from Algolia into what the Vue Autosuggest component expects, except this time we will also need to make sure the shape of either hit is the same, to avoid too much logic in the template itself.

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
<template>
  <div class="container">
    <ais-instant-search
      :search-client="searchClient"
      index-name="instant_search"
    >
      <ais-configure
        :hitsPerPage="5"
        :restrictSearchableAttributes="['name']"
      />
      <ais-autocomplete
        :indices="[
          {
            value: 'instant_search_price_desc',
            label: 'Price (desc)',
          },
        ]"
      >
        <template slot-scope="{ currentRefinement, indices, refine }">
          <vue-autosuggest
            :suggestions="indicesToSuggestions(indices)"
            @selected="onSelect"
            :input-props="{
              style: 'width: 100%',
              onInputChange: refine,
              placeholder: 'Search here…',
            }"
          >
            <template slot-scope="{ suggestion }">
              <ais-highlight
                :hit="suggestion.item"
                attribute="name"
                v-if="suggestion.item.name"
              />
              <strong>$ {{ suggestion.item.price }}</strong>
              <img :src="suggestion.item.image" />
            </template>
          </vue-autosuggest>
        </template>
      </ais-autocomplete>
    </ais-instant-search>
  </div>
</template>

<script>
import algoliasearch from 'algoliasearch/lite';
import { VueAutosuggest } from 'vue-autosuggest';

export default {
  components: { VueAutosuggest },
  data() {
    return {
      searchClient: algoliasearch(
        'latency',
        '6be0576ff61c053d5f9a3225e2a90f76'
      ),
      query: '',
    };
  },
  methods: {
    onSelect(selected) {
      if (selected) {
        console.log(selected);
      }
    },
    indicesToSuggestions(indices) {
      return indices.map(({ hits }) => ({
        data: hits,
      }));
    },
  },
};
</script>

You can find the complete example on GitHub.

Did you find this page helpful?