原先我是使用 pg_search 包做搜索功能,但搜索效果很差,由于没有安装中文分词库,所以模糊搜索几乎不可用。
所以我想优化搜索功能,刚开始是准备自部署 meilisearch 服务端来完成,初始代码写完后,却一直无法完成 ActionText 的索引,遂放弃。
随后简单对比了几家提供搜索功能的服务商,只有 Algolia 提供了免费层,1万次/月的搜索次数,1百万条索引记录,非常慷慨,而且它也是 Hacker News 的全文搜索后端,很好用。
Algolia 支持的数据导入方式非常丰富,除了 api 外,还提供了主流 CMS 的插件、爬虫、文件的导入方法:
algolia import data methods
这里我使用了 Rails 的SDK进行导入,步骤如下:
1. 添加包到 Gemfile 并安装
所以我想优化搜索功能,刚开始是准备自部署 meilisearch 服务端来完成,初始代码写完后,却一直无法完成 ActionText 的索引,遂放弃。
随后简单对比了几家提供搜索功能的服务商,只有 Algolia 提供了免费层,1万次/月的搜索次数,1百万条索引记录,非常慷慨,而且它也是 Hacker News 的全文搜索后端,很好用。
Algolia 支持的数据导入方式非常丰富,除了 api 外,还提供了主流 CMS 的插件、爬虫、文件的导入方法:
这里我使用了 Rails 的SDK进行导入,步骤如下:
1. 添加包到 Gemfile 并安装
gem "algoliasearch-rails"
2. 添加初始化文件:config/initializers/algoliasearch.rb
AlgoliaSearch.configuration = {
application_id: ENV["ALGOLIASEARCH_APP_ID"],
api_key: ENV["ALGOLIASEARCH_API_KEY"],
# pagination_backend: :will_paginate # 如果使用了 will_paginate 分页,可添加该行
}
3. 在需要索引的模型中,添加搜索功能,比如我在 Article 模型中添加的代码:
class Article < ApplicationRecord
has_rich_text :content
# ...
include AlgoliaSearch
algoliasearch if: :should_index? do
attribute :title, :slug, :description, :plain_content
attribute :plain_content do
text = content.to_plain_text
algolia_max_characters = ENV.fetch("ALGOLIA_MAX_CHARACTERS", "3500").to_i
if text.size > algolia_max_characters
text = text.truncate(algolia_max_characters)
end
text
end
searchableAttributes [ "title", "slug", "description", "plain_content" ]
end
def should_index?
status == "publish" || status == "shared"
end
#...
end
需要注意的是,免费层的每个索引记录大小需要限制在 10kb 以内,但我使用 bytesize 方法时无法成功添加,提示无效的 object,所以这里我直接使用字符数。
然后在 articles_controller 中添加相关处理代码
然后在 articles_controller 中添加相关处理代码
def index
respond_to do |format|
format.html {
@page = params[:page].present? ? params[:page].to_i : 1
@per_page = 10
if params[:q].present?
# 使用Algolia搜索
algolia_results = Article.algolia_search(params[:q], { hitsPerPage: @per_page, page: @page - 1 }) # Algolia页码从0开始
# 获取Algolia的结果总数
@total_count = algolia_results.size
@articles = algolia_results
else
# 不搜索,只分页
@articles = Article.published
.includes(:rich_text_content)
.order(created_at: :desc)
.paginate(page: @page, per_page: @per_page)
@total_count = @articles.total_entries
end
}
# ...
end
end
在 view 中添加搜索代码
<%= form_tag root_path, method: :get, class: 'search-form' do %>
<%= search_field_tag :q, params[:q], placeholder: 'Search...' %>
<%= submit_tag 'Search' %>
<% end %>
最后,设置好认证信息和环境变量后,在 rails console 中进行首次索引:Article.reindex!
如果想清除所有索引,则执行:Article.clear_index!
完成
完成