Here's how to get started with Bonsai and Ruby on Rails using Active Search, the search framework from 37signals. Active Search gives your models one search interface that works across database full-text search and search engines like OpenSearch and Elasticsearch.
Add the Gems
Active Search doesn't include a search client, so add the one that matches your cluster. For an OpenSearch cluster:
Then run bundle install, followed by the install task, which writes config/search.yml and config/search.rb:
Configure the Connection
You can find your Bonsai cluster URL in the Access section of your cluster dashboard. Hard-coding your credentials is not recommended. Instead, export the URL to an environment variable called BONSAI_URL:
# Substitute with your own Bonsai cluster URL:
Heroku users will not need to do so, as their Bonsai cluster URL will already be in a Config Var of the same name.
Then point the production environment at your cluster in config/search.yml:
development:
adapter: sqlite
production:
adapter: opensearch
hosts:
- <%= ENV["BONSAI_URL"] %>
The client reads the host, port and credentials from the URL. To confirm that your app can reach the cluster, run:
RAILS_ENV=production
Configure Your Models
Declare an index for each model you want to search in config/search.rb. text fields are searched, and the other types are used for filtering and sorting:
ActiveSearch.define_index(:articles) do
text :title
text :body
string :status
end
Then add has_search to the model:
has_search
end
has_search uses the index named after the model's table. It reindexes a record after every create and update, and removes it after destroy, through Active Job.
Indexing Your Documents
Create the index on your cluster:
RAILS_ENV=production
The model callbacks only index records as they change, so load your existing records with a batch. This sends them to your cluster as _bulk requests:
ActiveSearch.index(:articles).batch(max_size: 500) do
Article.find_each { batch.add(article) }
end
To check that everything made it in, count the documents in each index:
RAILS_ENV=production
The document count on your Cluster Overview should match.
Searching
Queries chain like Active Record queries, and pagination is built in:
@page = Article.search(params[:q])
.filter(status: )
.page(params[:page], per_page: 20)
@page.results.each do
article.title
article.hit.score
end
To see the request Active Search sends to your cluster, call to_native_query. You can paste the result into the Console as a POST to /articles/_search:
Article.search().to_native_query
Query Logs
Query Logs extracts the user's search terms from each request. To tell Bonsai exactly what the user typed, add it to the request with native:
Article.search(params[:q]).native {
request.merge(ext: { bonsai: { user_query: params[:q] } })
}.page(params[:page])
Next Steps
The Active Search README covers highlighting, filters, polymorphic indexes, routing and the full list of adapters. For a walkthrough of Active Search with the Bonsai dashboard, see Active Search, Meet Bonsai on the Bonsai blog.
Ready to power your search with AI?
Launch a fully managed Elasticsearch or OpenSearch cluster, with built-in vector search and AI capabilities.