在實(shí)際應(yīng)用中如果可以讓用戶快速的搜索出自己想要的內(nèi)容,這將會(huì)是一個(gè)很有用的功能。那么要怎么來實(shí)現(xiàn)呢?
像簡單一點(diǎn)的方法可以使用 SQL 的 LIKE 來實(shí)現(xiàn),如
SELECT * FROM articles WHERE title LIKE '%小蘋果%';
但這樣實(shí)現(xiàn)對(duì)數(shù)據(jù)量很大的表,其實(shí)是相當(dāng)耗時(shí)的。而且在其它業(yè)務(wù)下,我們可以會(huì)對(duì)用戶提交的搜索詞,進(jìn)行分詞。在分詞后,上面的SQL 可能就變成
SELECT * FROM articles WHERE title ?LIKE '%小蘋果%' OR LIKE '%蘋果%' OR LIKE '%小%';
這樣效率肯定更低了。這時(shí)候我們可以使用 第三方的搜索程序,來減少數(shù)據(jù)庫的壓力,像 elasticsearch,Solr 等等。
我們這里選擇 elasticsearch,具體可以看這里 Elasticsearch 與 Solr
如果還不知道 elasticsearch,請(qǐng)選 ElasticSearch 入門
安裝 Gem
Rails 下使用 ElasticSearch ,可以使用 elasticsearch-rails 這個(gè) Gem
# Gemfile
# 搜索
gem 'elasticsearch-model'
gem 'elasticsearch-rails'
$ bundle
配置 Model
打開要添加搜索的 model 類,添加如下內(nèi)容
# 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>

運(yùn)行結(jié)果