Search by Algolia
Feature Spotlight: Query Rules
product

Feature Spotlight: Query Rules

You’re running an ecommerce site for an electronics retailer, and you’re seeing in your analytics that users keep ...

Jaden Baptista

Technical Writer

An introduction to transformer models in neural networks and machine learning
ai

An introduction to transformer models in neural networks and machine learning

What do OpenAI and DeepMind have in common? Give up? These innovative organizations both utilize technology known as transformer models ...

Vincent Caruana

Sr. SEO Web Digital Marketing Manager

What’s the secret of online merchandise management? Giving store merchandisers the right tools
e-commerce

What’s the secret of online merchandise management? Giving store merchandisers the right tools

As a successful in-store boutique manager in 1994, you might have had your merchandisers adorn your street-facing storefront ...

Catherine Dee

Search and Discovery writer

New features and capabilities in Algolia InstantSearch
engineering

New features and capabilities in Algolia InstantSearch

At Algolia, our business is more than search and discovery, it’s the continuous improvement of site search. If you ...

Haroen Viaene

JavaScript Library Developer

Feature Spotlight: Analytics
product

Feature Spotlight: Analytics

Analytics brings math and data into the otherwise very subjective world of ecommerce. It helps companies quantify how well their ...

Jaden Baptista

Technical Writer

What is clustering?
ai

What is clustering?

Amid all the momentous developments in the generative AI data space, are you a data scientist struggling to make sense ...

Vincent Caruana

Sr. SEO Web Digital Marketing Manager

What is a vector database?
product

What is a vector database?

Fashion ideas for guest aunt informal summer wedding Funny movie to get my bored high-schoolers off their addictive gaming ...

Vincent Caruana

Sr. SEO Web Digital Marketing Manager

Unlock the power of image-based recommendation with Algolia’s LookingSimilar
engineering

Unlock the power of image-based recommendation with Algolia’s LookingSimilar

Imagine you're visiting an online art gallery and a specific painting catches your eye. You'd like to find ...

Raed Chammam

Senior Software Engineer

Empowering Change: Algolia's Global Giving Days Impact Report
algolia

Empowering Change: Algolia's Global Giving Days Impact Report

At Algolia, our commitment to making a positive impact extends far beyond the digital landscape. We believe in the power ...

Amy Ciba

Senior Manager, People Success

Retail personalization: Give your ecommerce customers the tailored shopping experiences they expect and deserve
e-commerce

Retail personalization: Give your ecommerce customers the tailored shopping experiences they expect and deserve

In today’s post-pandemic-yet-still-super-competitive retail landscape, gaining, keeping, and converting ecommerce customers is no easy ...

Vincent Caruana

Sr. SEO Web Digital Marketing Manager

Algolia x eTail | A busy few days in Boston
algolia

Algolia x eTail | A busy few days in Boston

There are few atmospheres as unique as that of a conference exhibit hall: the air always filled with an indescribable ...

Marissa Wharton

Marketing Content Manager

What are vectors and how do they apply to machine learning?
ai

What are vectors and how do they apply to machine learning?

To consider the question of what vectors are, it helps to be a mathematician, or at least someone who’s ...

Catherine Dee

Search and Discovery writer

Why imports are important in JS
engineering

Why imports are important in JS

My first foray into programming was writing Python on a Raspberry Pi to flicker some LED lights — it wasn’t ...

Jaden Baptista

Technical Writer

What is ecommerce? The complete guide
e-commerce

What is ecommerce? The complete guide

How well do you know the world of modern ecommerce?  With retail ecommerce sales having exceeded $5.7 trillion worldwide ...

Vincent Caruana

Sr. SEO Web Digital Marketing Manager

Data is king: The role of data capture and integrity in embracing AI
ai

Data is king: The role of data capture and integrity in embracing AI

In a world of artificial intelligence (AI), data serves as the foundation for machine learning (ML) models to identify trends ...

Alexandra Anghel

Director of AI Engineering

What are data privacy and data security? Why are they  critical for an organization?
product

What are data privacy and data security? Why are they critical for an organization?

Imagine you’re a leading healthcare provider that performs extensive data collection as part of your patient management. You’re ...

Catherine Dee

Search and Discovery writer

Achieving digital excellence: Algolia's insights from the GDS Retail Digital Summit
e-commerce

Achieving digital excellence: Algolia's insights from the GDS Retail Digital Summit

In an era where customer experience reigns supreme, achieving digital excellence is a worthy goal for retail leaders. But what ...

Marissa Wharton

Marketing Content Manager

AI at scale: Managing ML models over time & across use cases
ai

AI at scale: Managing ML models over time & across use cases

Just a few years ago it would have required considerable resources to build a new AI service from scratch. Of ...

Benoit Perrot

VP, Engineering

Looking for something?

facebookfacebooklinkedinlinkedintwittertwittermailmail

We invited our friends at Starschema to write about an example of using Algolia in combination with MongoDB. We hope that you enjoy this four-part series by Full Stack Engineer Soma Osvay.

If you’d like to look back, here are the other links:

Part 1 – Use-case, architecture, and current challenges

Part 2 – Proposed solution and design

Part 3 – Data pipeline implementation


In this post, I will implement the frontend that will consume the Algolia index we created in part 3 of this series. The created web application is available here: https://algolia-listings.starschema.com/. You can try it out with our sample data by default, but if you’ve been following along and experimenting with the format we used in the last article, you can hook up your own index! The code of the application is available on GitHub. A public demo is hosted on StackBlitz.

Step 0. Planning

The frontend of our existing consumer-facing application is written with jQuery and vanilla JavaScript, so I need to make sure that the Algolia sample application that I am developing is compatible with those technologies. Thankfully, Algolia’s InstantSearch.js is compatible with vanilla frontends without any customization, so I am able to use the default sample implementation in the Algolia documentation. Before starting, I drew up a quick sketch of what I wanted to create with the Algolia search UI. I took our existing search page as a baseline and extended it with a few extra features that we’re currently missing:

Frontend wireframe design

I used the official Algolia Getting started guide to set up my project and start coding. The npx create-instantsearch-app created a very well-prepared and well-structured application that I could modify to match my use-case.

Before starting the Algolia specific development, I had to make sure that my Algolia app ID and API key aren’t hard coded in my application so I can share the source code easily. To do this, we created a form that asks for your Algolia credentials and stores them in the browser localStorage to use in queries.

Demo application screenshot

Step 1. Modify HTML and CSS

First, I had to change the layout of the generated index.html file that was created along with the project. This is because I wanted to have a different search layout than Algolia originally created for me based on my UI plans. After a few iterations, I actually deviated from my original plan: I added a Clear Refinements button on the top of the filter section, scrapped pagination because I realized Algolia supports Infinite Scrolling, and I decided to implement GeoSearch (so that our end users can search by location in addition to text). My updated Algolia-specific HTML and CSS looks like this:

<!--Used to host the Algolia search UI-->
<div id="algolia-container">
	<!-- The search box. Located on the top of the page, spanning the entire width -->
	<div id="searchbox"></div>
	<!-- The filters section, located on the left -->
	<div class="filters">
		<h2>Filters</h2>
		<!-- Clear filters button location -->
		<div id="clear-refinements"></div>
		<!-- Country filter location -->
		<h3>Country</h3>
		<div id="country-list"></div>
		<!-- Property Types filter location -->
		<h3>Property Types</h3>
		<div id="property-list"></div>
		<!-- Review scores filter location -->
		<h3>Review Scores</h3>
		<div id="review-scores"></div>
		<!-- Price filter location -->
		<h3>Price</h3>
		<div id="price"></div>
		<!-- Cleaning fee filter location -->
		<h3>Cleaning Fee</h3>
		<div id="cleaning-fee"></div>
	</div>
	<!-- The results panel, located to the right side from the filters -->
	<div class="results">
		<h2>Results</h2>
		<!-- The pagination container, which was later changed to infinite scroll results container -->
		<div class="pagination-container">
			<!-- The container which displays the number of results, and a link which can load the next set of results. These are modified from js -->
			<div id="result-count">
				<span></span>
				<a href="#"></a>
			</div>
			<!-- The location of the control that controls how many results are loaded at once -->
			<div id="per-page"></div>
		</div>
		<!-- The location for the map which shows the results on the world map -->
		<div id="map-display">
			<h3>Map</h3>
			<div id="geo-search"></div>
		</div>
		<!-- The location of the search result details -->
		<div id="details-display">
			<h3>Details</h3>
			<div id="hits"></div>
		</div>
	</div>
</div>

Algolia’s InstantSearch.js is able to create its own controls automatically, so I just have to provide the layout itself.

I also put a little effort into making this look nice with some CSS:

#algolia-container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 1rem;
    display: grid;
    grid-template-columns: 200px 1fr;
    grid-template-rows: auto auto;
    gap: 20px;
}
 
#searchbox {
    grid-column: 1 / 3;
    grid-row: 1;
}
.filters {
    grid-row: 2;
    grid-column: 1;
}
.results {
    grid-row: 2;
    grid-column: 2;
}
.pagination-container {
    display: grid;
    grid-template-columns: 1fr auto auto;
    gap: 20px;
}
 
.ais-GeoSearch-map {
    height: 500px; /* You can change this height */
}

Step 2. Initialize Algolia InstantSearch.js

Next, I initialized the Algolia JS engine that will query my index and display the results.

const {
	algoliasearch,
	instantsearch
} = window;

// Initialize the Algolia Search client and connect to our index
const searchClient = algoliasearch(appId, searchKey);
const search = instantsearch({
	indexName: indexName,
	routing: true,
	searchClient,
});

Step 3. Add widgets

Algolia has designed their frontend functionality into “widgets”, UI components that you can dynamically hydrate empty HTML nodes with. Algolia uses these to add a search box, a filtering and faceting interface, infinite scroll, and many other functionalities. We can add widgets by calling addWidgets and providing the required widgets as an array.

search.addWidgets([
	// The widget definitions go here
]);

I’m going to step through all the widgets I used, but just keep in mind that the following code samples all take place inside that array parameter to addWidgets.

  1. Searchbox. This will add the basic search bar to the page.
    instantsearch.widgets.searchBox({
    	container: '#searchbox',
    	placeholder: 'Search real-estate listings',
    	autofocus: true
    })
    
  2. InfiniteHits. This is where our search results will populate. I used InfiniteHits instead of just Hits to enable infinite scrolling.
    instantsearch.widgets.infiniteHits({
    	container: '#hits',
    	templates: {
    		// Item template will be filled out later
    		item: `Sample item template`
    	}
    })
    

    This control will contain the item template, which is a piece of HTML code that displays the individual search result. I’ll come back to this — right now there’s just a placeholder there.

  3. Hits per page. This widget allows the user to select the number of items to load at a time.
    instantsearch.widgets.hitsPerPage({
    	container: '#per-page',
    	items: [{
    			label: 'Load 5 results per page',
    			value: 5
    		},
    		{
    			label: 'Load 10 results per page',
    			value: 10
    		},
    		{
    			label: 'Load 20 results per page',
    			value: 20
    		},
    		{
    			label: 'Load 50 results per page',
    			value: 50,
    			default: true
    		},
    		{
    			label: 'Load 100 results per page',
    			value: 100
    		},
    		{
    			label: 'Load 200 results per page',
    			value: 200
    		}
    	]
    })
    
  4. Clear Filters button. The user can press this button to clear all refinements.
    instantsearch.widgets.clearRefinements({
    	container: '#clear-refinements',
    	templates: {
    		resetLabel: 'Clear filters',
    	},
    })
    
  5. A Refinement list for property type and country filter. This provides checkboxes that allow users to filter for results that are of specific property types and are located in specific countries.
    instantsearch.widgets.refinementList({
      container: '#property-list',
      attribute: 'property_type'
    }),
    instantsearch.widgets.refinementList({
      container: '#country-list',
      attribute: 'address.country'
    })
    
  6. A Rating menu for filtering for listings of certain ratings. I originally wanted to create a simple radio button menu for this, but I realized that Algolia supports this kind of control out-of-the-box.
    instantsearch.widgets.ratingMenu({
    	container: '#review-scores',
    	attribute: 'scores.stars'
    })
    
  7. Range sliders for a listing’s price and cleaning fee. Originally, I wanted text inputs clamped to a certain range, but I found that sliders are more intuitive to use.
    instantsearch.widgets.rangeSlider({
    	container: '#price',
    	attribute: 'price',
    	precision: 10
    }),
    instantsearch.widgets.rangeSlider({
    	container: '#cleaning-fee',
    	attribute: 'cleaning_fee',
    	precision: 5
    })
    
  8. Map widget for displaying results on the world map. I also added a click event for the markers on the map, which I will later implement to scroll to the clicked listing’s details.
    instantsearch.widgets.geoSearch({
    	container: '#geo-search',
    	googleReference: window.google,
    	initialPosition: {
    		lat: 48.864716,
    		lng: 2.349014,
    	},
    	initialZoom: 10,
    	builtInMarker: {
    		createOptions(item) {
    			return {
    				title: item.name,
    			};
    		},
    		events: {
    			click({
    				event,
    				item,
    				marker,
    				map
    			}) {
    				// to be implemented later
    			},
    		},
    	},
    })
    
  9. I also added a custom connector for infinite hits. Custom connectors let you hijack the functionality of a widget but provide your own HTML, so it’s entirely customizable and dynamic. The reason that I went this route is that Algolia didn’t provide an existing widget to show the result information exactly the way I wanted to due to the layout of our existing search page. Essentially, I give the array of widgets my own custom widget name like this:
    customInfiniteHits({})
    

    Then, outside of the widget array, I create a custom function that runs when the hits change and returns new HTML for the hit list. I configured it to have customized views when there are no search results for the current geo-search or when there are no search results at all. When there are results, it displays the result count and allows the user to request that the next page of results be appended to the bottom of the current page.

    // Define custom logic that runs when the results changed.
    // This will call a function that displays the total result count and allows the user to Load more or clear filters if needed.
    // The hitsChanged method is defined below to keep the initialization code clean.
    // Documentation: <https://www.algolia.com/doc/api-reference/widgets/infinite-hits/js/>
    const renderInfiniteHits = hitsChanged;
    const customInfiniteHits = instantsearch.connectors.connectInfiniteHits(
    	renderInfiniteHits
    );
    // This function is called every time the search results change
    // It checks how many results there are in total and either:
    // - displays a 'No results found' message to the user along with the possibility to Clear Filters. It also hides the result container and possibly the map too
    // - displays information about how many total results there are, and how many are currently displayed. It also allows the users to click a 'Load more' button on the top of the page.
    function hitsChanged(renderOptions) {
    	// if this is an initial render and we got no results object, skip
    	if (!renderOptions.results) {
    		return;
    	}
    	// get the reference for the Result Count elements on the UI (its text and link as well)
    	const resultCountElement = document.getElementById('result-count');
    	const textEl = resultCountElement.querySelector('span');
    	const linkEl = resultCountElement.querySelector('a');
    	// check if we have any results
    	const hasHits = renderOptions.results.nbHits !== 0;
    	// check if we have any search query
    	const hasQuery = !!renderOptions.results.query;
    	// check if we have any geo bounding box (query made on map)
    	const hasGeoQuery = !!renderOptions.results._state.insideBoundingBox;
    	// We show/hide result Details depending if we have results or not
    	document.getElementById('details-display').style.display = hasHits ? 'block' : 'none';
    	// We hide the Map display if we have no results AND there was no map query applied (so the query can be undone)
    	document.getElementById('map-display').style.display = hasHits || hasGeoQuery ? 'block' : 'none';
    	// Update the Result count container to display information about results
    	if (hasHits) {
    		// if there are any results
    		if (renderOptions.isLastPage) {
    			// if we are on last page, show text and a link to clear filters
    			textEl.innerText = `Showing all ${renderOptions.hits.length} results`;
    			linkEl.style.display = 'none';
    			linkEl.innerText = 'Clear all filters';
    			linkEl.href = '.';
    			linkEl.style.display = 'inline';
    			linkEl.onclick = null;
    		} else {
    			// if we are not on last page, show text and link to load more items
    			textEl.innerText = `Showing top ${renderOptions.hits.length} results of ${renderOptions.results.nbHits}`;
    			linkEl.href = '';
    			linkEl.innerText = 'Load more';
    			linkEl.style.display = 'inline';
    			linkEl.href = "#";
    			linkEl.onclick = () => {
    				renderOptions.showMore();
    				return false;
    			};
    		}
    	} else {
    		// if we have no results, construct message
    		let statusMessage = 'No results have been found';
    		if (hasQuery) {
    			statusMessage += ` for '${renderOptions.results.query}'`;
    		}
    		if (hasGeoQuery) {
    			statusMessage += ' in selected map area';
    		}
    		// show message and link to clear filters
    		textEl.innerText = statusMessage
    		linkEl.innerText = 'Clear all filters';
    		linkEl.href = '.';
    		linkEl.style.display = 'inline';
    		linkEl.onclick = null;
    	}
    }
    

After adding my widgets, the UI looked like the following:

Demo application UI with new widgets

Step 4. Modify the item template

When adding the widgets, I left the search result template empty, so the item details were not yet displayed properly. I changed the InfiniteHits widget configuration to this:

instantsearch.widgets.infiniteHits({
  container: '#hits',
  templates: {
    // We use no 'empty' template, as our results container will be hidden if there are no results.
    // The item template is heavily modified to draw the details of a listing in detail
    item: `
      <article id="hit-{{objectID}}">
        <div class="name-container">
          <h1 class="name">{{#helpers.highlight}}{ "attribute": "name" }{{/helpers.highlight}}</h1>
          {{#scores}}
            <div class="stars">
              <svg aria-hidden="true">
                {{#scores.has_one}}
                  <use xlink:href="#ais-RatingMenu-starSymbol"></use>
                {{/scores.has_one}}
                {{^scores.has_one}}
                  <use xlink:href="#ais-RatingMenu-starEmptySymbol"></use>
                {{/scores.has_one}}
              </svg>
              <svg aria-hidden="true">
                {{#scores.has_two}}
                  <use xlink:href="#ais-RatingMenu-starSymbol"></use>
                {{/scores.has_two}}
                {{^scores.has_two}}
                  <use xlink:href="#ais-RatingMenu-starEmptySymbol"></use>
                {{/scores.has_two}}
              </svg>
              <svg aria-hidden="true">
                {{#scores.has_three}}
                  <use xlink:href="#ais-RatingMenu-starSymbol"></use>
                {{/scores.has_three}}
                {{^scores.has_three}}
                  <use xlink:href="#ais-RatingMenu-starEmptySymbol"></use>
                {{/scores.has_three}}
              </svg>
              <svg aria-hidden="true">
                {{#scores.has_four}}
                  <use xlink:href="#ais-RatingMenu-starSymbol"></use>
                {{/scores.has_four}}
                {{^scores.has_four}}
                  <use xlink:href="#ais-RatingMenu-starEmptySymbol"></use>
                {{/scores.has_four}}
              </svg>
              <svg aria-hidden="true">
                {{#scores.has_five}}
                  <use xlink:href="#ais-RatingMenu-starSymbol"></use>
                {{/scores.has_five}}
                {{^scores.has_five}}
                  <use xlink:href="#ais-RatingMenu-starEmptySymbol"></use>
                {{/scores.has_five}}
              </svg>
            </div>
          {{/scores}}
        </div>
        {{#description}}
          <div class="description">
            <div class="title">Description{{}}</div>
            <p class="desc">{{#helpers.highlight}}{ "attribute": "description" }{{/helpers.highlight}}</p>
          </div>
        {{/description}}
        {{#summary}}
          <div class="summary">
            <div class="title">Summary</div>
            <p class="desc">{{#helpers.highlight}}{ "attribute": "summary" }{{/helpers.highlight}}</p>
          </div>
        {{/summary}}
        {{#space}}
          <div class="space">
            <div class="title">Space</div>
            <p class="desc">{{#helpers.highlight}}{ "attribute": "space" }{{/helpers.highlight}}</p>
          </div>
        {{/space}}
        {{#neighborhood}}
          <div class="neigh">
            <div class="title">Neighborhood</div>
            <p class="desc">{{#helpers.highlight}}{ "attribute": "neighborhood_overview" }{{/helpers.highlight}}</p>
          </div>
        {{/neighborhood}}
        {{#transit}}
          <div class="transit">
            <div class="title">Transit</div>
            <p class="desc">{{#helpers.highlight}}{ "attribute": "transit" }{{/helpers.highlight}}</p>
          </div>
        {{/transit}}
        <div class="info">
          {{#property_type}}
            <div>
              <span class="title">Property Type:</span>
              <span>{{property_type}}</span>
            </div>
          {{/property_type}}
          {{#address}}
            <div>
              <span class="title">Address:</span>
              <span>{{#helpers.highlight}}{ "attribute": "address.street" }{{/helpers.highlight}}</span>
            </div>
          {{/address}}
          {{#price}}
            <div>
              <span class="title">Price:</span>
              <b>{{price}}$ per night</b>
              {{#cleaning_fee}}
                <span> + {{cleaning_fee}}$ cleaning fee</span>
              {{/cleaning_fee}}
              {{#security_deposit}}
                <span> + {{security_deposit}}$ security deposit</span>
              {{/security_deposit}}
            </div>
          {{/price}}
          {{#accommodates}}
            <div>
              <span class="title">Accommodates:</span>
              <b>{{accommodates}} people</b>
              {{#bedrooms}}
                <span> in {{bedrooms}} bedroom(s)</span>
              {{/bedrooms}}
              {{#beds}}
                <span>, {{beds}} bed(s)</span>
              {{/beds}}
              {{#bathrooms}}
                <span> with {{bathrooms}} bathroom(s)</span>
              {{/bathrooms}}
            </div>
          {{/accommodates}}
        </div>
        {{#images.picture_url}}
          <img class="image" src="{{images.picture_url}}">
        {{/images.picture_url}}
      </article>
		`
  }
})

The Algolia item template uses Mustache for adding variables. It is important to add the variables as attributesToRetrieve when you are creating the index so that they are present in the code when Algolia constructs the item’s HTML. I also added the following CSS to display the items properly:

article {
    display: grid;
    width: 100%;
    grid-template-columns: 1fr 400px;
    column-gap: 20px;
    grid-template-rows: auto auto auto auto auto auto auto 1fr;
}
 
article .title {
    margin-top: 8px;
    font-size: 14px;
    color: gray;
}
article p {
    display: block;
    margin: 0px;
}
 
article .name-container {
    grid-row: 1;
    grid-column: 1 / 3;
}
article .name-container > * {
    display: inline-block;
    vertical-align: middle;
}
 
.stars {
    margin-left: 8px;
    height: 24px;
}
.stars svg {
    width: 24px;
    height: 24px;
    display: inline-block;
    fill: yellowgreen;
}
 
article .description {
    grid-row: 2;
    grid-column: 1;
}
article .summary {
    grid-row: 3;
    grid-column: 1;
}
article .space {
    grid-row: 4;
    grid-column: 1;
}
article .neigh {
    grid-row: 5;
    grid-column: 1;
}
article .transit {
    grid-row: 6;
    grid-column: 1;
}
article .info {
    grid-row: 7;
    grid-column: 1;
}
article .info > * {
    margin-top: 8px;
}
article .image {
    grid-column: 2;
    grid-row: 2 / 9;
    margin-top: 8px;
    width: 100%;
}
article .properties {
    display: grid;
    grid-template-columns: auto auto;
    gap: 4px;
    grid-auto-flow: column;
    width: fit-content;
}
article .properties .key {
    color: gray;
    font-size: 12px;
}
article .properties .value {
    font-size: 12px;
}

And now the search results look like this:

Demo application UI final search results

Lessons learned

Overall, I found that the Algolia InstantSearch.js framework provides an incredibly flexible way of creating your own search interfaces in your web applications. The UI building feels smooth, and the widget system is a wonderful tool to build good-looking interfaces very quickly. Using the custom connectors, I also realized that Algolia can fit into more complex use-cases as well, which require a more customized approach. The generated HTML can be styled easily to look much different than the prototype.

My entire Algolia frontend implementation was a few hundred lines of code, compared to the thousands of lines I would have had to write if I was going to implement this kind of capability myself. Most of the code was taken up by my custom generalization and connector logic, and Algolia let me tie all of those complex features in with the default InstantSearch.js widgets with just a few commands.

The searching is astonishingly fast, the index outperforms my expectations by quite a bit. The average search or filter action shows a result within 60ms, much quicker than our usual expectation of a whole second.

Overall conclusion

During this proof of concept, I found that:

  • The search speed and accuracy of Algolia outperforms any existing solutions I have seen so far.
  • The Algolia index has a straightforward construction, not requiring deep technical knowledge.
  • Search priorities, rankings, geo-searching, and other attributes are customizable and don’t require extensive maintenance.
  • The Algolia search index seamlessly integrates into our existing data pipeline. It also exposes a great Python API, so the scripts can be written and maintained by our Python-loving data engineers.
  • The Algolia frontend SDKs are very well-documented. I showed my application to some of our frontend developers and after checking the code, they were very excited about using InstantSearch.js themselves.
  • Since Algolia is cloud-hosted, it keeps our infrastructure team happy, as there is no need to introduce another system into our environment. It scales automatically and the SLAs offered match our requirements.
  • We don’t have to modify our application backend at all, which saves us a lot of time and cost.

Based on these findings, I will definitely recommend to my team that we use Algolia in production.

About the author
Soma Osvay

Full Stack Engineer, Starschema

Recommended Articles

Powered byAlgolia Algolia Recommend

Creating an omnibar with Autocomplete
engineering

Bryan Robinson

Senior Developer Relations Specialist

Add Autocomplete search to your Strapi CMS
engineering

Chuck Meyer

Sr. Developer Relations Engineer

Build a React app with fast indexing and instant inventory updates
engineering

Julia Seidman

Developer Educator