• Stars
    star
    398
  • Rank 108,325 (Top 3 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 11 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

AlgoliaSearch integration to your favorite ORM

Algolia for Rails

The perfect starting point to integrate Algolia within your Rails project

CircleCI Gem Version Code Climate ActiveRecord Mongoid Sequel

DocumentationCommunity ForumStack OverflowReport a bugFAQSupport

This gem let you easily integrate the Algolia Search API to your favorite ORM. It's based on the algoliasearch-client-ruby gem. Rails 5.x and 6.x are supported.

You might be interested in the sample Ruby on Rails application providing a autocomplete.js-based auto-completion and InstantSearch.js-based instant search results page: algoliasearch-rails-example.

API Documentation

You can find the full reference on Algolia's website.

  1. Setup

  2. Usage

  3. Options

  4. Indices

  5. Testing

  6. Troubleshooting

Setup

Install

gem install algoliasearch-rails

Add the gem to your Gemfile:

gem "algoliasearch-rails"

And run:

bundle install

Configuration

Create a new file config/initializers/algoliasearch.rb to setup your APPLICATION_ID and API_KEY.

AlgoliaSearch.configuration = { application_id: 'YourApplicationID', api_key: 'YourAPIKey' }

The gem is compatible with ActiveRecord, Mongoid and Sequel.

Timeouts

You can configure a various timeout thresholds by setting the following options at initialization time:

AlgoliaSearch.configuration = {
  application_id: 'YourApplicationID',
  api_key: 'YourAPIKey',
  connect_timeout: 2,
  receive_timeout: 30,
  send_timeout: 30,
  batch_timeout: 120,
  search_timeout: 5
}

Notes

This gem makes extensive use of Rails' callbacks to trigger the indexing tasks. If you're using methods bypassing after_validation, before_save or after_commit callbacks, it will not index your changes. For example: update_attribute doesn't perform validations checks, to perform validations when updating use update_attributes.

All methods injected by the AlgoliaSearch module are prefixed by algolia_ and aliased to the associated short names if they aren't already defined.

Contact.algolia_reindex! # <=> Contact.reindex!

Contact.algolia_search("jon doe") # <=> Contact.search("jon doe")

Usage

Index Schema

The following code will create a Contact index and add search capabilities to your Contact model:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    attributes :first_name, :last_name, :email
  end
end

You can either specify the attributes to send (here we restricted to :first_name, :last_name, :email) or not (in that case, all attributes are sent).

class Product < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    # all attributes will be sent
  end
end

You can also use the add_attribute method, to send all model attributes + extra ones:

class Product < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    # all attributes + extra_attr will be sent
    add_attribute :extra_attr
  end

  def extra_attr
    "extra_val"
  end
end

Relevancy

We provide many ways to configure your index allowing you to tune your overall index relevancy. The most important ones are the searchable attributes and the attributes reflecting record popularity.

class Product < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    # list of attribute used to build an Algolia record
    attributes :title, :subtitle, :description, :likes_count, :seller_name

    # the `searchableAttributes` (formerly known as attributesToIndex) setting defines the attributes
    # you want to search in: here `title`, `subtitle` & `description`.
    # You need to list them by order of importance. `description` is tagged as
    # `unordered` to avoid taking the position of a match into account in that attribute.
    searchableAttributes ['title', 'subtitle', 'unordered(description)']

    # the `customRanking` setting defines the ranking criteria use to compare two matching
    # records in case their text-relevance is equal. It should reflect your record popularity.
    customRanking ['desc(likes_count)']
  end

end

Indexing

To index a model, simple call reindex on the class:

Product.reindex

To index all of your models, you can do something like this:

Rails.application.eager_load! # Ensure all models are loaded (required in development).

algolia_models = ActiveRecord::Base.descendants.select{ |model| model.respond_to?(:reindex) }

algolia_models.each(&:reindex)

Frontend Search (realtime experience)

Traditional search implementations tend to have search logic and functionality on the backend. This made sense when the search experience consisted of a user entering a search query, executing that search, and then being redirected to a search result page.

Implementing search on the backend is no longer necessary. In fact, in most cases it is harmful to performance because of added network and processing latency. We highly recommend the usage of our JavaScript API Client issuing all search requests directly from the end user's browser, mobile device, or client. It will reduce the overall search latency while offloading your servers at the same time.

The JS API client is part of the gem, just require algolia/v3/algoliasearch.min somewhere in your JavaScript manifest, for example in application.js if you are using Rails 3.1+:

//= require algolia/v3/algoliasearch.min

Then in your JavaScript code you can do:

var client = algoliasearch(ApplicationID, Search-Only-API-Key);
var index = client.initIndex('YourIndexName');
index.search('something', { hitsPerPage: 10, page: 0 })
  .then(function searchDone(content) {
    console.log(content)
  })
  .catch(function searchFailure(err) {
    console.error(err);
  });

We recently (March 2015) released a new version (V3) of our JavaScript client, if you were using our previous version (V2), read the migration guide

Backend Search

Notes: We recommend the usage of our JavaScript API Client to perform queries directly from the end-user browser without going through your server.

A search returns ORM-compliant objects reloading them from your database. We recommend the usage of our JavaScript API Client to perform queries to decrease the overall latency and offload your servers.

hits =  Contact.search("jon doe")
p hits
p hits.raw_answer # to get the original JSON raw answer

A highlight_result attribute is added to each ORM object:

hits[0].highlight_result['first_name']['value']

If you want to retrieve the raw JSON answer from the API, without re-loading the objects from the database, you can use:

json_answer = Contact.raw_search("jon doe")
p json_answer
p json_answer['hits']
p json_answer['facets']

Search parameters can be specified either through the index's settings statically in your model or dynamically at search time specifying search parameters as second argument of the search method:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    attribute :first_name, :last_name, :email

    # default search parameters stored in the index settings
    minWordSizefor1Typo 4
    minWordSizefor2Typos 8
    hitsPerPage 42
  end
end
# dynamical search parameters
p Contact.raw_search('jon doe', { hitsPerPage: 5, page: 2 })

Backend Pagination

Even if we highly recommend to perform all search (and therefore pagination) operations from your frontend using JavaScript, we support both will_paginate and kaminari as pagination backend.

To use :will_paginate, specify the :pagination_backend as follow:

AlgoliaSearch.configuration = { application_id: 'YourApplicationID', api_key: 'YourAPIKey', pagination_backend: :will_paginate }

Then, as soon as you use the search method, the returning results will be a paginated set:

# in your controller
@results = MyModel.search('foo', hitsPerPage: 10)

# in your views
# if using will_paginate
<%= will_paginate @results %>

# if using kaminari
<%= paginate @results %>

Tags

Use the tags method to add tags to your record:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    tags ['trusted']
  end
end

or using dynamical values:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    tags do
      [first_name.blank? || last_name.blank? ? 'partial' : 'full', has_valid_email? ? 'valid_email' : 'invalid_email']
    end
  end
end

At query time, specify { tagFilters: 'tagvalue' } or { tagFilters: ['tagvalue1', 'tagvalue2'] } as search parameters to restrict the result set to specific tags.

Faceting

Facets can be retrieved calling the extra facets method of the search answer.

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    # [...]

    # specify the list of attributes available for faceting
    attributesForFaceting [:company, :zip_code]
  end
end
hits = Contact.search('jon doe', { facets: '*' })
p hits                    # ORM-compliant array of objects
p hits.facets             # extra method added to retrieve facets
p hits.facets['company']  # facet values+count of facet 'company'
p hits.facets['zip_code'] # facet values+count of facet 'zip_code'
raw_json = Contact.raw_search('jon doe', { facets: '*' })
p raw_json['facets']

Faceted search

You can also search for facet values.

Product.search_for_facet_values('category', 'Headphones') # Array of {value, highlighted, count}

This method can also take any parameter a query can take. This will adjust the search to only hits which would have matched the query.

# Only sends back the categories containing red Apple products (and only counts those)
Product.search_for_facet_values('category', 'phone', {
  query: 'red',
  filters: 'brand:Apple'
}) # Array of phone categories linked to red Apple products

Group by

More info on distinct for grouping can be found here.

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    # [...]

    # specify the attribute to be used for distinguishing the records
    # in this case the records will be grouped by company
    attributeForDistinct "company"
  end
end

Geo-Search

Use the geoloc method to localize your record:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    geoloc :lat_attr, :lng_attr
  end
end

At query time, specify { aroundLatLng: "37.33, -121.89", aroundRadius: 50000 } as search parameters to restrict the result set to 50KM around San Jose.

Options

Auto-indexing & asynchronism

Each time a record is saved, it will be asynchronously indexed. On the other hand, each time a record is destroyed, it will be - asynchronously - removed from the index. That means that a network call with the ADD/DELETE operation is sent synchronously to the Algolia API but then the engine will asynchronously process the operation (so if you do a search just after, the results may not reflect it yet).

You can disable auto-indexing and auto-removing setting the following options:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch auto_index: false, auto_remove: false do
    attribute :first_name, :last_name, :email
  end
end

Temporary disable auto-indexing

You can temporary disable auto-indexing using the without_auto_index scope. This is often used for performance reason.

Contact.delete_all
Contact.without_auto_index do
  1.upto(10000) { Contact.create! attributes } # inside this block, auto indexing task will not run.
end
Contact.reindex! # will use batch operations

Queues & background jobs

You can configure the auto-indexing & auto-removal process to use a queue to perform those operations in background. ActiveJob (Rails >=4.2) queues are used by default but you can define your own queuing mechanism:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch enqueue: true do # ActiveJob will be triggered using a `algoliasearch` queue
    attribute :first_name, :last_name, :email
  end
end

Things to Consider

If you are performing updates & deletions in the background then a record deletion can be committed to your database prior to the job actually executing. Thus if you were to load the record to remove it from the database than your ActiveRecord#find will fail with a RecordNotFound.

In this case you can bypass loading the record from ActiveRecord and just communicate with the index directly:

class MySidekiqWorker
  def perform(id, remove)
    if remove
      # the record has likely already been removed from your database so we cannot
      # use ActiveRecord#find to load it
      index = AlgoliaSearch.client.init_index("index_name")
      index.delete_object(id)
    else
      # the record should be present
      c = Contact.find(id)
      c.index!
    end
  end
end

With Sidekiq

If you're using Sidekiq:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch enqueue: :trigger_sidekiq_worker do
    attribute :first_name, :last_name, :email
  end

  def self.trigger_sidekiq_worker(record, remove)
    MySidekiqWorker.perform_async(record.id, remove)
  end
end

class MySidekiqWorker
  def perform(id, remove)
    if remove
      # the record has likely already been removed from your database so we cannot
      # use ActiveRecord#find to load it
      index = AlgoliaSearch.client.init_index("index_name")
      index.delete_object(id)
    else
      # the record should be present
      c = Contact.find(id)
      c.index!
    end
  end
end

With DelayedJob

If you're using delayed_job:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch enqueue: :trigger_delayed_job do
    attribute :first_name, :last_name, :email
  end

  def self.trigger_delayed_job(record, remove)
    if remove
      record.delay.remove_from_index!
    else
      record.delay.index!
    end
  end
end

Synchronism & testing

You can force indexing and removing to be synchronous (in that case the gem will call the wait_task method to ensure the operation has been taken into account once the method returns) by setting the following option: (this is NOT recommended, except for testing purpose)

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch synchronous: true do
    attribute :first_name, :last_name, :email
  end
end

Custom index name

By default, the index name will be the class name, e.g. "Contact". You can customize the index name by using the index_name option:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch index_name: "MyCustomName" do
    attribute :first_name, :last_name, :email
  end
end

Per-environment indices

You can suffix the index name with the current Rails environment using the following option:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch per_environment: true do # index name will be "Contact_#{Rails.env}"
    attribute :first_name, :last_name, :email
  end
end

Custom attribute definition

You can use a block to specify a complex attribute value

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    attribute :email
    attribute :full_name do
      "#{first_name} #{last_name}"
    end
    add_attribute :full_name2
  end

  def full_name2
    "#{first_name} #{last_name}"
  end
end

Notes: As soon as you use such code to define extra attributes, the gem is not anymore able to detect if the attribute has changed (the code uses Rails's #{attribute}_changed? method to detect that). As a consequence, your record will be pushed to the API even if its attributes didn't change. You can work-around this behavior creating a _changed? method:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    attribute :email
    attribute :full_name do
      "#{first_name} #{last_name}"
    end
  end

  def full_name_changed?
    first_name_changed? || last_name_changed?
  end
end

Nested objects/relations

Defining the relationship

You can easily embed nested objects defining an extra attribute returning any JSON-compliant object (an array or a hash or a combination of both).

class Profile < ActiveRecord::Base
  include AlgoliaSearch

  belongs_to :user
  has_many :specializations

  algoliasearch do
    attribute :user do
      # restrict the nested "user" object to its `name` + `email`
      { name: user.name, email: user.email }
    end
    attribute :public_specializations do
      # build an array of public specialization (include only `title` and `another_attr`)
      specializations.select { |s| s.public? }.map do |s|
        { title: s.title, another_attr: s.another_attr }
      end
    end
  end

end

Propagating the change from a nested child

With ActiveRecord

With ActiveRecord, we'll be using touch and after_touch to achieve this.

# app/models/app.rb
class App < ApplicationRecord
  include AlgoliaSearch

  belongs_to :author, class_name: :User
  after_touch :index!

  algoliasearch do
    attribute :title
    attribute :author do
      author.as_json
    end
  end
end

# app/models/user.rb
class User < ApplicationRecord
  # If your association uses belongs_to
  # - use `touch: true`
  # - do not define an `after_save` hook
  has_many :apps, foreign_key: :author_id

  after_save { apps.each(&:touch) }
end

With Sequel

With Sequel, you can use the touch plugin to propagate the changes:

# app/models/app.rb
class App < Sequel::Model
  include AlgoliaSearch

  many_to_one :author, class: :User

  plugin :timestamps
  plugin :touch

  algoliasearch do
    attribute :title
    attribute :author do
      author.to_hash
    end
  end
end

# app/models/user.rb
class User < Sequel::Model
  one_to_many :apps, key: :author_id

  plugin :timestamps
  # Can't use the associations since it won't trigger the after_save
  plugin :touch

  # Define the associations that need to be touched here
  # Less performant, but allows for the after_save hook to trigger
  def touch_associations
    apps.map(&:touch)
  end

  def touch
    super
    touch_associations
  end
end

Custom objectID

By default, the objectID is based on your record's id. You can change this behavior specifying the :id option (be sure to use a uniq field).

class UniqUser < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch id: :uniq_name do
  end
end

Restrict indexing to a subset of your data

You can add constraints controlling if a record must be indexed by using options the :if or :unless options.

It allows you to do conditional indexing on a per document basis.

class Post < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch if: :published?, unless: :deleted? do
  end

  def published?
    # [...]
  end

  def deleted?
    # [...]
  end
end

Notes: As soon as you use those constraints, addObjects and deleteObjects calls will be performed in order to keep the index synced with the DB (The state-less gem doesn't know if the object don't match your constraints anymore or never matched, so we force ADD/DELETE operations to be sent). You can work-around this behavior creating a _changed? method:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch if: :published do
  end

  def published
    # true or false
  end

  def published_changed?
    # return true only if you know that the 'published' state changed
  end
end

You can index a subset of your records using either:

# will generate batch API calls (recommended)
MyModel.where('updated_at > ?', 10.minutes.ago).reindex!

or

MyModel.index_objects MyModel.limit(5)

Sanitizer

You can sanitize all your attributes using the sanitize option. It will strip all HTML tags from your attributes.

class User < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch per_environment: true, sanitize: true do
    attributes :name, :email, :company
  end
end

If you're using Rails 4.2+, you also need to depend on rails-html-sanitizer:

gem 'rails-html-sanitizer'

UTF-8 Encoding

You can force the UTF-8 encoding of all your attributes using the force_utf8_encoding option:

class User < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch force_utf8_encoding: true do
    attributes :name, :email, :company
  end
end

Notes: This option is not compatible with Ruby 1.8

Exceptions

You can disable exceptions that could be raised while trying to reach Algolia's API by using the raise_on_failure option:

class Contact < ActiveRecord::Base
  include AlgoliaSearch

  # only raise exceptions in development env
  algoliasearch raise_on_failure: Rails.env.development? do
    attribute :first_name, :last_name, :email
  end
end

Configuration example

Here is a real-word configuration example (from HN Search):

class Item < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch per_environment: true do
    # the list of attributes sent to Algolia's API
    attribute :created_at, :title, :url, :author, :points, :story_text, :comment_text, :author, :num_comments, :story_id, :story_title

    # integer version of the created_at datetime field, to use numerical filtering
    attribute :created_at_i do
      created_at.to_i
    end

    # `title` is more important than `{story,comment}_text`, `{story,comment}_text` more than `url`, `url` more than `author`
    # btw, do not take into account position in most fields to avoid first word match boost
    searchableAttributes ['unordered(title)', 'unordered(story_text)', 'unordered(comment_text)', 'unordered(url)', 'author']

    # tags used for filtering
    tags do
      [item_type, "author_#{author}", "story_#{story_id}"]
    end

    # use associated number of HN points to sort results (last sort criteria)
    customRanking ['desc(points)', 'desc(num_comments)']

    # google+, $1.5M raises, C#: we love you
    separatorsToIndex '+#$'
  end

  def story_text
    item_type_cd != Item.comment ? text : nil
  end

  def story_title
    comment? && story ? story.title : nil
  end

  def story_url
    comment? && story ? story.url : nil
  end

  def comment_text
    comment? ? text : nil
  end

  def comment?
    item_type_cd == Item.comment
  end

  # [...]
end

Indices

Manual indexing

You can trigger indexing using the index! instance method.

c = Contact.create!(params[:contact])
c.index!

Manual removal

And trigger index removing using the remove_from_index! instance method.

c.remove_from_index!
c.destroy

Reindexing

The gem provides 2 ways to reindex all your objects:

Atomical reindexing

To reindex all your records (taking into account the deleted objects), the reindex class method indices all your objects to a temporary index called <INDEX_NAME>.tmp and moves the temporary index to the final one once everything is indexed (atomically). This is the safest way to reindex all your content.

Contact.reindex

Notes: if you're using an index-specific API key, ensure you're allowing both <INDEX_NAME> and <INDEX_NAME>.tmp.

Warning: You should not use such an atomic reindexing operation while scoping/filtering the model because this operation replaces the entire index, keeping the filtered objects only. ie: Don't do MyModel.where(...).reindex but do MyModel.where(...).reindex! (with the trailing !)!!!

Regular reindexing

To reindex all your objects in place (without temporary index and therefore without deleting removed objects), use the reindex! class method:

Contact.reindex!

Clearing an index

To clear an index, use the clear_index! class method:

Contact.clear_index!

Using the underlying index

You can access the underlying index object by calling the index class method:

index = Contact.index
# index.get_settings, index.partial_update_object, ...

Primary/replica

You can define replica indices using the add_replica method. Use inherit: true on the replica block if you want it to inherit from the primary settings.

class Book < ActiveRecord::Base
  attr_protected

  include AlgoliaSearch

  algoliasearch per_environment: true do
    searchableAttributes [:name, :author, :editor]

    # define a replica index to search by `author` only
    add_replica 'Book_by_author', per_environment: true do
      searchableAttributes [:author]
    end

    # define a replica index with custom ordering but same settings than the main block
    add_replica 'Book_custom_order', inherit: true, per_environment: true do
      customRanking ['asc(rank)']
    end
  end

end

To search using a replica, use the following code:

Book.raw_search 'foo bar', replica: 'Book_by_editor'
# or
Book.search 'foo bar', replica: 'Book_by_editor'

Share a single index

It can make sense to share an index between several models. In order to implement that, you'll need to ensure you don't have any conflict with the objectID of the underlying models.

class Student < ActiveRecord::Base
  attr_protected

  include AlgoliaSearch

  algoliasearch index_name: 'people', id: :algolia_id do
    # [...]
  end

  private
  def algolia_id
    "student_#{id}" # ensure the teacher & student IDs are not conflicting
  end
end

class Teacher < ActiveRecord::Base
  attr_protected

  include AlgoliaSearch

  algoliasearch index_name: 'people', id: :algolia_id do
    # [...]
  end

  private
  def algolia_id
    "teacher_#{id}" # ensure the teacher & student IDs are not conflicting
  end
end

Notes: If you target a single index from several models, you must never use MyModel.reindex and only use MyModel.reindex!. The reindex method uses a temporary index to perform an atomic reindexing: if you use it, the resulting index will only contain records for the current model because it will not reindex the others.

Target multiple indices

You can index a record in several indices using the add_index method:

class Book < ActiveRecord::Base
  attr_protected

  include AlgoliaSearch

  PUBLIC_INDEX_NAME  = "Book_#{Rails.env}"
  SECURED_INDEX_NAME = "SecuredBook_#{Rails.env}"

  # store all books in index 'SECURED_INDEX_NAME'
  algoliasearch index_name: SECURED_INDEX_NAME do
    searchableAttributes [:name, :author]
    # convert security to tags
    tags do
      [released ? 'public' : 'private', premium ? 'premium' : 'standard']
    end

    # store all 'public' (released and not premium) books in index 'PUBLIC_INDEX_NAME'
    add_index PUBLIC_INDEX_NAME, if: :public? do
      searchableAttributes [:name, :author]
    end
  end

  private
  def public?
    released && !premium
  end

end

To search using an extra index, use the following code:

Book.raw_search 'foo bar', index: 'Book_by_editor'
# or
Book.search 'foo bar', index: 'Book_by_editor'

Testing

Notes

To run the specs, please set the ALGOLIA_APPLICATION_ID and ALGOLIA_API_KEY environment variables. Since the tests are creating and removing indices, DO NOT use your production account.

You may want to disable all indexing (add, update & delete operations) API calls, you can set the disable_indexing option:

class User < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch per_environment: true, disable_indexing: Rails.env.test? do
  end
end

class User < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch per_environment: true, disable_indexing: Proc.new { Rails.env.test? || more_complex_condition } do
  end
end

❓ Troubleshooting

Encountering an issue? Before reaching out to support, we recommend heading to our FAQ where you will find answers for the most common issues and gotchas with the client.

Use the Dockerfile

If you want to contribute to this project without installing all its dependencies, you can use our Docker image. Please check our dedicated guide to learn more.

More Repositories

1

places

🌐 Turn any <input> into an address autocomplete
JavaScript
5,372
star
2

autocomplete

🔮 Fast and full-featured autocomplete library
TypeScript
5,047
star
3

docsearch

📘 The easiest way to add search to your documentation.
TypeScript
3,980
star
4

instantsearch

⚡️ Libraries for building performant and instant search and recommend experiences with Algolia. Compatible with JavaScript, TypeScript, React and Vue.
TypeScript
3,700
star
5

react-instantsearch

⚡️ Lightning-fast search for React and React Native applications, by Algolia.
TypeScript
1,969
star
6

algoliasearch-client-javascript

⚡️ A fully-featured and blazing-fast JavaScript API client to interact with Algolia.
TypeScript
1,259
star
7

github-awesome-autocomplete

:octocat: Add instant search capabilities to GitHub's search bar
JavaScript
1,062
star
8

vue-instantsearch

👀 Algolia components for building search UIs with Vue.js
JavaScript
854
star
9

shipjs

Take control of what is going to be your next release.
JavaScript
749
star
10

awesome-algolia

🔍👋 START HERE! A curated list of Algolia libraries, resources and projects.
696
star
11

algoliasearch-client-php

⚡️ A fully-featured and blazing-fast PHP API client to interact with Algolia.
PHP
670
star
12

instantsearch-ios

⚡️ A library of widgets and helpers to build instant-search applications on iOS.
Swift
573
star
13

voice-overlay-ios

🗣 An overlay that gets your user’s voice permission and input as text in a customizable UI
Swift
544
star
14

sup3rS3cretMes5age

Simple to use, simple to deploy, one time self destruct messaging service, with hashicorp vault as a backend
Go
506
star
15

react-element-to-jsx-string

Turn a ReactElement into the corresponding JSX string
JavaScript
490
star
16

hn-search

Hacker News Search
TypeScript
489
star
17

docsearch-configs

DocSearch - Configurations
JavaScript
455
star
18

expect-jsx

✅ toEqualJSX for expect assertion library
JavaScript
410
star
19

scout-extended

Scout Extended: The Full Power of Algolia in Laravel
PHP
382
star
20

algoliasearch-wordpress

❌🗑🙅‍♂️ Algolia Search plugin for WordPress is no longer supported. Please use our API client guide instead
JavaScript
360
star
21

docsearch-scraper

DocSearch - Scraper
Python
298
star
22

color-extractor

Extract the dominant color(s) of your fashion articles!
Python
271
star
23

algoliasearch-netlify

Official Algolia Plugin for Netlify. Index your website to Algolia when deploying your project to Netlify with the Algolia Crawler
TypeScript
260
star
24

angular-instantsearch

⚡️Lightning-fast search for Angular apps, by Algolia
TypeScript
255
star
25

voice-overlay-android

🗣 An overlay that gets your user’s voice permission and input as text in a customizable UI
Kotlin
253
star
26

algoliasearch-laravel

[Deprecated] We now recommend using Laravel Scout, see =>
PHP
238
star
27

jekyll-algolia

Add fast and relevant search to your Jekyll site
Ruby
214
star
28

algoliasearch-client-swift

⚡️ A fully-featured and blazing-fast Swift API client to interact with Algolia.
Swift
203
star
29

algoliasearch-client-python

⚡️ A fully-featured and blazing-fast Python API client to interact with Algolia.
Python
194
star
30

algoliasearch-client-go

⚡️ A fully-featured and blazing-fast Go API client to interact with Algolia.
Go
193
star
31

search-bundle

Seamless integration of Algolia Search into your Symfony project.
PHP
190
star
32

atom-autocomplete-module-import

⚛️ Search & install npm packages from import/require statements.
JavaScript
182
star
33

gatsby-plugin-algolia

A plugin to push to Algolia based on graphQl queries
JavaScript
176
star
34

algoliasearch-helper-js

Helper for implementing advanced search features with Algolia
JavaScript
174
star
35

datasets

Interesting datasets you could use with Algolia
173
star
36

youtube-captions-scraper

Fetch youtube user submitted or fallback to auto-generated captions
JavaScript
173
star
37

pwa-ecom-ui-template

React/Next.js based starter kit, focused on delivering a rich Search & Discovery e-commerce experience.
TypeScript
172
star
38

algoliasearch-django

Seamless integration of Algolia into your Django project.
Python
167
star
39

algoliasearch-client-ruby

⚡️ A fully-featured and blazing-fast Ruby API client to interact with Algolia.
Ruby
166
star
40

algoliasearch-magento-2

Algolia Search integration for Magento 2 - compatible with versions from 2.3.x to 2.4.x
PHP
156
star
41

instantsearch-android

A library of widgets and helpers to build instant-search applications on Android.
Kotlin
153
star
42

instant-search-demo

Instant-search demo (facets, sliders, paginations & more)
CSS
140
star
43

npm-search

🗿 npm ↔️ Algolia replication tool ⛷️ 🐌 🛰️
TypeScript
134
star
44

algoliasearch-jekyll

⚠ DEPRECATED Use jekyll-algolia instead.
Ruby
124
star
45

algoliasearch-client-csharp

⚡️ A fully-featured and blazing-fast C# API client to interact with Algolia.
C#
113
star
46

firestore-algolia-search

TypeScript
112
star
47

kubernetes-hands-on

Kubernetes Hands-on by Algolia
110
star
48

frontman

💎 A Ruby-based static website generator
Ruby
108
star
49

create-instantsearch-app

⚡️ Build InstantSearch apps at the speed of thought
JavaScript
107
star
50

algoliasearch-client-android

Algolia Search API Client for Android
Java
98
star
51

faux-jax

NO MORE MAINTAINED: Intercept and respond to requests in the browser (AJAX) and Node.js (http(s) module)
JavaScript
96
star
52

cli

🔍 Algolia’s official CLI devtool
Go
94
star
53

algolia-cli-old

[DEPRECATED] This repo and npm package are no longer maintained or supported. The new official command line tool can be found here: https://github.com/algolia/cli
JavaScript
82
star
54

doc-code-samples

This repository holds the Algolia documentation big code samples like GeoSearch, Calendar...
TypeScript
82
star
55

rollup-jest-boilerplate

🎉 Full featured boilerplate for building JavaScript libraries the modern way
JavaScript
80
star
56

marvel-search

Searchable list of all Marvel superheroes and supervillains
JavaScript
77
star
57

examples

Set of code samples highlighting the different ways to use the Algolia API
CSS
76
star
58

instantsearch-ios-examples

Example apps built with InstantSearch iOS
Swift
67
star
59

instantsearch-android-examples

Example apps built with algolia/instantsearch-android
Kotlin
63
star
60

algoliasearch-client-css

Algolia Search API Client for CSS
JavaScript
63
star
61

mongoolia

Keep your mongoose schemas synced with Algolia
JavaScript
58
star
62

algoliasearch-client-kotlin

⚡️ A fully-featured and blazing-fast Kotlin/Android API client to interact with Algolia.
Kotlin
56
star
63

hn-reactnative-sample

Sample Hacker News Search app by Algolia based on React Native.
JavaScript
54
star
64

search-insights.js

Library for reporting click, conversion and view metrics using the Algolia Insights API
TypeScript
53
star
65

jest-serializer-html

Jest snapshot serializer that beautifies HTML.
JavaScript
51
star
66

redux-updeep

small reducer generator that uses updeep to immutably deep merge partial updates into the reducer's state
JavaScript
50
star
67

algoliasearch-alexa

🔊 Search by voice in Alexa, powered by Algolia
JavaScript
44
star
68

chunk-text

🔪 chunk/split a string by length without cutting/truncating words.
JavaScript
44
star
69

algoliasearch-client-java

⚡️ A fully-featured and blazing-fast Java API client to interact with Algolia.
Java
43
star
70

react-nouislider

CSS
42
star
71

react-test-boilerplate

Companion project for Algolia's React unit testing blog post
JavaScript
41
star
72

algoliasearch-crawler-github-actions

Algolia Crawler Github action
TypeScript
40
star
73

demo-geo-search

Demo code illustrating the geo search features of Algolia
JavaScript
39
star
74

laravel-scout-algolia-macros

DEPRECATED: Use of this repository is deprecated. Please use Scout Extended - https://github.com/algolia/scout-extended instead.
PHP
39
star
75

algoliasearch-client-objc

Algolia Search API Client for iOS & OS X
Objective-C
38
star
76

docsearch-website

Previous repository for the DocSearch documentation website, now at https://github.com/algolia/docsearch/tree/next/packages/website
CSS
38
star
77

algoliasearch-client-node

DEPRECATED
36
star
78

algoliasearch-rails-example

AlgoliaSearch+Ruby on Rails examples
Ruby
36
star
79

elasticsearch-topk-plugin

Elasticsearch Top-K Aggregation Plugin
Java
35
star
80

wordpress-docker

Simple docker based environment for WordPress plugins and themes development.
Shell
34
star
81

algolia-sitemap

a node library allowing you to generate sitemaps from an Algolia index.
JavaScript
33
star
82

jekyll-algolia-example

Front-end example of the jekyll-algolia plugin
HTML
33
star
83

vue-instantsearch-examples

Examples for Vue InstantSearch v1, v2 links: https://github.com/algolia/vue-instantsearch-examples/issues/50
Shell
33
star
84

unified-instantsearch-ecommerce

The fastest way to implement Algolia, for e-commerce customers.
JavaScript
32
star
85

algoliasearch-client-java-legacy

*DEPRECATED* Algolia Search API Client for Java, see https://github.com/algolia/algoliasearch-client-java-2
Java
31
star
86

talksearch-scraper

Extract captions and metadata from YouTube playlists and push them to Algolia
JavaScript
31
star
87

diffable-html

Opinionated HTML formatter focused towards making HTML diffs readable.
JavaScript
30
star
88

api-clients-automation

🤖 Monorepo of the Algolia API specs and their auto-generated clients and documentation
PHP
30
star
89

recommend

A UI library for Algolia Recommend, available for Vanilla JavaScript and React.
TypeScript
29
star
90

eslint-config-algolia

Algolia's ESLint config and prettier instructions for JavaScript projects
JavaScript
27
star
91

talksearch

🎤 An interactive search experience for video titles and transcripts
JavaScript
25
star
92

algolia-firebase-nodejs

An example showing how to push data from Firebase to Algolia
JavaScript
24
star
93

algoliasearch-client-scala

⚡️ A fully-featured and blazing-fast Scala API client to interact with Algolia.
Scala
24
star
94

redux-magic-async-middleware

redux-magic-async-middleware is a middleware which makes it easy to handle asynchronous data with redux
JavaScript
23
star
95

laravel-scout-settings

DEPRECATED: Use of this repository is deprecated. Please use Scout Extended - https://github.com/algolia/scout-extended instead.
PHP
23
star
96

pdrone

Control Parrot drones with JavaScript
JavaScript
23
star
97

algoliasearch-helper-flutter

⚡️ Building block to create instant-search applications with Flutter
Dart
23
star
98

algolia-swift-demo

iOS instant search tutorial
Swift
23
star
99

algolia-react-boilerplate

🔥 A highly scalable, and customizable boilerplate, made with ReactInstantSearchHooks and with many Algolia's features. Ready to configure and deploy. You have just to follow steps in readme file. 💥
JavaScript
23
star
100

algolia-coding-contest

Welcome to the first Algolia Coding Contest, until May 5th.
22
star