Scott Smith

Blog Tutorials Projects Speaking RSS

Algolia Real Time Search With Firebase

One key feature of Firebase is building realtime applications by using their backend to store and sync data. Algolia further enhances that by providing realtime search capabilities. In a few simple steps, this tutorial will teach you how to import your existing data, index new data as it is added to Firebase, and remove indexed data when it is removed from Firebase.

Algolia’s Node.js client simplifies the integration of your Firebase applications with Algolia’s real time search service. The module makes it easy for you to use Algolia’s search capabilities in a manner that will be familiar to those already developing Firebase and Node.js applications.

Prerequisites

Familiar with Firebase

This tutorial assumes you are familiar with Firebase, how it works, and how to build Firebase applications. If you would like to learn more before continuing with this tutorial, I suggest reading the following documentation and tutorials:

  1. Getting started
  2. Quickstart web tutorial
  3. Web development guide

Create a Node.js Application

In order to index your Firebase data and continually add/update index information, you will need to create a Node.js application. This application will be responsible for getting data out of Firebase and indexing it with Algolia. It can then be run anywhere like Heroku, Nodejitsu, AWS, Azure, etc.

In this tutorial, we will be indexing contact information in a Firebase application. Be sure to change ‘YourApplicationID’ and ‘YourAPIKey’ to your account values here. Because we are making calls that require more than read access, you will need to create a new key or use an existing one that can Add Records, Delete Records, and Delete Index (for reindexing example). You will also need to set your Firebase ‘INSTANCE’ to the one your application uses.

Here is the intial portion of the Node.js application.

1
2
3
4
5
6
7
var Firebase = require('firebase');
var algoliasearch = require('algoliasearch');
var client = algoliasearch('YourApplicationID', 'YourAPIKey');
var index = client.initIndex('contacts');

// Connect to our Firebase contacts data
var fb = new Firebase('<INSTANCE>.firebaseio.com/contacts');

Be sure to install the necessary packages so your application will run.

1
2
npm install firebase --save
npm install algoliasearch --save

Import Existing Data

In many cases, you may already have data within your Firebase application. In order to integrate with Algolia, you will want to index that data. We will use contact information being stored within Firebaseio as our example. Add the following code to your Node.js application.

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
// Get all data from Firebase
fb.on('value', initIndex);

function initIndex(dataSnapshot) {
  // Array of data to index
  var objectsToIndex = [];

  // Get all objects
  var values = dataSnapshot.val();

  // Process each Firebase ojbect
  for (var key in values) {
    if (values.hasOwnProperty(key)) {
      // Get current Firebase object
      var firebaseObject = values[key];

      // Specify Algolia's objectID using the Firebase object key
      firebaseObject.objectID = key;

      // Add object for indexing
      objectsToIndex.push(firebaseObject);
    }
  }

  // Add or update new objects
  index.saveObjects(objectsToIndex, function(err, content) {
    if (err) {
      throw err;
    }

    console.log('Firebase<>Algolia import done');
  });
}

To ensure the indexing performs well it is suggested you limit the number of items indexed per call between 1,000 and 10,000 depending on the object size.

Once you run this code, you will have all of your existing Firebase data indexed with Algolia. You will want to remove this code once is is done because the event will continue to fire each time data is added.

Reindex Data

Sometimes, you may have the need to completely reindex your data. This means removing data from the index that may not longer exist, adding new data, and updating existing data. The following code can be added to the Node.js application to perform a reindexing. You will want to remove or comment out the initial index code if currently present.

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
// Get all data from Firebase
fb.on('value', reindexIndex);

function reindexIndex(dataSnapshot) {
  // Array of objects to index
  var objectsToIndex = [];

  // Create a temp index
  var tempIndexName = 'contacts_temp';
  var tempIndex = client.initIndex(tempIndexName);

  // Get all objects
  var values = dataSnapshot.val();

  // Process each Firebase object
  for (var key in values) {
    if (values.hasOwnProperty(key)) {
      // Get current Firebase object
      var firebaseObject = values[key];

      // Specify Algolia's objectID using the Firebase object key
      firebaseObject.objectID = key;

      // Add object for indexing
      objectsToIndex.push(firebaseObject);
    }
  }

  // Add or update new objects
  index.saveObjects(objectsToIndex, function(err, content) {
    if (err) {
      throw err;
    }

    // Overwrite main index with temp index
    client.moveIndex(tempIndexName, 'contacts', function(err, content) {
      if (err) {
        throw err;
      }

      console.log('Firebase<>Algolia reimport done');
    });
  });
}

To ensure the reindexing performs well it is suggested you limit the number of items indexed per call between 1,000 and 10,000 depending on the object size.

Once you run this code, you will have all of your existing Firebase data reindexed with Algolia. You will want to remove this code once is is done because the event will continue to fire each time data is added.

Add or Update Data

Now, we need to handle the case where data is being added or updated. We can easily setup our code to automatically add or update data to our search index by attaching to the ‘child_added’ and ‘child_changed’ events. This will allow us to define code that will be called after data is stored in Firebase. Add the following code to your Node.js application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Listen for changes to Firebase data
fb.on('child_added', addOrUpdateObject);
fb.on('child_changed', addOrUpdateObject);

function addOrUpdateObject(dataSnapshot) {
  // Get Firebase object
  var firebaseObject = dataSnapshot.val();

  // Specify Algolia's objectID using the Firebase object key
  firebaseObject.objectID = dataSnapshot.key();

  // Add or update object
  index.saveObject(firebaseObject, function(err, content) {
    if (err) {
      throw err;
    }

    console.log('Firebase<>Algolia object saved');
  });
}

Now, whenever contact data is saved in Firebase, it will automatically be indexed with Algolia.

Delete Data

Next, we need to handle the case where data is deleted from your Firebase application. In order to do this, we can attach to the ‘child_removed’ event. This will allow us to define code that will be called after data is removed from Firebase. Add the following code to your Node.js application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Listen for changes to Firebase data
fb.on('child_removed', removeIndex);

function removeIndex(dataSnapshot) {
  // Get Algolia's objectID from the Firebase object key
  var objectID = dataSnapshot.key();

  // Remove the object from Algolia
  index.deleteObject(objectID, function(err, content) {
    if (err) {
      throw err;
    }

    console.log('Firebase<>Algolia object deleted');
  });
}

Now, whenever contact data is removed from Firebase, it will automatically get removed from Algolia.

Next Steps

  1. Read the Node.js documentation
  2. Dive into the Node.js command reference
  3. Explore the Node.js API client source code