在实际应用中如果可以让用户快速的搜索出自己想要的内容,这将会是一个很有用的功能。那么要怎么来实现呢?
像简单一点的方法可以使用 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>