Chewy is an ODM (Object Document Mapper), built on top of the official Elasticsearch client.
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_indexcallbacks.
Add this line to your application's Gemfile:
gem 'chewy'
And then execute:
$ bundle
Or install it yourself as:
$ gem install chewy
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.
Chewy is compatible with MRI 3.2-3.4.
| 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.
The following Active Record versions are supported by Chewy:
- 7.2
- 8.0
Chewy provides functionality for Elasticsearch index handling, documents import mappings, index update strategies and chainable query DSL.
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'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.0Please 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'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'
endAdd User model, table and migrate it:
$ bundle exec rails g model User first_name last_name email
$ bundle exec rails db:migrateAdd update_index to app/models/user.rb:
class User < ApplicationRecord
update_index('users') { self }
end- 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>
- 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- So a request against
http://localhost:3000/users/search?query=test1@example.comissuing 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",
...
}
}
}
]- 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
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.
- Fork it (http://github.com/toptal/chewy/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Implement your changes, cover it with specs and make sure old specs are passing
- Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - 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 ElasticsearchCopyright (c) 2013-2025 Toptal, LLC. See LICENSE.txt for further details.