Searchkick callbacks
Bài viết được tham khảo từ link https://github.com/ankane/searchkick#reindex Searchkick là một gem khá quyen thuộc trong việc sử dụng Elastisearch trong rails, việc hiểu rõ hơn về gem này giúp bạn chủ động hơn trong công việc Đôi khi trong lúc sử dụng ES (Elasticsearch), chúng ta cần skip đánh ...
Bài viết được tham khảo từ link https://github.com/ankane/searchkick#reindex
Searchkick là một gem khá quyen thuộc trong việc sử dụng Elastisearch trong rails, việc hiểu rõ hơn về gem này giúp bạn chủ động hơn trong công việc
Đôi khi trong lúc sử dụng ES (Elasticsearch), chúng ta cần skip đánh index hoặc đưa việc đánh index vào job chạy nền, callbacks giúp bạn làm điều đó
To Reindex, or Not to Reindex
Reindex
- Khi bạn cài đặt hoặc nâng cấp searchkick
- Thay đổi phương pháp search_data
- Thay đổi phương pháp tìm kiếm
No need to reindex
- App khởi động
Stay Synced
Có bốn cách để giữ cho chỉ mục được đồng bộ với cơ sở dữ liệu của bạn.
- Ngay lập tức (mặc định)
Bất cứ khi nào một bản ghi được chèn vào, cập nhật hoặc xóa
- Không đồng bộ
Sử dụng công việc nền cho hiệu suất tốt hơn
class Product < ApplicationRecord searchkick callbacks: :async end
Jobs được thêm vào một hàng đợi có tên là searchkick.
- Hàng đợi
Đẩy id của các bản ghi cần cập nhật lên hàng đợi và sắp xếp lại lại dưới lên. Đây là cách hiệu suất hơn so với phương pháp không đồng bộ, cập nhật bản ghi riêng. Xem cách thiết lập.
- Manual
Tắt đồng bộ hóa tự động
class Product < ApplicationRecord searchkick callbacks: false end
Bạn có thể dùng cách này ví dụ khi import nhiều record vào cùng 1 lúc, sau đó đánh index lại các record mới được tạo ra cùng một lúc, Ví dụ
def import rows = CSV.read ... product_ids = [] Searchkick.callbacks(false) do rows.each do |row| import product ... product_ids << product.id end end Product.where(id: product_ids).reindex end
Chú ý hàm reindex đối với 1 active record relation không cần accept_danger: true đối với Searchkick ver 2.5.0 trở lên Ngoài ra nếu trong model product bạn có gọi reindex thì chỉ cần check Searchkick.callbacks? là được Ví dụ:
class Product < ActiveRecord::Base after_commit: ->{some_associations.reindex if Searchkick.callbacks?} end
Queuing
Đẩy id của hồ sơ cần được sắp xếp lại cho hàng đợi và sắp xếp lại số lượng lớn để có hiệu suất tốt hơn. Trước tiên, thiết lập Redis. Chúng tôi khuyên bạn nên sử dụng connection_pool.
Searchkick.redis = ConnectionPool.new { Redis.new }
Và trong model
class Product < ApplicationRecord searchkick callbacks: :queue end
Sau đó, thiết lập một job nền để chạy.
Searchkick::ProcessQueueJob.perform_later(class_name: "Product")
Bạn có thể kiểm tra chiều dài hàng đợi bằng:
Product.search_index.reindex_queue.length
Reindex conditionally
class Product < ApplicationRecord searchkick callbacks: false # add the callbacks manually after_commit :reindex, if: -> (model) { model.previous_changes.key?("name") } # use your own condition end
Testing
Để thực hiện, chỉ bật tính năng gọi lại Searchkick cho các thử nghiệm cần đến.
Minitest
Thêm vào test/test_helper.rb:
# reindex models Product.reindex # and disable callbacks Searchkick.disable_callbacks
Và sử dụng
class ProductTest < Minitest::Test def setup Searchkick.enable_callbacks end def teardown Searchkick.disable_callbacks end def test_search Product.create!(name: "Apple") Product.search_index.refresh assert_equal ["Apple"], Product.search("apple").map(&:name) end end
RSpec
Thêm vào spec/spec_helper.rb:
RSpec.configure do |config| config.before(:suite) do # reindex models Product.reindex # and disable callbacks Searchkick.disable_callbacks end config.around(:each, search: true) do |example| Searchkick.callbacks(true) do example.run end end end
Và sử dụng
describe Product, search: true do it "searches" do Product.create!(name: "Apple") Product.search_index.refresh assert_equal ["Apple"], Product.search("apple").map(&:name) end end
Factory Girl
Sử dụng một đặc tính và tạo một mock sau cho mỗi mô hình được lập chỉ mục:
FactoryGirl.define do factory :product do # ... # Note: This should be the last trait in the list so `reindex` is called # after all the other callbacks complete. trait :reindex do after(:create) do |product, _evaluator| product.reindex(refresh: true) end end end end # use it FactoryGirl.create(:product, :some_trait, :reindex, some_attribute: "foo")
Cảm ơn và hi vọng bài viết có ích trong công việc của bạn