Skip to content

toptal/chewy

Gem Version GitHub Actions Code Climate Inline docs

Chewy

Chewy is an ODM (Object Document Mapper), built on top of the official Elasticsearch client.

Why Chewy?

In this section we'll cover why you might want to use Chewy instead of the official elasticsearch-ruby client gem.

  • Every index is observable by all the related models.

    Most of the indexed models are related to each other and sometimes it is necessary to denormalize this related data and put it in the same object. For example, you need to index an array of tags together with an article. Chewy allows you to specify an updateable index for every model separately - so corresponding articles will be reindexed on any tag update.

  • Bulk import everywhere.

    Chewy utilizes the bulk ES API for full reindexing or index updates. It also uses atomic updates. All the changed objects are collected inside the atomic block and the index is updated once at the end with all the collected objects. See Chewy.strategy(:atomic) for more details.

  • Powerful querying DSL.

    Chewy has an ActiveRecord-style query DSL. It is chainable, mergeable and lazy, so you can produce queries in the most efficient way. It also has object-oriented query and filter builders.

  • Support for ActiveRecord.

    Chewy provides out-of-the-box integration with ActiveRecord, including automatic index updates on model changes via update_index callbacks.

Installation

Add this line to your application's Gemfile:

gem 'chewy'

And then execute:

$ bundle

Or install it yourself as:

$ gem install chewy

Compatibility

Chewy aims to support all Ruby and Rails versions that are currently maintained by their respective teams. When a version reaches end-of-life, we may drop support for it in a future release.

Ruby

Chewy is compatible with MRI 3.2-3.4.

Elasticsearch compatibility matrix

Chewy version Elasticsearch version
8.0.0 8.x
7.2.x 7.x
7.1.x 7.x
7.0.x 6.8, 7.x
6.0.0 5.x, 6.x
5.x 5.x, limited support for 1.x & 2.x

Important: Chewy doesn't follow SemVer, so you should always check the release notes before upgrading. The major version is linked to the newest supported Elasticsearch and the minor version bumps may include breaking changes.

See our migration guide for detailed upgrade instructions between various Chewy versions.

Active Record

The following Active Record versions are supported by Chewy:

  • 7.2
  • 8.0

Getting Started

Chewy provides functionality for Elasticsearch index handling, documents import mappings, index update strategies and chainable query DSL.

Minimal client setting

Create config/initializers/chewy.rb with this line:

Chewy.settings = {host: 'localhost:9250'}

And run rails g chewy:install to generate chewy.yml:

# config/chewy.yml
# separate environment configs
test:
  host: 'localhost:9250'
  prefix: 'test'
development:
  host: 'localhost:9200'

Elasticsearch

Make sure you have Elasticsearch up and running. You can install it locally, but the easiest way is to use Docker:

$ docker run --rm --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" elasticsearch:8.15.0

Security

Please note that starting from version 8 Elasticsearch has security features enabled by default. Docker command above has it disabled for local testing convenience. If you want to enable it, omit "xpack.security.enabled=false" part from Docker command, and run these command after starting container (container name es8 assumed):

Reset password for elastic user:

docker container exec es8 '/usr/share/elasticsearch/bin/elasticsearch-reset-password' -u elastic

Extract CA certificate generated by Elasticsearch on first run:

docker container cp es8:/usr/share/elasticsearch/config/certs/http_ca.crt tmp/

And then add them to settings:

# config/chewy.yml
development:
  host: 'localhost:9200'
  user: 'elastic'
  password: 'SomeLongPassword'
  transport_options:
    ssl:
      ca_file: './tmp/http_ca.crt'

Index

Create app/chewy/users_index.rb with User Index:

class UsersIndex < Chewy::Index
  settings analysis: {
    analyzer: {
      email: {
        tokenizer: 'keyword',
        filter: ['lowercase']
      }
    }
  }

  index_scope User
  field :first_name
  field :last_name
  field :email, analyzer: 'email'
end

Model

Add User model, table and migrate it:

$ bundle exec rails g model User first_name last_name email
$ bundle exec rails db:migrate

Add update_index to app/models/user.rb:

class User < ApplicationRecord
  update_index('users') { self }
end

Example of data request

  1. Once a record is created (could be done via the Rails console), it creates User index too:
User.create(
  first_name: "test1",
  last_name: "test1",
  email: 'test1@example.com',
  # other fields
)
# UsersIndex Import (355.3ms) {:index=>1}
# => #<User id: 1, first_name: "test1", last_name: "test1", email: "test1@example.com", # other fields>
  1. A query could be exposed at a given UsersController:
def search
  @users = UsersIndex.query(query_string: { fields: [:first_name, :last_name, :email, ...], query: search_params[:query], default_operator: 'and' })
  render json: @users.to_json, status: :ok
end

private

def search_params
  params.permit(:query, :page, :per)
end
  1. So a request against http://localhost:3000/users/search?query=test1@example.com issuing a response like:
[
  {
    "attributes":{
      "id":"1",
      "first_name":"test1",
      "last_name":"test1",
      "email":"test1@example.com",
      ...
      "_score":0.9808291,
      "_explanation":null
    },
    "_data":{
      "_index":"users",
      "_type":"_doc",
      "_id":"1",
      "_score":0.9808291,
      "_source":{
        "first_name":"test1",
        "last_name":"test1",
        "email":"test1@example.com",
        ...
      }
    }
  }
]

Documentation

  • Getting Started — end-to-end tutorial building search for a media library
  • Configuration — client settings, update strategies, notifications, integrations
  • Indexing — index definition, field types, crutches, witchcraft, index manipulation
  • Import — import options, raw import, journaling
  • Querying — search requests, pagination, scopes, scroll, loading
  • Rake Tasks — all rake tasks and parallelization
  • Testing — RSpec, Minitest, DatabaseCleaner
  • Troubleshooting — pre-request filter
  • Non-Rails Usage — using Chewy without Rails

FAQ

Can I use Chewy without Rails?

Yes. ActiveSupport and the elasticsearch gem are the only hard dependencies; the Rails railtie loads conditionally. See the Non-Rails Usage guide.

Does Chewy follow SemVer?

No. The major version tracks the newest supported Elasticsearch version and minor version bumps may include breaking changes. Always check the release notes before upgrading.

Which versions of Ruby, Rails and Elasticsearch are supported?

See the Compatibility section above. When a Ruby or Rails version reaches end-of-life we may drop support in a future release.

What's the UndefinedUpdateStrategy error?

Chewy raises this when you save a model with an update_index callback and no strategy is active. Wrap your code in Chewy.strategy(:atomic) { ... } or set Chewy.root_strategy = :bypass. See Troubleshooting for details.

Can I use Chewy with OpenSearch?

OpenSearch is not officially supported or tested. Chewy depends on the official elasticsearch Ruby client and targets Elasticsearch.

How do I connect to Elastic Cloud?

Use the standard client settings with your Cloud credentials (API key or user/password). See Configuration for examples.

Contributing

  1. Fork it (http://github.com/toptal/chewy/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Implement your changes, cover it with specs and make sure old specs are passing
  4. Commit your changes (git commit -am 'Add some feature')
  5. Push to the branch (git push origin my-new-feature)
  6. Create new Pull Request

Use the following Rake tasks to control the Elasticsearch cluster while developing, if you prefer native Elasticsearch installation over the dockerized one:

rake elasticsearch:start # start Elasticsearch cluster on 9250 port for tests
rake elasticsearch:stop # stop Elasticsearch

Copyright

Copyright (c) 2013-2025 Toptal, LLC. See LICENSE.txt for further details.

About

High-level Elasticsearch Ruby framework based on the official elasticsearch-ruby client

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Languages