ActiveElastic grants to an ActiveRecord models to query and index documents easily to ElasticSearch.
ActiveElastic uses the following gems to work properly:
- ActiveRecord
- elasticsearch-model
- elasticsearch-persitence
- Sidekiq: For document indexing in the background. (Future version will use ActiveJob)
Add this line to your application's Gemfile:
gem 'active_elastic', git: 'https://github.com/PixelPerfectTree/active_elastic'
And then execute:
$ bundle install
ActiveElastic is supposed to work with an ActiveRecord model.
Include ActiveElastic::Model
to ActiveRecord models to power it up!.
class Post < ActiveRecord::Base
include ActiveElastic::Model
end
ActiveElastic has a few configuration methods that can be used in an initializer.
ActiveElastic::Config.configure do |config|
config.index_prefix = nil # Prefix to be use with indexes name. By default is empty.
config.prepend_env_in_index = true # Prepend the current enviroment in document index name.
config.index_document_after_save = false # Auto index the document when the model is modified.
config.use_background_jobs = false # Use Background Jobs for indexing documents (Sidekiq)
config.schema_models = [ # Models to be imported by the schema importer.
:Posts,
:Comments
]
end
To use Sidekiq make sure you have this queues in the sidekiq worker: elastic_search_indexer_worker
and
elatic_model_importer
ActiveElastic adds methods to build queries for ElasticSeach.
To begin to build this queries there is a elastic_find
method we need to use.
Execute the current query. By default returns all the documents.
Post.elastic_find.all
Filters documents by a condition.
Post.elastic_find.where(active: true)
We also can use a array. This is an alias to .in
Post.elastic_find.where(tags: ['tag1', 'tag2'])
Same has where
but negated.
Return the first document
Find a document by a single conditions. Raises ActiveElastic::RecordNotFound
if document is not found.
Find a document by ID. Raises ActiveElastic::RecordNotFound
if document is not found.
Add an order condition to the current query.
Add a limit condition to the current query. By default is 10
Search document with the offset number useing the current limit.
Check if a field is null or missing.
Check if a field is not null or missing.
Add a conditions where a field has to have all values
Post.elastic_find.inclued_in(tags: ['tag1', 'tags2']) # Find Post that are tagged with tag1 and tag2
Same as inclued_in
but negated.
Execute all the query methods inside a hash.
conditions = {
where: { title "Hello World" },
where: { active: true },
order: title
}
Post.elaastic_find.filter_using(conditions).all
We also can define scopes inside the model.
class Post < ActiveRecord::Base
include ActiveElastic::Model
elastic_scope :started, -> { where(started: true) }
default_scope, -> { where(active: true) }
end
Post.elastic_find.started.all
If we have to do a query without the default scope we can use unscoped
method to have a query without default scope.
Post.elastic_find.unscoped.started.all
The index_document
method calls the indexer worker.
By default the worker will index the document without using a backgorund job.
If ActiveElastic::Config.use_background_jobs
is true, it will use Sidekiq the enqueue the document for indexation in the elastic_search_indexer_worker
.
The indexstion use the as_indexed_json
method to serialize the object.
Note: Background Jobs are disable in the test enviroment.
If we want to include relations inside the indexed document. We need to define which relations will be included.
To do this we need to define a index_relations
method inside the model and use index_relation
method.
class Post < ActiveRecord::Base
include ActiveElastic::Model
def index_relations(exlucluded_relations=[])
index_relation(:comments) unless exclude_relations.include? :comments
end
end
The indexer will call the comments
method and serialize its result.
ActiveElastic provides some Rake tasks to manipulate schemas and import DB data to ElasticSearch.
Mosts of this tasks uses the models defined in ActiveElastic::Config.schema_models
.
Create the models schema for ElasticSearch
Drop all the ElasticSearch schemas.
Will drop and then create all the model schemas.
Imports all the models's data to ElasticSearch.
This job uses Sidekiq's elatic_model_importer
queue for background Job.
Imports the data for a single model to ElasticSearch.
This job uses Sidekiq's elatic_model_importer
queue for background Job.
Imports the data for a single model to ElasticSearch without using a background job.
You can use this helper module for Rspec to reset ElasticSearch for each test.
# spec/support/elastic_helper.rb
module ElasticHelper
def elastic_cleanable
before :each do
ActiveElastic::ElasticSchema.force_create
end
end
end
Usage:
### spec/rails_helper.rb
....
RSpec.configure do |config|
config.extend ElasticHelper
...
### /spec/some_spec.rb
describe SomeSpec do
elastic_cleanble
it do
...
end
end
Make sure to use Model.refresh_index!
to access documents when created in test. Not using this will return nil when retreaving the created document.
....
it "this is a example" do
FactoryGirl.create(:post)
Post.refresh_index! # Without this command, the next search would return an empty list of posts.
expect(Post.elastic_find.all.total).to eq(1)
end
- Fork it ( https://github.com/PixelPerfectTree/active_elastic' )
- 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 a new Pull Request