在實際應用中如果可以讓用戶快速的搜索出自己想要的內容,這將會是一個很有用的功能。那么要怎么來實現呢?
像簡單一點的方法可以使用 SQL 的 LIKE
來實現,如
SELECT * FROM articles WHERE title LIKE '%小蘋果%';
但這樣實現對數據量很大的表,其實是相當耗時的。而且在其它業務下,我們可以會對用戶提交的搜索詞,進行分詞。在分詞后,上面的SQL 可能就變成
SELECT * FROM articles WHERE title ?LIKE '%小蘋果%' OR LIKE '%蘋果%' OR LIKE '%小%';
這樣效率肯定更低了。這時候我們可以使用 第三方的搜索程序,來減少數據庫的壓力,像 elasticsearch
,Solr
等等。
我們這里選擇 elasticsearch
,具體可以看這里 Elasticsearch 與 Solr
如果還不知道 elasticsearch,請選 ElasticSearch 入門
安裝 Gem
Rails 下使用 ElasticSearch ,可以使用 elasticsearch-rails 這個 Gem
# Gemfile
# 搜索
gem 'elasticsearch-model'
gem 'elasticsearch-rails'
$ bundle
配置 Model
打開要添加搜索的 model 類,添加如下內容
# app/models/article.rb
+ require 'elasticsearch/model'
class Article < ActiveRecord::Base
...
+ include Elasticsearch::Model
+ include Elasticsearch::Model::Callbacks
+ settings index: { number_of_shards: 1 } do
+ mappings dynamic: 'false' do
+ indexes :title
+ end
+ end
...
end
+ # Delete the previous articles index in Elasticsearch
+ Article.__elasticsearch__.client.indices.delete index: Article.index_name rescue nil
+ # Create the new index with the new mapping
+ Article.__elasticsearch__.client.indices.create \\
+ index: Article.index_name,
+ body: { settings: Article.settings.to_hash, mappings: Article.mappings.to_hash }
+ # Index all article records from the DB to Elasticsearch
+ Article.import force: true
使用
添加 app/controllers/search_controller.rb
class SearchController < ApplicationController
def search
if params[:q].nil?
@result = []
else
@result = Article.search(params[:q]).paginate(page: 1, per_page: 10)
end
end
end
添加 ** app/views/search/search.html.erb**
<h1>Articles Search</h1>
<%= form_for search_path, method: :get do |f| %>
<p>
<%= f.label "Search for" %>
<%= text_field_tag :q, params[:q] %>
<%= submit_tag "Go", name: nil %>
</p>
<% end %>
<ul>
<% @result.records.each_with_hit do |item, hit| %>
<p><%= item.title %></p>
<% end %>
</ul>
運行結果