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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


最近在做地名搜索定位的项目,相当于对经过地理编码的数据进行搜索

主要是将数据库中的数据导入到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

摘自互联网
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: oracle数据库