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

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

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


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值