您的位置:首页 > 数据库 > Oracle

使用lucene solr搭建Oracle数据库全文搜索服务

2012-11-18 22:25 716 查看
最近在做地名搜索定位的项目,相当于对经过地理编码的数据进行搜索

主要是将数据库中的数据导入到solr中并发布出来,数据量目前是1500万条左右

记录一下大概的工作步骤

1 基本部署

目前solr最高版本为4.0

由于项目服务器使用JDK1.5, 在本例中使用3.6.1版本, 服务器使用TomCat 及Weblogic

下载并解压apache-solr-3.6.1.zip,

将文件dist\apache-solr-3.6.1.war改为zip后缀并解压

解压出来的文件放到 tomcat\webapps\solr\

注意:如果要部署到weblogic中,建议先修改apache-solr-3.6.1.zip中的META-INF\MANIFEST.MF中的

Implementation-Version值,去掉其中的冒号,以免weblogic自动识别版本号时出现非法字符导致部署失败

新建一个文件夹目录,以保存solr索引文件,比如:D:\Solr_Home\solr

在此目录下新建两个目录,lib, cores

将apache-solr-3.6.1.zip中的dist文件夹下所有文件及文件夹复制到lib目录下

将apache-solr-3.6.1.zip中的示例项目文件夹example\example-DIH\solr\db复制到cores目录下

打开db\conf\solrconfig.xml,找到apache-solr-dataimporthandler的lib配置段

修改其lib位置如下:

<lib dir="../../lib/" regex="apache-solr-dataimporthandler-.*\.jar" />


将example\example-DIH\solr\solr.xml复制到D:\Solr_Home\solr目录下

修改solr.xml,将cores段修改为如下文本:
<cores adminPath="/admin/cores">
<core instanceDir="/cores/db" name="db"/>
</cores>


用编辑器打开tomcat\webapps\solr\WEB-INF\web.xml

将env-entry段取消注释

修改其中的env-entry-value值为D:\Solr_Home\solr

(此即为solr自带样例)

如下:
<env-entry>
<env-entry-name>solr/home</env-entry-name>
<env-entry-value>E:/solr_home/solr</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>


启动tomcat,然后打开localhost:8080/solr/ 此时,能成功看到Welcome to Solr的页面,

点击Admin db 进入管理界面,可进行查询等操作

2 数据导入 索引建立

将数据库的表数据导入到solr中做查询,例如使用Oracle数据库,

表名为Address

有三列

name,x,y

可以通过select name,x,y from Address进行查询

打开db\conf\db-data-config.xml

修改dataSource段和document段如下:
<dataConfig>
<dataSource driver="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@127.0.0.1:1521:testoracle" user="test" password="test" batch-size="-1"/>

<document>
<entity name="user" query="select name,x,y from Address">
<field column="x" name="x" />
<field column="name" name="name" />
<field name="y" column="y" />
</entity>
</document>
</dataConfig>


其中entity相当于一条记录,field相当于记录的字段,与表内数据对应

batch-size是多少条记录提交一次,根据索引的大小,一般设置1000以内

打开conf\schema.xml文件

查找所有field段并注释掉

然后添加如下记录:
<field name="name" type="text" indexed="true" stored="true"/>
<field name="x" type="string" indexed="true" stored="true"/>
<field name="y"  type="string" indexed="true" stored="true"/>


修改uniqueKey及defaultSearchField,如下
<uniqueKey>name</uniqueKey>
<defaultSearchField>name</defaultSearchField>


将oracle的jdbc驱动包, ojdbc14.jar 复制到 D:\Solr_Home\solr\db\lib\ 目录下

 

重启tomcat,打开localhost:8080/solr/db/dataimport?command=full-import

不出意外的话,数据会很快导入到solr中,如果数据量比较大,

可通过地址查看导入过程:

localhost:8080/solr/db/dataimport

导入完成后可打开localhost:8080/solr/db/admin,在此页面中进行查询

注意,若查询中文,可能会遇到乱码或无法查询的情况,

对于tomcat需要修改tomcat\conf\server.xml中的connector段

加入URIEncoding="UTF-8",如下:

<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8" />
对于weblogic,修改solr\WEB-INF\weblogic.xml

在最后加入如下配置:
<charset-params>
<input-charset>
<resource-path>/*</resource-path>
<java-charset-name>UTF-8</java-charset-name>
</input-charset>
</charset-params>


另附:db2数据导入数据源配置:
<dataSource driver="com.ibm.db2.jcc.DB2Driver" url="jdbc:db2://127.0.0.1:50000/testdb" user="test" password="test" batch-size="-1"/>
weblogic中jndi数据源配置:
<dataSource name="test" jndiName="jdbc/test" type="JdbcDataSource" batch-size="-1"/>


3 中文分词配置

经过以上的配置,可以对中文进行查询了, 但效果并不好, 可使用分词工具提高搜索命中率

比较流行的中文分词有IKAnalyzer和mmseg4j 其中IKAnalyzer最新版的为2012_u6,可到code.google.com/p/ik-analyzer下载

但最新的包是基于jdk1.6构建的,作者目前并没有将最新的源码开放出来,故只能手动下载早期版本重新编译,若使用JDK1.6则不存在此问题

不过流程一样的,对于需要分词的字段类型, 可在schema.xml中进行配置

打开db\conf\schema.xml

找到<fieldType name="text" class="solr.TextField">

修改其中内容如下:
<fieldType name="text" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer" />
<!-- <analyzer class="org.ansj.lucene.AnsjAnalyzer" /> -->
<analyzer type="index">
<!-- <tokenizer class="solr.WhitespaceTokenizerFactory"/> -->
<tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" isMaxWordLength="false" />
<!-- <tokenizer class="org.ansj.solr.AnsjTokenizerFactory" isStemming="false" /> -->
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
<analyzer type="query">
<!-- <tokenizer class="solr.WhitespaceTokenizerFactory"/> -->
<tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" isMaxWordLength="false" />
<!-- <tokenizer class="org.ansj.solr.AnsjTokenizerFactory" isStemming="false" /> -->
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
</fieldType>


主要就是查询和索引所使用的分词类Tokenizer,mmseg4j与此类似,不再赘述

4 集群部署

可以按照mater-repeater-slave的架构进行集群配置

其中master为主要服务器,负责更新索引

repeater从master同步索引,并为slave提供索引源

slave从repeater同步索引

此架构可减少因多台slave机器同步索引对master造成的压力

配置很简单,将db分别复制到三台不同的机器

修改其solrconfig.xml文件

对于master机器(IP为192.168.1.101):

      
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="master">
<str name="replicateAfter">commit</str>
<str name="replicateAfter">startup</str>
<str name="confFiles">schema.xml,stopwords.txt</str>
</lst>
</requestHandler>
对于repeater机器(IP为192.168.1.102):

      
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="master">
<str name="replicateAfter">commit</str>
<str name="replicateAfter">startup</str>
<str name="confFiles">schema.xml,stopwords.txt</str>
</lst>
<lst name="slave">
<str name="masterUrl">http://192.168.1.101:8080/solr/db/replication</str>
<str name="pollInterval">00:00:60</str>
</lst>
</requestHandler>


对于slave机器(IP为其他)

     
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="slave">
<str name="masterUrl">http://192.168.1.102:8080/solr/db/replication</str>
<str name="pollInterval">00:00:60</str>
</lst>
</requestHandler>  
  此配置亦可应用于同一台机器的不同节点(cores)

5 多节点查询

在一台机器部署多个cores,可减轻同一磁盘区域的IO,分解压力,比如对于不同区域地名查询

可按照地市来分别建立cores,在db同级目录下建立其他core文件夹,并在solr.xml中增加节点配置信息,

如增加一个名为dbslave的core,solr.xml如下:

 
<cores adminPath="/admin/cores">
<core instanceDir="/cores/db" name="db"/>
<core instanceDir="/cores/dbslave" name="dbslave"/>
</cores>
  

单节点查询url如下:

  http://localhost:8080/solr/db/select/?q=%E5%92%8C%E5%B9%B3&version=2.2&start=0&rows=10&indent=on
若要同时查询两个core内容, 可拼接url如下:
http://localhost:8080/solr/db/select/?q=%E5%92%8C%E5%B9%B3&version=2.2&start=0&rows=10&indent=on&shards=localhost:8080/solr/db,localhost:8080/solr/dbslave
当然, 做客户端开发的话使用solr提供的solrj包,可简化相当多的操作

导入数据遇到问题:

实际使用中发现,无论是用DB2还是Oracle,导入大量数据时会报错(大概10万条),

org.apache.solr.handler.dataimport.JdbcDataSource closeConnection

FATAL: Ignoring Error when closing connection

查到这是一个已知的bug,编号是solr-2045
https://issues.apache.org/jira/browse/SOLR-2045
根据上面的patch,重新编译DataImportHandler的源码打包后解决

部署到RedHat 5 上的Weblogic遇到问题:

1 can not find core name in path,大概是这个提示,折腾很久之后发现是solrhome中的solr.xml配置中

对core的路径配置多了一个反斜杠,如下配置在windows环境下没有问题:

 <cores adminPath="/admin/cores">
<core instanceDir="/cores/db" name="db"/>
<core instanceDir="/cores/dbslave" name="dbslave"/>
</cores>
但在linux下要改成如下:

<cores adminPath="/admin/cores">
<core instanceDir="cores/db" name="db"/>
<core instanceDir="cores/dbslave" name="dbslave"/>
</cores>


2 启动weblogic是报告too many files

这个查了发现是linux系统对同时打开的文件数目有限制,

由于我将索引文件按区域分了将近400个core,

可能是因为solr启动时预读索引文件数目过多导致

使用ulimit -n 可查看当前的设置,使用

ulimit -n 409600来设置这个值

问题出在这里,但是怎么解决,网上众说纷纭,

最终是通过如下方法解决:

修改/etc/security/limits.conf,在文件末加上

* soft nofile 409600
* hard nofile 409600
查看 /etc/pam.d/login 确保文件中有:

session required  pam_limits.so


查看/etc/pam.d/su 确保文件中有:

session         required        pam_limits.so

最后,关于solr的集群或者说云计算的扩展,从youtube上找了个nutshell的应用实例视频,

搬运到搜狐视频了,有兴趣的可以看看,顺便赞一下搜狐视频,上面的美剧很给力,

 Scaling Solr in the Cloud http://url.cn/8rkrPE
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息