Search with autocomplete is a standard feature in most apps. It is used for searching through a catalog of resources such as products, services, airports, hotels, cars, posts, etc. This capability does not come built-in with Google Firestore DB. Firestore DB doesn’t support keystroke search or native indexing for text fields in documents. Furthermore, loading an entire collection on the client or a cloud function just to search on certain fields is not prudent. It can cause performance degradation as well as increase the overall cost via expensive queries since Firestore’s pricing model is based on a per-document read model. 

Firebase recommends using a third-party service like Algolia or Elasticsearch to enable full text search or keystroke search for Firestore data. Integration with Algolia requires configuring the Algolia client with your App ID and API key. Alogia is also a paid service with very limited options in the free plan. If you don’t want to go through the overhead of setting up and paying for Algolia or Elasticsearch, a simple workaround for keystroke/typeahead search can be implemented on Cloud Firestore using searchable data structures and some special data querying methods. 

Before we get into it, this article assumes you have a basic understanding of working with React apps and have some experience working with Google Firebase and Firestore DB. If not, I strongly encourage doing some tutorials on how to build React apps as well as dipping your feet in Google Firebase and Firestore. Onwards to the article then. 

Now, let’s suppose we want to implement a Country autocomplete search component as shown below. 

To build this Autocomplete search dropdown, we will use the following in our React app:

  1. List of countries in the dropdown data sourced from countries.json, provided here – https://gist.github.com/amitjambusaria/b9adebcb4f256eae3dfa64dc9f1cc2ef
  2. React Autosuggest – https://react-autosuggest.js.org
  3. Google Firestore database

React Autosuggest Setup

The dropdown options are the countries are not preloaded on the client side. This is done to avoid overloading the DOM with thousands of options, which can lead to sluggishness and performance degradations. Instead, with each keystroke, a network call is made with a search query to fetch a filtered subset of options. 

As seen above, with each keystroke, a GET call is made to the Firestore database with the search keywords. The front-end React Autosuggest component has a prop called onSuggestionsFetchRequested, wherein you can pass a method that can fetch the search-specific options from the server; in our case, data/options will be directly fetched from the Firestore database. The following are some of other key props that come with React Autosuggest: 

Prop

Type

Required

Description

suggestions

Array

These are the suggestions that will be displayed. Items can take an arbitrary shape.

onSuggestionsFetchRequested

Function

Will be called every time you need to recalculate suggestions.

onSuggestionsClearRequested

Function

Will be called every time you need to set suggestions to [].

getSuggestionValue

Function

Implement it to teach Autosuggest what should be the input value when a suggestion is clicked.

renderSuggestion

Function

Use your imagination to define how suggestions are rendered.

inputProps

Object

Pass through arbitrary props to the input. It must contain value and onChange.

Click here for the full list of props. Given below is the front-end search component that leverages React Autosuggest.

Cloud Firestore Setup

Keystroke search is not supported natively by Firestore. To get around this limitation, we will have to seed the search options in a creative way. This solution is ideal when you want to search on just one or two properties of your document and don’t want to invest in paid services like Algolia or Elastic Search. 

In our app, since we are searching for countries, we will have to seed the Country Collection in our Firestore DB. But simply seeding the data is not enough. For type-ahead autocomplete we need the ability to search the document based on the country “name” property. Loading the entire collection and performing the search directly on the client-side is not feasible, because, depending on the size of the collection, it could cause slowness. It can also get very expensive since Firstore’s pricing model is based on a per document read model, so when you load an entire collection for each user the costs can quickly add up.

The answer lies in creating a searchableKeywords object for the field we want to search on. In our app, the country “name” string will be broken into substring elements and stored as an Array on each individual document. We can then query Firestore on these substrings. For example, the searchableKeywords for the country “Canada” would be:

The searchableKeywords Array is created using a seeding script. This script is meant to be run as Admin against your Firestore DB. When executed, the generateKeywords method (line 29) computes the searchableKeywords Array with the country name substrings. This Array is added to each Country document. Finally, the entire Country Collection is committed to Firestore (line 53-64).

Once the searchableKeywords are in place, you can query it using the array-contains Firestore operator. When the user types “can” in the search field, all Countries which have “can” in their searchableKeywords Array will be returned as autocomplete suggestions. Given below is the query to fetch suggestions.

Conclusion

This approach for autocomplete keystroke search is very easy to setup and maintain in Firestore. It is pretty barebones and not as feature-rich as Algolia or Elasticsearch. Another drawback is that the user has to enter their search term correctly and it does not handle spelling errors. Having said that, if your needs are simple and you want something for free, this can be a quick and elegant solution for your app.



Source link

Write A Comment