Full-text search đơn giản trong Ruby on Rails với gem search_cop
Bài đăng này đã không được cập nhật trong 8 năm
Như các bạn đã biết về full-text search thì đây là một cách để tăng tốc độ thực hiện câu query, với những ai chưa rõ full-text search là gì thì có thể tham khảo thêm ở đây: Giới thiệu về full-text search.
Trong bài viết này mình sẽ hướng dẫn các bạn một cách dùng gem để hỗ trợ sử dụng full-text seach thay vì viết query trực tiếp trong model. Tuy nhiên khi sử dụng thì các bạn cần lưu ý là phải đánh index trước.
1. Installation :
Thêm dòng sau vào trong gem file:
gem "search_cop"
và chạy lệnh
bundle install trong terminal.
2. Usage
Để sử dụng được gem này, trước tiên các bạn cần kích hoạt bằng cách include SearchCop trong model và xác định các thuộc tính mà bạn dự định sẽ tìm kiếm dựa vào nó.
class Book < ActiveRecord::Base
include SearchCop
search_scope :search do
attributes :title, :description, :stock, :price, :created_at, :available
attributes comment: ["comments.title", "comments.message"]
attributes author: "author.name"
# ...
end
has_many :comments
belongs_to :author
end
Ngoài ra bạn cũng có thể viết nhiều search_scope:
search_scope :admin_search do
attributes :title, :description, :stock, :price, :created_at, :available
# ...
end
search_scope :user_search do
attributes :title, :description
# ...
end
Sau đó ta gọi đến SearchCop trong controller như sau:
Book.search("stock > 0")
# ... WHERE books.stock > 0
Book.search("price > 10 stock > 0")
# ... WHERE books.price > 10 AND books.stock > 0
Book.search("Harry Potter")
# ... WHERE (books.title LIKE '%Harry%' OR books.description LIKE '%Harry%' OR ...) AND (books.title LIKE '%Potter%' OR books.description LIKE '%Potter%' ...)
Book.search("available:yes OR created_at:2014")
# ... WHERE books.available = 1 OR (books.created_at >= '2014-01-01 00:00:00' and books.created_at <= '2014-12-31 00:00:00')
Trong trường hợp bạn muốn search từ thuộc tính của các model khác, chúng ta sẽ thực hiện như sau:
class Book < ActiveRecord::Base
# ...
belongs_to :author
search_scope :search do
attributes author: "author.name"
end
# ...
end
Mặc định SearchCop sẽ sử dụng eager_load. Trong trường hợp bạn không muốn sử dụng eager_load một cách tự động, bạn có thể xác định một scope:
class Book < ActiveRecord::Base
# ...
search_scope :search do
# ...
scope { joins(:author).eager_load(:comments) } # etc.
end
# ...
end
SearchCop sẽ bỏ qua việc tự động load các quan hệ và sử dụng scope đã được định nghĩa. Bạn cũng có thể sử dụng scope cùng với aliases để thực hiện các câu lệnh joins và search phức tạp với các bảng/models được join:
class Book < ActiveRecord::Base
# ...
search_scope :search do
attributes similar: ["similar_books.title", "similar_books.description"]
scope do
joins "left outer join books similar_books on ..."
end
aliases similar_books: Book # Tell SearchCop how to map SQL aliases to models
end
# ...
end
Với quan hệ nhiều nhiều ta có thể thực hiện như sau:
class Book < ActiveRecord::Base
# ...
has_many :comments
has_many :users, :through => :comments
search_scope :search do
attributes user: "users.username"
end
# ...
end
3. Một số lưu ý:
- Bạn cần phải đánh index trước khi sử dụng fulltext-search
- Nếu đã có index, bạn cần thêm dòng options :attributes_name, :type => :fulltext vào trong search_scope
Ngoài ra các bạn có thể vào link dưới đây để đọc thêm.
Link tham khảo: https://github.com/mrkamel/search_cop
All rights reserved