Search engine
Nhắc đến Google chúng ta nghĩ ngay đến công cụ tìm kiếm lớn nhất thế giới. Trong thời đại bùng nổ thông tin số như hiện tại thì công tụ tìm kiếm là thứ không thể thiếu. Hầu hết các trang web đều trang bị chức năng tìm kiếm, tuy không thể so sánh được với Google nhưng cũng giúp ích cho người dùng ...
Nhắc đến Google chúng ta nghĩ ngay đến công cụ tìm kiếm lớn nhất thế giới. Trong thời đại bùng nổ thông tin số như hiện tại thì công tụ tìm kiếm là thứ không thể thiếu. Hầu hết các trang web đều trang bị chức năng tìm kiếm, tuy không thể so sánh được với Google nhưng cũng giúp ích cho người dùng trong việc tìm kiếm nội dung trên trang.
Với ruby on rails, làm thế nào để thiết kế và tạo ra 1 tiện ích tìm kiếm như thế? Bài viết này sẽ đưa ra câu trả lời cho câu hỏi đó. Đầu tiên chúng tôi giới thiệu về search engin Sorl, và gem Sunspot. Sau đó sẽ bàn luận về 1 vấn đề trong tìm kiếm và cách giải quyết khi sử dụng sorl và sunspot.
I. Solr là gì?
Solr là search search mã nguồn mở rất phổ biến. Nó hỗ trợ nhiều tính năng như full-text search, hit highlighting, faceted search, near real-time indexing, dynamic clustering, database integration, rich document (Word, PDF, ...) handling, and geospatial.
II. Sunspot là gì?
Sunspot là thư viện tương tác giữa rails application và Solr.
III. Cài đặt và cách sử dụng Sunspot, Solr
1. Cài đặt
Thêm gem vào Gemfile:
gem 'sunspot_rails' gem 'sunspot_solr'
Sau khi chạy bundle install, chạy lệnh sau để khởi tạo sunspot. Khi chạy lệnh này, file cấu hình mặc định sunspot.xml sẽ được tạo ra. Đây chính là file khai báo thông tin cần thiết để kết nối tới solr server như hostname, port ...
$rails g sunspot_rails:install #config/sunspot.xml production: solr: hostname: localhost port: 8983 log_level: WARNING staging: solr: hostname: localhost port: 8080 log_level: WARNING development: solr: hostname: localhost port: 8982 log_level: INFO test: solr: hostname: localhost port: 8981 log_level: WARNING
Và chạy Solr server:
rake sunspot:solr:start
Chạy lệnh để index dữ liệu:
rake sunspot:reindex
2. Cách sử dụng
Giả sử có bảng advices với các thuộc tính như title, user_id, state, created_at, update_at. Khi chúng ta muốn tìm kiếm advice dựa trên thuộc tính title thì class Advice trong model sẽ cài đặt như sau:
class Advice < ActiveRecord::Base attr_accessible :title, :user_id, :state, :created_at, :updated_at searchable do text :title, :stored => true integer :user_id string :state time :created_at end end
Khi viết xong model, như đã hướng dẫn ở trên, chúng ta dùng lệnh rake sunspot:reindex để nhập dữ liệu cho solr. Và controller Searches cài đặt như dưới đây.
class SearchesController < ApplicationController def search search = Advice.search do fulltext params[:title] with(:user_id, params[:user_id]) with(:state, params[:state]) paginate(:per_page => 5, :page => params[:page]) order_by :created_at, :desc end seach.total # tổng số kết quả tìm được search.results # mảng advice tìm được end end
Trong đó:
fulltext params[:title] khai báo tìm kiếm những Advice có title chứa từ khoá params[:title]. Cùng với một số điều kiện như: with(:user_id, params[:user_id]) với owner có id là params[:user_id]. with(:state, params[:state]) với state là params[:state]
Và một số tính năng khác như phân trang, xắp xếp kết quả.
IV. Một vấn đề trong tìm kiếm
Trong tiếng Nhật, hiragana và katakana chỉ là 2 cách viết, không hề khác nhau về mặt ý nghĩa. Nên yêu cầu đặt ra đối với tính năng tìm kiếm là phải đưa ra kết quả giống nhau khi search với từ khoá dưới đang hiragana hoặc katakana. Nhưng solr ko làm được điều đó. Nguyên nhân là do solr sử dụng nguyên văn dữ liệu đầu vào để index và sử dụng index đó vào việc tìm kiếm. Nếu dữ liệu đầu vào là hiragana thì index dưới dạng hiragana, và tương tự đối với katakana. Và hoàn toàn không có cơ chế nhận biết giữa hiragana và katakana.
Ví dụ: ひらがな ー ヒラガナ
Ý tưởng để giải quyết vấn đề này khá đơn giản, đó là chuyển đổi dữ liệu cần tìm kiếm và từ khoá về cùng 1 định dạng katakana hoặc hiragana. Chuyển đổi text từ katakana sang hiragana ta có thể thực hiện dễ dàng bằng NKF. Tương tự như ví dụ ở trên nhưng thay đổi một chút trong model và controller seach như dưới đấy.
Chuyển title sang định dạng hiragana.
class Advice < ActiveRecord::Base attr_accessible :title, :user_id, :state, :created_at, :updated_at searchable do text :title, :stored => true do NKF.nkf(“--hiragana -w”, title) end integer :user_id string :state time :created_at end end
Khi tìm kiếm, ta cũng chuyển từ khoá sang định dạng hiragana.
Advice.search do fulltext NKF.nkf(“--hiragana -w”, params[:title]) end
V. Conclusion
Từ vấn đề trên có thể mở rộng vấn đề tìm kiếm mà dữ liệu ko nhất thiết phải lưu trữ trong cơ sở dữ liệu, chỉ cần có 1 bộ chuyển đổi kiểu như NKF.
Ứng dụng như khi tìm kiếm mà muốn xuất ra kết quả dưới dạng nhiều ngôn ngữ. Giả sử đối với 2 ngôn ngữ tiếng Anh và tiếng Việt: English là Tiếng Anh Vietnamese là Tiếng Việt
Làm sao tìm được những dữ liệu chứa “Tiếng Anh” khi từ khoá nhập vào là “English”?
Tương tự như NKF, ta chỉ việc xây dựng thư viện chuyển đổi (ví dụ như từ điển) về 1 định đạng tiếng Anh hoặc tiếng Việt để solr index. Như vậy ta sẽ tìm được kết quả ở cả hai loại ngôn ngữ.
VI.