1?strong>开语
2?strong>概述
3?strong>渊源
4?strong>初识Solr
5?strong>Solr的安?/strong>
6?strong>Solr分词序
7?strong>Solr中文应用的一个实?/strong>
8?strong>Solr的检索运符
[开语]按照惯例应该写一技术文章了Q这ơ结合Lucene/Solr来分享一下开发经验?/span>
Lucene是一个用Java语言写的全文(g)索开发包QAPIQ,利用它可以实现强大的(g)索功能,它的详细介绍大家可以去Google上搜索一下,本文重点攑֜Solr相关的讨Z?/span>
[概述]目前国内研究Solr的h不多Q而且大多是因为项目开发需要。Solr师承LuceneQؓ(f)Apache基金?x)下的一个项目,具体的说它还是Lucene下的一个子目。Solrn豪门Q而且h自己的技术特点,填补了以往Lucene仅仅作ؓ(f)开发工具包的遗憾,它是一个完完整整地应用。换句话_(d)它是一个全文检索服务器Q它开即用,让我们能立马体会(x)到Lucene的强大功能,为Lucene产品化走Z一大步?br />
Solr分词原理演示界面
[渊源]最初,CNET Networks使用Lucene API来开发了一些应用,q在q个基础上生了Solr的雏形,后来Apache Software Foundation在Lucene目的支持下得到了SolrQ这已经?006q?月䆾的事了?006q??7日,Solr正是加入Apache基金?x)的孵化目Q在整个目孵化期间QSolr Ex地积累各U特性ƈ吸引了一个稳定的user体、developer体和Committer体Qƈ?q之后的17日正式酝酿成熟,在这之前已经成功发布?.1.0版。目前的E_版本?.2QSolr?月䆾?007Apacheq会(x)上大攑ּ彩,在今q?1月底来到香港参?007亚洲开源Y件峰?x),遗憾的是Z么不来北?-(
[初识Solr]Solr服务器不同于普通的关系型数据库Q不仅仅在于它核心本质的不同Q面向结构化和非l构化数据的不同Q,很大的不同还在于它的体系架构上。Solr服务器一般情况下需要部|于应用服务?Java容器上(如果是本机通信不涉?qing)RPC可以不用Java容器Q如采用嵌入方式使用SolrQ,无法独立工作于JVM上?br />
Solr架构?/strong>
Solr服务器可以存储数据ƈ通过索引对其q行快速高效检索。对外提供HTTP/XML和Json API接口Q这使得它能够在多语a环境下集成,比如针对它的客户端的开发。Solr目前的客L(fng)面向的有Java、PHP、Python、C#、Json和Ruby{,遗憾的是没有面向C/C++Q这也是本h目前在研I的Q,研究音乐搜烦(ch)分类的Brian Whitman曑֜Ҏ(gu)q_上用JNI技术在C代码中嵌入Solr实现(g)索,不过是一个Cocoa工程。有了这些客L(fng)Q用者能很方便地Solr集成到具体运用中。目前最完善的当属Java客户端SolrjQ以?qing)加入到Solr trunkQƈ在1.3版本中正式发布?/span>
如果不研I开发SolrQ只是用SolrQ只需要关注Solr的以下几个方面:(x)
1、Solr服务器的配置在solrconfig.xml中完成,包括对缓存,servlet的个性化配置{等Q即pȝ全局的配|;
2、烦(ch)引方法、烦(ch)引域Q字D)(j){等在schema.xml中完成,q个配置是针对Solr实例的;
3、烦(ch)引数据文仉认放在Solr文档根目录下的data/index目录下,q个路径可以通过W?炚w|,同时可以这个目录下的文件进行复制粘_(d)卛_完成索引的复用;
4、徏立烦(ch)引的旉相当长,我采用按词无字典索引方式?G110万条中文记录q行索引Q花了将q?个半时的时_(d)当然q个旉和很多因素有养I有兴的话大家可以留a和我讨论Q,相对而言Q在linux下徏索引旉要比windows下快很多Q可以用commit操作使新增烦(ch)引生效,同时注意索引的优化,索引优化也是很费资源和时间的Q但是优化烦(ch)引也是提高检索速度的重要方法,因此需要好好权衡这一点;
5、安装完后的Solr目录下有q么几个文g夹:(x)bin文g多w主要是用于徏立镜像和完成q程同步的脚本;conf文g夹下主要??点中提到的配|文Ӟadmin文g夹下是的主要是提供web理界面的文Ӟ
6、目前Solr1.2不具备安全性设计,没有用户l及(qing)权限讄Q在q行具体应用旉要注意安全,目前最有效的方法是通过应用服务器上的授权实现?br />
本文怹链接Q?a >http://www.jinsehupan.com/blog/?p=25
[Solr的安?/span>]Solr发行版中已经有一个用Jetty为servlet容器的小例子Q可以用这个例子来体验Q那正在在自己想部v的^台和应用服务器上该怎么一个步骤呢Q?/span>
要开始?SolrQ需安装以下软gQ?br />
1、Java 1.5 或更高版本;
2、Ant 1.6.x 或更高版本(用于~译理Solr工程Q个人推荐,当然可以使用eclipseQ;
3、Web 览器,用来查看理面Q官方徏议用FirefoxQ但实际没有发现和IE有什么差别)(j)Q?br />
4、servlet 容器Q如Tomcat 5.5Q不使用6版本Q。本文以Tomcat ?8080 端口上运行ؓ(f)例。如果运行的是其?servlet 容器或在其他的端口上q行Q则可能要修改代码中的URL才能讉KCZ应用E序?Solr?/span>
下面开始安装配|:(x)
1、用Ant~译工程或下载示例应用程序,Solr WAR 文g复制?servlet 容器的webapps目录中;
2、得到Solr文g夹,以备随后其复制到当前目录,可以使用ant build得到Q也可以在下载的压羃包中扑ֈQ以它ؓ(f)模板以备之后的修改;
3、可以通过以下三种方式之一讄 Solr 的主位置Q?br />
讄 java pȝ属?solr.solr.home Q没错,是 solr.solr.homeQ一般在嵌入式集成中用得多)(j)Q?br />
配置 java:comp/env/solr/home 的一?JNDI 查找指向 solr 目录Q徏?tomcat55/conf/Catalina/localhost/solr.xml文gQ注意这个xml文g名将是Solr实例名称Q?中的当前目录被指定ؓ(f)下面中的f:/solrhomeQ文件内容如下:(x)
在包?solr 目录的目录中启动 servlet 容器Q默认的 Solr ȝ录是当前工作目录下的 solrQ;
4、最后一点就是如果有CJKQ中日韩文字Q应用,出现q问题Q采用如下方法解冻I其实已经不算是solr配置问题Q而是应用服务器配|问题)(j)Q修改Tomcat的conf/server.xml文g中对于端口(本文?080Q的q接器统一资源~码为UTF-8Q因为Solr1.2内核支持UTF-8~码Q?/span>
[Solr分词序]Solr建立索引和对关键词进行查询都得对字串q行分词Q在向烦(ch)引库中添加全文检索类型的索引的时候,Solr?x)首先用I格q行分词Q然后把分词l果依次使用指定的过滤器q行qo(h)Q最后剩下的l果才会(x)加入到烦(ch)引库中以备查询。分词的序如下Q?br />
索引
1Q空格whitespaceTokenize
2Q过滤词StopFilter
3Q拆字WordDelimiterFilter
4Q小写过滤LowerCaseFilter
5Q英文相q词EnglishPorterFilter
6Q去除重复词RemoveDuplicatesTokenFilter
查询
1Q查询相q词
2Q过滤词
3Q拆?br />
4Q小写过?br />
5Q英文相q词
6Q去除重复词
以上是针对英文,中文的除了空|其他都类?/span>
[Solr中文应用的一个实?/span>]
1、首先配|schema.xmlQ这个相当于数据表配|文Ӟ它定义了加入索引的数据的数据cd的?.2版本的schema.xml主要包括types、fields和其他的一些缺省设|?/span>
A、首先需要在typesl点内定义一个FieldType子结点,包括name,class,positionIncrementGap{等一些参敎ͼname是q个FieldType的名Uͼclass指向org.apache.solr.analysis包里面对应的class名称Q用来定义这个类型的行ؓ(f)。在FieldType定义的时候最重要的就是定义这个类型的数据在徏立烦(ch)引和q行查询的时候要使用的分析器analyzer,包括分词和过滤。在例子中textq个FieldType在定义的时候,在index的analyzer中用solr.WhitespaceTokenizerFactoryq个分词包,是I格分词Q然后用solr.StopFilterFactoryQsolr.WordDelimiterFilterFactoryQsolr.LowerCaseFilterFactoryQsolr.EnglishPorterFilterFactoryQsolr.RemoveDuplicatesTokenFilterFactoryq几个过滤器。在向烦(ch)引库中添加textcd的烦(ch)引的时候,Solr?x)首先用I格q行分词Q然后把分词l果依次使用指定的过滤器q行qo(h)Q最后剩下的l果才会(x)加入到烦(ch)引库中以备查询。Solr的analysis包ƈ没有带支持中文的包,在这里我们采用lucene里的语言包(在下载后的solr压羃包内Qlib目录下有一个lucene-analyzers-2.2.0.jar包,里面含有中文处理的cn和cjkc)(j)Q有cn和cjk两个cd以支持中文。我们采用cjkc,q在schema.xml中加入如下配|:(x)
支持cd定义完成了?/span>
B、接下来的工作就是在fieldsl点内定义具体的字段Q类似数据库中的字段Q,是filedQfiled定义包括name,typeQؓ(f)之前定义q的各种FieldTypeQ?indexedQ是否被索引Q?storedQ是否被储存Q,multiValuedQ是否有多个|(j){等。例如定义如下:(x)
field的定义相当重要,有几个技巧需注意一下,对可能存在多值得字段量讄multiValued属性ؓ(f)trueQ避免徏索引是抛出错误;如果不需要存储相应字D|量stored属性设为false?/span>
C、徏议徏立了一个拷贝字D,所有的全文字段复制C个字D中Q以便进行统一的检索:(x)
q在拯字段l点处完成拷贝设|:(x)
D、除此之外,q可以定义动态字D,所谓动态字D就是不用指定具体的名称Q只要定义字D名U的规则Q例如定义一个dynamicFieldQname?_iQ定义它的type为textQ那么在使用q个字段的时候,M以_il尾的字D都被认为是W合q个定义的,例如name_iQgender_iQschool_i{?/span>
2、配|solrconfig.xmlQ用来配|Solr的一些系l属性,比较重要的一个就是可以通过更改其中的dataDir属性来指定索引文g的存放位|,对于有大数据量的情况下还要进行自动commit操作配置Q以下设|ؓ(f)当内存烦(ch)引量辑ֈ20W条时自动q行往盘写操作,以免堆溢出,q也是解军_个入库xml文g最好不要超q?0M的有效方法:(x)
3、配|好q些后,需要重新启动Solr服务器配置生效Q然后向其中d数据?/span>
4、添加数据是通过向服务器的update Servlet POST xml格式的数据来实现的,xmll构是这L(fng)add中间有很多个docQ每个doc中有很多个field。添加到索引库中的每条记录都必须指定唯一的数字id来唯一标识q条索引。徏立好xml文gQ例如solr.xmlQ之后,在exampledocs目录下执行:(x)java -jar post.jar solr.xml来添加烦(ch)引数据。对于post的jar包,如果重新配置了应用服务器Q如使用了comcatQ端口改?080Q实例名U改为solrx了需要重新生成相应的post.jar包进行操作?/span>
另附ronghao实现中文分词的案例供大家参考:(x)
对全文检索而言Q中文分词非常的重要Q这里采用了qieqie庖丁分词Q非怸错:(x)Q)(j)。集成非常的Ҏ(gu)Q我下蝲的是2.0.4-alpha2版本Q其中它支持最多切分和按最大切分。创q一个中文TokenizerFactoryl承自solr的BaseTokenizerFactory?/span>
**
* Created by IntelliJ IDEA.
* User: ronghao
* Date: 2007-11-3
* Time: 14:40:59
* 中文切词 对庖丁切词的装
*/
public class ChineseTokenizerFactory extends BaseTokenizerFactory {
/**
* 最多切?默认模式
*/
public static final String MOST_WORDS_MODE = “most-words”;
/**
* 按最大切?/span>
*/
public static final String MAX_WORD_LENGTH_MODE = “max-word-length”;
private String mode = null;
public void setMode(String mode) {
if (mode==null||MOST_WORDS_MODE.equalsIgnoreCase(mode)
|| “default”.equalsIgnoreCase(mode)) {
this.mode=MOST_WORDS_MODE;
} else if (MAX_WORD_LENGTH_MODE.equalsIgnoreCase(mode)) {
this.mode=MAX_WORD_LENGTH_MODE;
}
else {
throw new IllegalArgumentException(”不合法的分析器Mode参数讄:” + mode);
}
}
@Override
public void init(Map args) {
super.init(args);
setMode(args.get(”mode”));
}
public TokenStream create(Reader input) {
return new PaodingTokenizer(input, PaodingMaker.make(),
createTokenCollector());
}
private TokenCollector createTokenCollector() {
if( MOST_WORDS_MODE.equals(mode))
return new MostWordsTokenCollector();
if( MAX_WORD_LENGTH_MODE.equals(mode))
return new MaxWordLengthTokenCollector();
throw new Error(”never happened”);
}
}
在schema.xml的字Dtext配置里加入该分词器?/span>
1. <fieldtype name="text" class="solr.TextField" positionIncrementGap="100">
2.
3. <analyzer type="index">
4.
5. <tokenizer class="com.ronghao.fulltextsearch.analyzer.ChineseTokenizerFactory" mode="most-words"/>
6.
7.
8. <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
9.
10. <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
11.
12. <filter class="solr.LowerCaseFilterFactory"/>
13.
14.
15. <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
16.
17. </analyzer>
18.
19. <analyzer type="query">
20.
21. <tokenizer class="com.ronghao.fulltextsearch.analyzer.ChineseTokenizerFactory" mode="most-words"/>
22.
23. <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
24.
25. <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
26.
27. <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0"/>
28.
29. <filter class="solr.LowerCaseFilterFactory"/>
30.
31. <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
32.
33. </analyzer>
34.
35. </fieldtype>
完成后重启tomcatQ即可在http://localhost:8080/solr/admin/analysis.jsp
体验到庖丁的中文分词。注意要paoding-analysis.jar复制到solr的lib下,注意修改jar包里字典的home?/span>
[Solr的检索运符]
“:” 指定字段查指定|如返回所有?:*²
“?”²表示单个L字符的通配
“*” 表示多个L字符的通配Q不能在(g)索的开始?或?W号Q?/span>²
“~”²表示模糊(g)索,如检索拼写类g”roam”的项q样写:(x)roam~找到Ş如foam和roams的单词;roam~0.8Q检索返回相似度?.8以上的记录?br />
²邻近(g)索,如检索相?0个单词的”apache”?#8221;jakarta”Q?#8221;jakarta apache”~10
“^”²控制相关度检索,如检索jakarta apacheQ同时希望去?#8221;jakarta”的相兛_更加好,那么在其后加?#8221;^”W号和增量|即jakarta^4 apache
布尔操作WAND、||²
布尔操作WOR?/span>²&&
布尔操作WNOT??²Q排除操作符不能单独与项使用构成查询Q?br />
“+” 存在操作W,要求W号”+”后的必d文档相应的域中存?/span>²
( ) 用于构成子查?/span>²
² [] 包含范围(g)索,如检索某旉D记录,包含头尾Qdate:[200707 TO 200710]
{}²不包含范围检索,如检索某旉D记录,不包含头?br />
date:{200707 TO 200710}
" 转义操作W,Ҏ(gu)字符包括+ -² && || ! ( ) { } [ ] ^ ” ~ * ? : "