Cabin — React & Redux Example App — Algolia

Nick Parsons
Jun 28, 2016 · 6 min read
cabin_algolia_post
cabin_algolia_post

This is the 7th post in our 8 part tutorial series created by GetStream.io. The final result is your own feature-rich, scalable social network app built with React and Redux! Visit cabin.getstream.io for an overview of all 8 tutorials and a live demo. The full source code is available on GitHub.

Introduction

You’re in luck! This is exactly what Algolia allows you to do. With Algolia, you can build unique search experiences for your application in a fraction of the time that it would normally take — we’re talking about saving hours, days or possibly weeks. Best of all, it’s hosted and delivers nearly instant results that can be fine-tuned to your exact needs.

There’s a reason why we chose to use it to build Cabin, as did other giants, such as Product Hunt, CrunchBase, DigitalOcean, Medium, and Hacker News (just to name a few).

Overview

Getting Started

Server Side

Client Side

Typo Tolerance

Geo-Based Search

Weekly Usage Report

Dashboard

Stay updated to upcoming posts in this React & Redux series:

Getting Started

Step 1: Install & Clone Example App

Follow the step below to clone the repo (if you haven’t already):

git clone git@github.com:GetStream/stream-react-example.git

Note: If you have not already completed the introductory tutorial, now is a great time to do so as we outline the application structure and initial setup required.

Step 2: Create Algolia Account

Simply head over to their website and create a FREE account.

and create a FREE account. You’ll have an unlimited 14 day trial, but not to worry, you can always use their Hacker plan if you stay below 10,000 records and 100,000 operations per month.

Step 3: Gather API Credentials

On the left hand side of your dashboard, click on “API Keys”.

Screen Shot 2016-06-10 at 2.09.16 PM
Screen Shot 2016-06-10 at 2.09.16 PM

Both the client facing application and server side API will use the same credentials.

Fill in your API credentials in /env.sh and source the file appropriately:

vim ./env.sh

export ALGOLIA_APP_ID=VALUE
export ALGOLIA_SEARCH_ONLY_KEY=VALUE
export ALGOLIA_API_KEY=VALUE

source ./env.sh

Step 4. Install the API Client

In our case, we’ll install it via NPM:

cd /app && npm install algoliasearch --save

cd ../api && npm install algoliasearch --save

Algolia also provides easy to use integrations via bower, and via CDN.

Step 5: Create an Index

Screen Shot 2016-06-10 at 2.53.42 PM
Screen Shot 2016-06-10 at 2.53.42 PM

Jumping into the Server Side Code

To begin, let’s have a look at the server side API where the heavy lifting happens behind the scenes.

Let’s head over to /api/routes/uploads.js and take a look at around line 322:

var algolia = algoliaSearch(config.algolia.appId, config.algolia.apiKey);

var index = algolia.initIndex('cabin');

index.addObject(result);

As you can see, the code is extremely straightforward.

First, we initialize the Algolia client using our appId and apiKey.

Second, we initialize our newly created index, cabin, and assign it to a variable named index.

Lastly, we call addObject and pass in our object for indexing.

Note: If you have a look at the code above line ~322, you’ll notice that there is a series of waterfall function calls being made using the popular Node.js library, Async. The several layers of waterfall provide us with an object at the end (the object used for indexing), which is structured as:

{
"id": 1,
"email": "foo@bar.com",
"fb_uid": "1213861088933558",
"first_name": "Foo",
"last_name": "Bar"
}

Behind the scenes, we’re able to look at the incoming response (for debugging purposes) and see exactly what was passed to Algolia:

Screen Shot 2016-06-10 at 3.03.48 PM
Screen Shot 2016-06-10 at 3.03.48 PM

Note: To get to API Call Details, click on Indices on the left sidebar, then click on Logs. From there, you can choose any of the latest operations.

For brevity, we’re only going to cover the POST /uploads endpoint; however, Algolia is used throughout the API and can be found in /api/routes/users.js.

Client Side Implementation

Head over to /app/modules/actions.

This directory contains all our Redux actions, which you can read about on our previous blog post found here.

The primary logic for our client side search can be found inside of Search.js in our actions directory.

Because we’re using ES6 on the client, we can use the import statement to pull in the algoliasearch NPM library:

import algoliasearch from 'algoliasearch'
import config from 'config'

const algolia = algoliasearch(config.algolia.appId, config.algolia.searchOnlyKey)

Let’s move down to around line 40, and look at where we call our dispatch event:

return dispatch => {

// initialize the 'cabin' index:
let index = algolia.initIndex('cabin'),
attrs = []

switch(type) {
case 'all':
attrs.push(
'first_name',
'last_name',
'location',
'hashtags',
)
break;
case 'hashtags':
attrs.push('hashtags')
break
case 'user':
attrs.push(
'first_name',
'last_name',
)
break
case 'location':
attrs.push('location')
break
}

// perform algolia search:
index.search(term, {
attributesToHighlight: attrs,
hitsPerPage: 100
}, (err, content) => {
dispatch(_searchResponse(term, content))
})
}

Breaking this down a bit — here we are searching our “cabin” index for a term with two options:

  • attributesToHighlight
  • hitsPerPage

attributesToHighlight is based on one of four search modes we have created: all, hashtags, user, and location.

Depending on our case, we use a switch statement to send an object of the appropriate object attributes to search upon. Highlighting search terms in results is an important part of creating a great search UX. It’s important for users to know why their search returned the results that it did. Algolia does result highlighting by default, but for Cabin we need to specify the attributes we want highlighted because they differ based on the type of search.

hitsPerPage is straightforward — and in this case, we are returning 100 results.

As far as implementation goes, that’s all it takes to have a fast and accurate search in your application!

More Awesome Options & Functionality

Typo Tolerance

minWordSizeFor1Typo
minWordSizeFor2Typos
typoTolerance
allowTyposOnNumericTokens

Geo-Based Search

Weekly Usage Report

Screen Shot 2016-06-13 at 9.05.56 AM
Screen Shot 2016-06-13 at 9.05.56 AM

Powerful Dashboard For Debugging

Screen Shot 2016-06-10 at 2.47.52 PM
Screen Shot 2016-06-10 at 2.47.52 PM

Hungry For More?

Conclusion

This tutorial series is created by getstream.io. Try the 5 min interactive tutorial to learn how Stream works.


Originally published at The Stream Blog.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store