Guides / Building Search UI / UI & UX patterns

Geo Search with Vue InstantSearch

Overview

We will see how we can leverage the geo search capabilities of Algolia with the connectGeoSearch connector. This demo is built with Google Maps but the core logic is not tied to any map provider. You can build your own map widget with a different provider (e.g. Leaflet).

Since wrapping Google Maps for Vue isn’t trivial, in this guide we will use the vue-googlemaps library to save time.

Dataset

We’ll use a dataset of 3000+ records of the biggest airports in the world.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
  {
    "objectID": "3797",
    "name": "John F Kennedy Intl",
    "city": "New York",
    "country": "United States",
    "iata_code": "JFK",
    "links_count": 911
    "_geoloc": {
      "lat": 40.639751,
      "lng": -73.778925
    }
  }
]

To be able to display hits on the map, we have the latitude and longitude stored in the record. We recommend storing it in the _geoloc attribute as it will allow you to do geo-filtering and and geo-sorting.

You can download the dataset on GitHub. Have a look at how to import it in Algolia.

Configure Index Settings

When displaying on a map, you still want the relevance to be good. For that let’s configure the index.

  • searchable attributes: we’re going to search in our 4 textual attributes: name, city, country and iata_code.
  • custom ranking: let’s use the number of other connected airports links_count as a ranking metric. The more connections the better.
1
2
3
4
$index->setSettings([
  'searchableAttributes' => ['name', 'city', 'country', 'iata_code'],
  'customRanking' => ['desc(links_count)']
]);

Displaying hits

First of all, we will start by adding the vue-googlemaps library as expected:

1
2
3
4
5
6
7
8
9
10
// main.js
import 'vue-googlemaps/dist/vue-googlemaps.css';
import VueGoogleMaps from 'vue-googlemaps';

Vue.use(VueGoogleMaps, {
  load: {
    // your Google API key
    apiKey: 'AIxxxxx',
  },
});

The next step is making a custom widget for Vue InstantSearch, in this case using connectGeoSearch :

1
2
3
4
5
6
7
8
<script>
import { createWidgetMixin } from 'vue-instantsearch';
import { connectGeoSearch } from 'instantsearch.js/es/connectors';

export default {
  mixins: [createWidgetMixin({ connector: connectGeoSearch })],
};
</script>

Now that you have access to the data from the Geo Search connector, you want to add a regular map in the template. Note that to make the map actually visible, you need to make sure it has a height given. This can be done with CSS by selecting the map element and giving it any height.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
  <div v-if="state" class="ais-GeoSearch">
    <googlemaps-map
      :center="center"
      :zoom.sync="zoom"
      class="ais-GeoSearch-map"
    >
    </googlemaps-map>
  </div>
</template>

<script>
export default {
  data() {
    return {
      center: { lat: 0, lng: 0 },
      zoom: 12,
    };
  },
};
</script>

The final step is looping over this.state.items to display the hits from this search:

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
<template>
  <div v-if="state" class="ais-GeoSearch">
    <googlemaps-map
      :center="center"
      :zoom.sync="zoom"
      class="ais-GeoSearch-map"
    >
      <googlemaps-marker
        v-for="item of state.items"
        :key="item.objectID"
        :title="item.name"
        :position="item._geoloc"
      />
    </googlemaps-map>
  </div>
</template>

<script>
import { createWidgetMixin } from 'vue-instantsearch';
import { connectGeoSearch } from 'instantsearch.js/es/connectors';

export default {
  mixins: [createWidgetMixin({ connector: connectGeoSearch })],
  data() {
    return {
      zoom: 12,
    };
  },
  computed: {
    center() {
      return this.state.items[0]._geoloc;
    },
  },
};
</script>

That’s it. Now you should have a complete geo search experience. Don’t forget that the complete source code of the example is available on GitHub.

Going further

This guide only explains how to display hits on a map, but connectGeoSearch connector has more features, like refining the search when the map moves, automatically centering on the correct items etc. Feel free to explore the options given to state from the connector to make these experiences.

Did you find this page helpful?