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 7 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