利用slor实现索引查询

 项目里有一个查询模块,就是从特定的ftp站点扫描,然后利用solr来生成索引文件,提供查询下载服务。关于如何搭建和配置solr,参见http://www.jinsehupan.com/blog/?p=25 和官方的文档,写的很详细。

这里具体讲讲在利用solr开发时需要注意的方面。

项目使用的是spring。项目中有一个solrService类,它主要负责对索引的操作,像新增索引,更新索引和删除失效的索引等。项目需要引入apache-solr-solrj-1.3-dev.jar、apache-solr-common-1.3-dev.jar、apache-solr-1.3-dev.jar三个包。

首先在spring的配置文件里面配置solrService类

Xml代码    SELECT f.id as sid, f.file_name as title, f.file_size as "size", f.file_time as time, f.category_id as c_i, ... FROM t_file f, t_site s, t_area a WHERE f.site_id=s.id AND a.id=s.area_id AND f.file_type=0 AND f.id {SOLR} ORDER BY f.id " quality="high" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer">  收藏代码
  1. <bean id="solrService" class="com.search.SolrService">  
  2.         <property name="jdbcDAO" ref="genericJdbcDAO" />  
  3.           
  4.         <!-- solrURL -->  
  5.         <property name="solrURL" value="http://localhost:8080/solr" />  
  6.         <!-- solr检索字段和数据库字段的对应关系,配置主键名,配置SQL -->          
  7.         <property name="sqlConfigMap">  
  8.         <map>  
  9.             <!--  
  10.             key:  
  11.                 需检索的主表(比如topic、article之类)对应的className  
  12.                 service监听这些bean的更新事件并作更新索引处理  
  13.             value:  
  14.                 pkBoName:  
  15.                     主键在BO中的属性名(如id、userId等)  
  16.                 sqlPart:   
  17.                     读取数据的SQL语句一部分,as成solr预定义名称  
  18.                     注意:WHERE条件最后要包含主键pk,且判断条件(>100之类)用“{SOLR}”代替,由service根据索引产生  
  19.                     如:where .... and id{SOLR}  
  20.                 sqlCount:  
  21.                     读取数据的SQL语句对应的count(*)语句,加入这个是为了能分页(分次)取数据  
  22.                     注意项同sqlPart说明(判断条件用“{SOLR}”代替)  
  23.                 pageSize:  
  24.                     分页读取时每页(每次)读取的记录条数,根据实际情况调整  
  25.                 sqlGetpk:  
  26.                     读取主键sid的SQL语句,加入这个是为了能同步删除的记录(对比数据表的id和solr存储的sid)  
  27.                 // solr预定义类型:  
  28.                     sid (solr内部唯一标识,sid生成方式为: {"去package的className"_"id"})  
  29.                     category (string), author (string), url (string), time (date),  
  30.                     title (text与string的区别是text类型有分词), content (text不存储), keyword (text),  
  31.                     summary (仅存储不索引 如果没有指定则根据content截断200字符生成), ip (string),  
  32.                     size (slong), indextime (date 添加索引时间 默认为NOW)  
  33.                     此外支持如下*匹配(有存储有索引)类型:  
  34.                         *_i (sint), *_s (string), *_l (slong), *_t (text)  
  35.                         *_b (boolean), *_f (float), *_d (double), *_dt (date)  
  36.                     及以下*匹配(仅索引不存储)类型:  
  37.                         *_ii (sint), *_is (string), *_il (slong), *_it (text)  
  38.                         *_ib (boolean), *_if (float), *_id (double), *_idt (date)  
  39.                     及以下*匹配(仅存储不索引)类型:  
  40.                         *_si (sint), *_ss (string), *_sl (slong)  
  41.                         *_sb (boolean), *_sf (float), *_sd (double), *_sdt (date)  
  42.             如:  
  43.             <entry key="com.wiscom.union.bo.Topic">  
  44.                 <bean class="com.wiscom.generic.base.search.SqlConfig">  
  45.                     <property name="pkBoName" value="id" />  
  46.                     <property name="sqlPart">  
  47.                         <value>SELECT t.id as sid, t.topic_title as title,  
  48.                             u.username as author FROM t_topic t, t_user u  
  49.                             WHERE t.userid=u.id AND t.id {SOLR} ORDER BY t.id</value>  
  50.                     <property name="sqlCount" value="SELECT count(*) FROM t_topic WHERE id {SOLR}" />  
  51.                     <property name="pageSize" value="100" />  
  52.                     <property name="sqlGetpk" value="SELECT id as sid FROM t_topic WHERE 1=1" />  
  53.                     </property>  
  54.                 </bean>  
  55.             </entry>  
  56.             则保存到solr索引时,sid: {Topic_"id"}  
  57.             -->  
  58.             <entry key="com.wiscom.union.bo.File">  
  59.                 <bean class="com.wiscom.generic.base.search.SqlConfig">  
  60.                     <property name="pkBoName" value="id" />  
  61.                     <property name="sqlPart">  
  62.                         <value>SELECT f.id as sid,  
  63.                           f.file_name as title,  
  64.                           f.file_size as "size",  
  65.                           f.file_time as time,  
  66.                           f.category_id as c_i,  
  67.                           ...  
  68.                           FROM t_file f, t_site s, t_area a WHERE f.site_id=s.id AND a.id=s.area_id AND f.file_type=0 AND f.id {SOLR} ORDER BY f.id</value>  
  69.                     </property>  
  70.                     <property name="sqlCount" value="SELECT count(*) FROM t_file WHERE id {SOLR}" />  
  71.                     <property name="pageSize" value="1000" /> <!-- 一次最多操作的数目-->  
  72.                     <property name="sqlGetpk" value="SELECT id as sid FROM t_file WHERE 1=1 ORDER BY id" />  
  73.                 </bean>  
  74.             </entry>  
  75.         </map>  
  76.         </property>  
  77.     </bean>  

 注释已经很详细了。sqlPart部分的as 什么什么,是在solr的配置文件schema.xml做的类型定义。这里需要注意的是solr对这些类型定义别名是区分大小写的,在使用oracle数据库时需要注意这个问题,因为oracle查询得到的列名都是大写的,大小写不一致会导致查询不到结果。

在solrService里以新增index文件为例。首先是要从数据库中得到相应的数据,然后使用SolrInputDocument来生成要提交的doc文档对象。

Java代码    收藏代码
  1. ...  
  2. // 生成doc  
  3. SolrInputDocument doc = new SolrInputDocument();  
  4. doc.addField(fieldName, fieldValue);  
  5. docsList.add(doc);  
  6. ...  
  7. // solrURLURL 为URL对象  
  8. SolrServer server = new CommonsHttpSolrServer(solrURLURL);  
  9. server.add(docsList);  
  10. // 提交  
  11. server.commit();  
  12. ...  

  solr虽然是基于lucene,但是在处理更新操作时是不同的,lucene没有更新操作,只能先将相应的索引删除,然后再添加新的索引。solr则不需要这么做,如果提交的doc的主键已经存在则会做更新操作,不需要我们自己做什么工作,所以更新操作和新增是一样的。我们的做法是在做ftp爬虫时区分哪些数据是更新的,哪些数据是删除的,然后把它们的主键提交到索引文件里,当solr的程序启动时,根据这些主键来对索引进行相应的操作。

  删除操作方法如下:

Java代码    收藏代码
  1. server.deleteById(id); //根据索引的主键删除  
  2. server.deleteByQuery("sid:SoLRdelPkS@*"); // 根据查询删除  
  3. server.commit();  

   最后需求注意的问题是中文的查询问题,中文分词可以采用庖丁分词,网上有很多介绍。这里有个问题是在Linux下使用tomcat做容器时,在提交中文时会出现乱码的问题。最终使用的resin才解决了问题 。

 

   在分析查询结果是采用的是SAXReader包。

Java代码 

你可能感兴趣的:(slor搜索查询,slor)