首页 > 代码库 > solr
solr
Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。
Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。
Solr优点:
(1)Solr 可以对几乎任何对象进行索引,该对象甚至可以不是ActiveRecord.而Sphinx和RDBMS耦合过于紧密
(2)Solr 索引的对象ID可以非空或者是字符串,而Sphinx要求被索引对象必须拥有非0整数作为ID
(3)Solr 支持Boolean作为查询条件搜索,更加方便 Solr 支持Facets,而Sphinx为此需要做更多工作
(4)Solr是对lucene的包装。所以他可以享受lucene每次升级带来的便利。
一、基本命令:
Rails3安装:
(1)Gemfile 添加 gem ‘sunspot_rails‘, ‘~> 1.2.1‘
(2)bundle install
(3)使用 rails g sunspot_rails:install 生成配置文件(config/sunspot.yml)
Solr服务器启动:
rake sunspot:solr:start(后台进程启动) 或者 rake sunspot:solr:run
Solr停止: rake sunspot:solr:stop
服务器建立索引:rake sunspot:reindex
可按model单独索引:rake sunspot:reindex[1000:Company]
示例:nohup rake sunspot:reindex[1000:Company] --trace RAILS_ENV=production &
查看Solr服务:http://railsserver:{sunspot.yml[RAILS_ENV][port]}/solr(http://127.0.0.1:8983/solr)
二、配置:
Schema.xml配置:
<analyzer type=‘index‘>
<charFilter class="solr.HTMLStripCharFilterFactory"/>
<filter class="solr.ASCIIFoldingFilterFactory"/>
<tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" isMaxWordLength="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
</analyzer>
<analyzer type=‘query‘>
<charFilter class="solr.HTMLStripCharFilterFactory"/>
<filter class="solr.ASCIIFoldingFilterFactory"/>
<tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" isMaxWordLength="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
</analyzer>
上述代码分为索引(index)和查询(query),对词语进行处理,分为五步:
(1)<charFilter class="solr.HTMLStripCharFilterFactory"/> 对html字符进行过滤;
(2)<filter class="solr.ASCIIFoldingFilterFactory"/> 过滤特殊字符;
(3)<tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" isMaxWordLength="true"/> IK分词;isMaxWordLength设置是否最大词长切分;
(4)<filter class="solr.LowerCaseFilterFactory"/> 小写转换
(5)<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/> 设置同义词词库;
synonyms格式:pvc => 聚氯乙烯
更多过滤分析条件见:http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
IKAnalyzer.cfg.xml 配置:
文件路径(测试机上):/opt/ruby-enterprise-1.8.7/lib/ruby/gems/1.8/gems/sunspot-1.2.1/solr/webapps/solr/WEB-INF/classes
文档: http://ik-analyzer.googlecode.com/files/IKAnalyzer%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D%E5%99%A8V3.2.8%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C.pdf
http://linliangyi2007.iteye.com/blog/501228
自定义词库:
<properties>
<entry key="ext_dict">/mydict.dic;/com/mycompany/dic/mydict2.dic;</entry>
</properties>
注意:mydict.dic与IKAnalyzer.cfg.xml同目录
屏蔽词配置:
<properties>
<entry key="ext_stopwords">/ext_stopword.dic</entry>
</properties>
注意:ext_stopword.dic与IKAnalyzer.cfg.xml同目录
三、索引方法:
Model索引定义(以price为例):
searchable (:auto_index => true,:auto_remove => true) do
text :full_name, :stored => true
string :company_name, :stored => true
string :brand_name, :stored => true do
self.try(:product).try(:brand).try(:name)
end
integer :brand_id,:references => Brand, :stored => true
integer :company_id,:references => Company, :stored => true
integer :attr_value_ids, :references => BaseMaterialTypeAttrValue, :multiple => true, :stored => true
time :updated_at,:trie => true, :stored => true
end
其中full_name、company_name等是自定义的函数,返回相应的值;自定义索引函数中尽量全用try,否则索引过程中会出现索引错误,例如brand_name
索引定义参数介绍:
(1)text :表示可以部分匹配,索引时是按分词索引
(2)string:完全匹配,被完整索引
(3)integer,long:整数
(4)float,double:浮点数
(5)time:data/time,相当于ruby的time class
(6)boolean:true、false
属性字段的几个参数:
(1)multiple:索引多个值
(2)references:引用类
(3)stored:是否存储到索引
(4)trie:Boolean: Numeric and time fields only;能使进行range搜索时速度更快。
实时建立索引方法:
(1)Sunspot.index(Objects)
Sunspot.commit
(2)Sunspot.index!(Objects)
(3)删除索引Sunspot.remove (*objects) ,然后Sunspot.commit
(4)删除索引Sunspot.remove! (*objects)
(5)在索引函数中加入searchable (:auto_index => true,:auto_remove => true) do 也可实时索引;
四、搜索:
两种搜索写法,例如:
(1)@results = Sunspot.new_search(Price)
@results.build { keywords(params[:search][:value], :query_phrase_slop => 1000, :phrase_slop => 1000, :highlight => true, :exclude_fields => [:search_key,:notes], :boost_fields => [:full_name => 5, :description => 4, :base_material_type_description => 3])}
@results.build { with(:status).equal_to("released")}
@results.build { without(:product_id).equal_to(nil)}
@results.build { order_by(:score,:desc) }
@results.build { order_by(:updated_at,:desc) }
@results.build { facet(:brand_id) }
@results.build { facet(:attr_value_ids) }
@results.execute!
(2)Sunspot.search(Price) do
keywords(params[:search][:value], :fields => [:full_name, :description], :highlight => true, :minimum_match => 0)
with(:updated_at).greater_than(30.days.ago.to_time)
paginate(:page => params[:page] || 1,:per_page => session[:per_page])
facet(:attr_value_ids)
end
限制方法有:
(1)with
(2)without
(3)order_by
(4)facet:面搜索
(5)paginate:传入rails中的will paginate分页参数
限制条件有:
(1)equal_to
(2)less_than
(3)greater_than
(4)between
(5)any_of 匹配任意一项,值为数组,如with(:attr_value_ids).any_of(params[:search][:attr_value_ids])
(6)all_of 匹配全部,值为数组
Any_of 和 all_of 可以分别表示or 、and逻辑,可以互相包含,如:
any_of do
with(:expired_at).greater_than(Time.now)
with(:expired_at, nil)
all_of do
with(:publshed_at).less_than(Time.now)
with(:author_id).equal_to(999)
end
end
keyword的其它参数详见:http://outoftime.github.com/sunspot/docs/classes/Sunspot/DSL/Fulltext.html
五、页面展示部分:
调用检索结果:
(1)@search.hits 索引的数据,直接从所用文档中得到数据
(2)@search.results 得到的数据集是从数据库中反查出来的数据
(3)@search.each_hit_with_result do |hit, result| ,同上
(4)hit.result 可用hit从数据库中查出对象
(5)hit.score 匹配度,搜索时可按score排序
(6)hit.stored(:name) 直接从索引文档中取得存储的参数
(7)与will_paginate的结合:will_paginate(@search.hits)
(8)高亮显示关键词:如
Search方法中搜索关键词语句中 加 :highlight => true
页面调用:hit.highlight(:body).format { |fragment| content_tag(:em, fragment) }
遇到的问题:页面调用hit.highlight(:body),如果body字段
含有所检索关键词时,hit.highlight(:body)为空会报错,需要对highlight(:body)进行判断,如果为空则调用hit.stored(:body)显示。
(9)分面搜索: 调用方法
@search.facet(:attr_value_ids).rows do |row|
值 row.value
对应记录数量row.count
end
solr filter 文档
http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
sunspot:
http://outoftime.github.com/sunspot/docs/classes/Sunspot/DSL/Fulltext.html
http://outoftime.github.com/sunspot/docs/classes/Sunspot/Search/AbstractSearch.html