The elasticsearch-rails2 library is based on the
elasticsearch-model and builds on top of the
the elasticsearch library.
It aims to simplify integration of Ruby on Rails 2.3 models (ActiveRecord)
with the Elasticsearch search.
(If your app is in Ruby on Rails 2.3 you can't use elasticsearch-model because it requires Ruby on Rails >= 3.0)
The library is compatible with Ruby 1.9.3.
Installation
Add this line to your application's Gemfile:
gem 'elasticsearch-rails2'
And then execute:
$ bundle
Or install it yourself as:
$ gem install elasticsearch-rails2
Usage
Let's suppose you have an Article model:
require 'elasticsearch/rails2'
class Article < ActiveRecord::Base
include Elasticsearch::Rails2
endThis will extend the model with functionality related to Elasticsearch:
Elasticsearch client
The module will set up a client,
connected to localhost:9200, by default. You can access and use it as any other Elasticsearch::Client:
Article.client.cluster.health
# => { "cluster_name"=>"elasticsearch", "status"=>"yellow", ... }To use a client with different configuration, just set up a client for the model:
Article.client = Elasticsearch::Client.new host: 'api.server.org'Or configure the client for all models:
Elasticsearch::Rails2.client = Elasticsearch::Client.new log: trueYou might want to do this during you application bootstrap process, e.g. in a Rails initializer.
Please refer to the
elasticsearch-transport
library documentation for all the configuration options, and to the
elasticsearch-api library documentation
for information about the Ruby client API.
Searching
For starters, we can try the "simple" type of search:
response = Article.search 'fox dogs'
response.took
# => 3
response.results.total
# => 2
response.results.first._score
# => 0.02250402
response.results.first._source.title
# => "Quick brown fox"Search results
The returned response object is a rich wrapper around the JSON returned from Elasticsearch,
providing access to response metadata and the actual results ("hits").
Each "hit" is wrapped in the Result class, and provides method access
to its properties via Hashie::Mash.
The results object supports the Enumerable interface:
response.results.map { |r| r._source.title }
# => ["Quick brown fox", "Fast black dogs"]
response.results.select { |r| r.title =~ /^Q/ }
# => [#<Elasticsearch::Model::Response::Result:0x007 ... "_source"=>{"title"=>"Quick brown fox"}}>]In fact, the response object will delegate Enumerable methods to results:
response.any? { |r| r.title =~ /fox|dog/ }
# => trueTo use Array's methods (including any ActiveSupport extensions), just call to_a on the object:
response.to_a.last.title
# "Fast black dogs"Search results as database records
Instead of returning documents from Elasticsearch, the records method will return a collection
of model instances, fetched from the primary database, ordered by score:
response.records.to_a
# Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" IN (1, 2)
# => [#<Article id: 1, title: "Quick brown fox">, #<Article id: 2, title: "Fast black dogs">]The returned object is the genuine collection of model instances returned by your database,
The records method returns the real instances of your model, which is useful when you want to access your
model methods -- at the expense of slowing down your application, of course.
In most cases, working with results coming from Elasticsearch is sufficient, and much faster. See the
elasticsearch-rails
library for more information about compatibility with the Ruby on Rails framework.
The Elasticsearch DSL
In most situation, you'll want to pass the search definition in the Elasticsearch domain-specific language to the client:
response = Article.search query: { match: { title: "Fox Dogs" } },
highlight: { fields: { title: {} } }
response.results.first.highlight.title
# ["Quick brown <em>fox</em>"]You can pass any object which implements a to_hash method, or you can use your favourite JSON builder
to build the search definition as a JSON string:
require 'jbuilder'
query = Jbuilder.encode do |json|
json.query do
json.match do
json.title do
json.query "fox dogs"
end
end
end
end
response = Article.search query
response.results.first.title
# => "Quick brown fox"Index Configuration
By default, index name and document type will be inferred from your class name, you can set it explicitely, however:
class Article
index_name "articles-#{Rails.env}"
document_type "post"
endFor index_name there is a global setting in case you want to use the same index for all models:
Elasticsearch::Rails2.index_name = 'production'Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request