Full-text search đơn giản trong Ruby on Rails với gem search_cop
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 ...
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