·什么是Solr?
Solr是基于lucene搭建的java搜索引擎服务端,是一个搜索中心式的程序。
·Solr的组成:
Solr由一个服务端程序,若干个搜索模块core,和一套java客户端组件Solrj组成。core运行在服务端之上,可以把一个core理解成一个网站的搜索服务提供者,虽然一个core里面可以配置多个网站,但并不建议这么做。所有的core都存放在一个目录下,这个目录叫做solrHome,这是Solr安装中必须配置的一个文件夹目录。
·Solr的特性:
Solr支持lucene的所有功能,而且通过http和java接口的方式完整的包装了这些功能。Solr添加了DataImport数据导入,UI管理界面,在线core管理,搜索集群等企业级特性。Solr支持非常多的索引数据源,有数据库、数据文件(如CSV)、甚至还有HTTP、RSS、EMAIL这样的数据源。这使得Solr无论是应对新开发的系统还是为旧系统添加全文检索都变得十分简单。
·Solr服务端的安装:
Solr自大于4.7.2的版本之后要求必须使用jdk1.7以上和相应的servlet容器。我们这里使用的是4.7.2版本。Solr的官方包的dist目录下有一个war文件,解压它到任意Servlet容器,为工程添加example\lib\ext下的所有包,这是日志所必须的,将example/resources下的 log4j.properties 文件复制到WEB-INF/classes目录中作为日志配置文件。
Solr在其安装包example目录下提供了若干solrHome的文件夹,每个solrHome文件夹都包含了一些可以装载的core,我们可以找一个简单的solr文件夹并将其设置为solrHome。solrHome的设置方法有设置JNDI环境变量、虚拟机环境变量两种方法。JNDI变量可以设置在Context配置段中,也可以设置在web.xml中。都必须设置绝对路径。在我的工程结构中solrHome目录就在我的工程目录下,因此我采用自定义Filter设置虚拟机环境变量System.setProperty("solr.solr.home","...")的方式来设置solrHome。
启动容器,访问这个web工程可以看到Solr的UI管理界面。UI左边是菜单,Core Admin可以动态卸载和安装一些core。菜单下面是目前已安装的core列表。选择相应的core,可以看到有分词测试(Analysis)、数据源索引(DataImport)、查询测试(Query)
·数据库core安装:
example目录下有个example-DIH目录,把它设置成solrHome。这个目录包含数据库数据源的core,名字是db,这个core支持以配置sql的方式扫描数据库、建立索引。使用这个core需要我们把dist目录下包含dataimport字眼的两个jar包放到工程目录下。
db core包含两个主要的配置文件:db-data-config.xml数据库配置、schema.xml索引字段配置。
db-data-config.xml是配置数据库数据源和扫描SQL的地方,它负责连接数据库,执行SQL并且把数据列映射到索引文件的字段上。注意在配置field时列名是大小写敏感的。如果使用oracle数据库,因为oracle默认使用大写列名,就必须把column写成大写的。某些时候,我们的数据里面会包含CLOB字段和一些富文本字段,Solr提供一些transformers转换器,可以在保存索引前把这些字段进行预处理。比如可以把CLOB转换成String的ClobTransformer,可以剪除所有HTML标记的HTMLStripTransformer。我们也可以用java或脚本语言定义自己的transformers。
schema.xml配置了索引文件里面的字段类型types,和业务所需的字段fields。我们可以配置自定义的字段类型,比如在用到第三方分词包时,我们可以自定义一个field然后指定它们的分词器,停止词过滤器等。业务字段field可以配置其是否为索引字段index或存储字段store,对于某些只需要存储但不需要查询的字段时有用。field可以指定为multiValued类型的,这时一个field可以以数组的形式存储多个数据库字段的值,配合copyField元素,可以方便地应对多个字段的查询需求。比如a like ... OR b like ...这样的查询需求就可以把ab合为一个字段c,然后以 c like ...的形式进行查询。
数据库的core安装完后,在Solr的主界面上可以找到DataImport菜单,在那里可以执行清理、新增、删除、优化索引的操作。
·分词包安装:
提到lucene就不得不提到它强大的扩展分词包。笔者开始主要在庖丁解牛、mmseg4j和IKAnalyzer几款间选择。庖丁解牛由于太长时间没有更新已经不能适用新版的lucene。mmseg4j自带搜狗词库,网上对它的反响不错,不过mmseg1.9.1在solr4.7.2下运行时有bug让我不得不修改它的源代码。而且mmseg不支持停止词,按网上的说法配置field type的filter元素,在测试Query时完全看不出任何效果,不知道mmseg作者为什么要取消停止词的功能,毕竟大众在使用搜索引擎时并没有那么专业,他们会添加大量对搜索引擎无意义的词进去,比如“为什么.....”,“怎么样.....”,从而干扰搜索引擎。因此笔者最终采用IKAnalyzer(以下简称IK)。
IK的更新比较迅速,可以完美支持笔者的solr版本。IK的安装很简单,只要复制IKAnalyzer.cfg.xml,stopword.dic以及一个jar包到classpath下即可。接下来在scheme里面配置IK的一个字段类型,将field的类型指向它,就可以在Query测试中看到搜索结果了。IK支持自定义停止词库和扩展词库。如果是某些专业性的网站,比如教育网站、农业网站、学科网站,建议配置相应的扩展词库,可大大提升分词的准确性。
·客户端Solrj的安装:
Solr提供了一个java的客户端包Solrj供客户端程序使用,复制dist\solrj-lib下的所有包到客户端工程下即可。客户端有SolrSever、SolrQuery、QueryResponse、SolrDocumentList几个核心的类。
SolrSever是服务端,其query(SolrQuery query)方法接受一个查询请求,并返回QueryResponse,QueryResponse中包含了搜索用时getElapsedTime,和结果集getResults。getResults返回SolrDocumentList,这里面以键值对形式包含所有查询结果,以及总条数getNumFound。SolrDocumentList实现了List接口,这一点可以方便我们进行API隔离封装。
SolrQuery 是构造查询条件的类,Solr有一套自己的查询语法:主要包括“字段名:值”这样的字段描述;连接和补充字段的逻辑符号如OR、AND、~(模糊)、^(权重);查询结果排序、分页、过滤(在结果中查询)、分组等功能。将这些组成一个queryString查询字符串传给SolrQuery就可以进行查询。当然也可以把这些条件使用单独的API方法进行设置(类似Hibernate的Criteria API查询)。
由于Solr服务端的QueryParser没有对查询的关键词进行分词,所以我们会发现Solr的关键词查询都是“精确查询”的,这显然不符合需求。所以我们有必要在客户端调用solr的分词接口进行分词后再进行查询。Solrj的java接口里面没有分词接口,我们可以调用SolrServer的getClient方法来获得一个HttpClient对象,然后调用对应http接口进行分词。在url里面加上wt=json,可以指定http接口返回数据格式为json。
·补充:
Solr不同版本间的API和配置方法略有不同,本文所使用的Solr版本是4.7.2,环境是Tomcat6.0,JDK1.6