March 20, 2020
brew install elasticsearch
elasticsearch
Open http://localhost:9200/
to make sure healthy.
gem 'elasticsearch-model'
bundle install
# config/initializers/elasticsearch.rb
Elasticsearch::Model.client = Elasticsearch::Client.new({
log: true
})
require 'elasticsearch/model'
class User < ApplicationRecord
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
end
Open bin/rails c
User.__elasticsearch__.create_index!(force: true) # do this before indexing in seed
User.create(email: 'ex@ample.com', password: 'password', name: 'kevin')
User.__elasticsearch__.search('kevin').results.total
Lets say you wanted to add more the waht is being indexed in eleasticsearch.
require 'elasticsearch/model'
class Example < ApplicationRecord
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
belongs_to :user
def as_indexed_json(options = {})
self.as_json(
only: [:id, :title],
include: {
user: {
only: [:id, :email]
}
}
)
end
end
Since Example
has user index in it, make sure you update all examples when user is updated by doing the following:
class User < ApplicationRecord
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
has_many :examples
after_save :index_examples_in_elasticsearch
def index_examples_in_elasticsearch
examples.find_each { |example| example.__elasticsearch__.index_document }
end
end
Example.__elasticsearch__.create_index!(force: true) # do this before indexing in seed
Example.create(title: 'Example', archive: false, user: User.last)
User.__elasticsearch__.search('kevin').records
User.__elasticsearch__.search(
query: {
multi_match: {
query: 'kevin',
fields: %w[name]
}
}
).records
User.__elasticsearch__.search('kev*').records.total
When you add kaminari
or will_paginate
make sure it is above elasticsearch-model
# Gemfile
gem 'kaminari'
gem 'elasticsearch-model'
User.__elasticsearch__.search('kev*').page(1).records
class BooksController < ApplicationController
def index
if query
response = User.__elasticsearch__.search(query).page(page).results
# recomend using jbuilder instead of building json in controller
render json: {
results: response.results,
total: response.total
}
return
end
render json: {
results: User.page(page),
total: User.count
}
end
private
def query
params.fetch(:query)
end
def page
param.fetch(:page, 1)
end
end
This works create in a dev enviroment, but eleaticsearch needs to be secure to work in production.
First you need to install a new gem.
# Gemfile
gem 'faraday_middleware-aws-signers-v4'
# config/initializers/elasticsearch.rb
if Rails.env.production?
require 'faraday_middleware/aws_signers_v4'
Elasticsearch::Model.client = Elasticsearch::Client.new({
log: true
}) do |f|
f.request(
:aws_signers_v4,
credentials: Aws::Credentials.new(ENV.fetch('AWS_ACCESS_KEY'), ENV.fetch('AWS_SECRET_ACCESS_KEY')),
service_name: 'es',
region: ENV.fetch('AWS_REGION')
)
end
else
Elasticsearch::Model.client = Elasticsearch::Client.new({
log: true
})
end