Sunspot 用 Ruby 的方式实现了与 Solr 搜索引擎的交互。底层是基于 Rsolr,而且提供了很方便的 DSL 接口实现建立索引和搜索。
gem 'sunspot_rails'
gem 'sunspot_solr', github: 'xhj/sunspot', require: 'sunspot_solr'
gem 'progress_bar'
备注:
rake sunspot:solr:reindex
时 会在 terminal 上等待较长时间。 安装生成默认的配置信息
rails generate sunspot_rails:install
运行 Sunspot
rake sunspot:solr:start #后台运行
rake sunspot:solr:run #在前台运行
rake sunspot:solr:start #后台运行
设置 model
class User
...
searchable do
text :name
end
...
end
建立索引
rake sunspot:solr:reindex
在 console
s = User.search do
fulltext '张小三'
end
puts s.results
使用 mmseg 之前
s = Section.search do
fulltext '张三'
end
puts s.results 为空
修改配置信息 使得在 index 和 query 的时候 都使用 mmseg4j 分词算法
文件 wheel-admin/solr/conf/schema.xml 62 行左右,修改为如下:
<fieldType name="text" class="solr.TextField" omitNorms="false">
<analyzer type="index">
<tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="max-word" dicPath="mmseg4j_dict"/>
<filter class="solr.StandardFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="max-word" dicPath="mmseg4j_dict"/>
<filter class="solr.StandardFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.PositionFilterFactory" />
</analyzer>
</fieldType>
重新建立索引
rake sunspot:solr:reindex
在 wheel-web 的 console
s = Section.search do
fulltext '张三'
end
puts s.results.map(&:title)
["张小三",
...]
备注:默认的排序是 按照得分情况进行的。比如:
puts s.hits[0].score
mmseg 算法有两种分词方法:simple 和 complex,都是基于正向最大匹配。complex 加了四个规则过虑。官方说:词语的正确识别率达到了 98.41%。mmseg4j 已经实现了这两种分词算法。
1.5 版的分词速度 simple 算法是 1100kb/s左右、complex算法是 700kb/s左右,(测试机:AMD athlon 64 2800+ 1G 内存 xp)。
1.6 版在 complex 基础上实现了最多分词 (max-word)。“很好听” -> "很好 | 好听"; “中华人民共和国” -> "中华 | 华人 | 共和 | 国"; “中国人民银行” -> "中国 | 人民 | 银行"。
1.7-beta 版,目前 complex 1200kb/s左右, simple 1900kb/s左右, 但内存开销了 50M 左右。上几个版都是在 10M 左右。
1.8 后,增加 CutLetterDigitFilter 过虑器,切分“字母和数”混在一起的过虑器。比如:mb991ch 切为 "mb 991 ch"。
目前我们使用的时 mmseg 1.9
默认情况 每次 http 都会 commit。所以实时性 还是很不错的。
修改 config/sunspot.yml
production:
solr:
hostname: localhost
port: 8983
log_level: WARNING
path: /solr/default
** path: /solr/default instead of path: /solr/productionon**
利用 capistrano 部署 Solr,相关脚本如下:
after "deploy:update_code", "solr:symlink"
namespace :solr do
desc "start solr"
task :start, :roles => :app, :except => { :no_release => true } do
run "cd #{application_path} && RAILS_ENV=#{rails_env} bundle exec rake sunspot:solr:start"
end
desc "stop solr"
task :stop, :roles => :app, :except => { :no_release => true } do
run "cd #{application_path} && RAILS_ENV=#{rails_env} bundle exec rake sunspot:solr:stop"
end
desc "reindex the whole database"
task :reindex, :roles => :app do
run "cd #{application_path} && RAILS_ENV=#{rails_env} bundle exec rake sunspot:solr:reindex"
end
desc "Symlink in-progress deployment to a shared Solr index"
task :symlink, :except => { :no_release => true } do
#创建solr所需要的目录
run "cd #{deploy_to} && mkdir -p #{shared_path}/solr/data"
run "cd #{deploy_to} && mkdir -p #{shared_path}/solr/pids"
run "ln -s #{shared_path}/solr/data/ #{release_path}/solr/data"
run "ln -s #{shared_path}/solr/pids/ #{release_path}/solr/pids"
end
end
Solr 和 ElasticSearch 比较:
Solr 和 Sphinx 比较:
Example:
s = Sunspot.search(Post) do
with(:blog_id, 1)
facet(:category_ids)
end
# facet 告诉Solr 返回的结果包括 blog id 为1的category_ids
puts s.results[0].category_ids