You have your model configured for being indexed and searchable with searchkick but sometimes you want to update a record or many records or a bunch of records without triggering searchkick reindex. It is here...
INTRODUCTION
Many articles have been written about how to combine rails, elasticsearch, sidekiq, and redis because this is an almost obvious schema in Ruby on Rails applications.
When you want to have a model indexed and searchable with elastisearch you go mainly with the gem searchkick.
The basic, most used and first option suggested by documentation is:
class Customer < ApplicationRecord
searchkick searchable: %i[name lastname],
filterable: %i[name],
callbacks: :async
def search_data
{
id: id,
name: name,
lastname: lastname
}
end
end
It is supposed also you have sidekiq on the table and the environment variable REDIS_URL.
In this scenario
When you update a customer:
Customer.first.update(name: 'Jack')
then a sidekiq job is triggered for reindex this customer.
PROBLEM
When you update all customers having 30 000 records:
Customer.all.each_with_index{|customer, index| customer.update(name: "Jack-#{index}")
then 30 000 sidekiq jobs are triggered and enqueued for reindex all these customers
SOLUTION
You can update your bunch of customers silencing searchkick and once all updates are executed you can reindex all those customers.
Take a look:
Searchkick.callbacks(false) do
Customer.all.each_with_index{|customer, index| customer.update(name: "Jack-#{index}")
end
Customer.reindex(mode: :async)
OR
Searchkick.disable_callbacks
Customer.all.each_with_index{|customer, index| customer.update(name: "Jack-#{index}")
Searchkick.enable_callbacks
Customer.reindex(mode: :async)
In this way, once all customers are updated then some sidekiq jobs are being triggered each of them indexing a bunch of customers in a bulk giving you a huge improvement regarding performance and resources.
The second way is especially useful for test:
describe '#has_vacancies?' do
subject(:event) { create :event, vacancies: 0 }
before do
Searchkick.disable_callbacks
end
after do
Searchkick.enable_callbacks
end
context 'when vacancies lower than 1' do
it 'return false' do
expect(event.vacancies?).to eq false
end
end
context 'when vacancies greater than 0' do
it 'return true' do
lesson.update(vacancies: 1)
expect(event.vacancies?).to eq true
end
end
end
Top comments (0)