用compass實現站內全文搜索引擎(二)


接下來是要建立搜索的服務類 

Java代碼  收藏代碼
  1. import java.util.ArrayList;  
  2. import java.util.HashMap;  
  3. import java.util.List;  
  4. import java.util.Map;  
  5. import org.compass.core.Compass;  
  6. import org.compass.core.CompassCallback;  
  7. import org.compass.core.CompassException;  
  8. import org.compass.core.CompassHighlighter;  
  9. import org.compass.core.CompassHits;  
  10. import org.compass.core.CompassQuery;  
  11. import org.compass.core.CompassSession;  
  12. import org.compass.core.CompassTemplate;  
  13. import org.compass.core.CompassTransaction;  
  14. import cn.rgcenter.entity.Article;  
  15.   
  16. public class SearchServiceBean {  
  17.   
  18.     private Compass compass;  
  19.     /** 索引查詢 * */  
  20.     public Map find(final String keywords, final String type, final int start,  
  21.             final int end) {  
  22.         CompassTemplate ct = new CompassTemplate(compass);  
  23.         return ct.execute(new CompassCallback<Map>() {  
  24.   
  25.             public Map doInCompass(CompassSession session)  
  26.                     throws CompassException {  
  27.                 List result = new ArrayList();  
  28.                 int totalSize = 0;  
  29.                 Map container = new HashMap();  
  30.                 CompassQuery query = session.queryBuilder().queryString(  
  31.                         keywords).toQuery();  
  32.                 CompassHits hits = query.setAliases(type).hits();  
  33.                 totalSize = hits.length();  
  34.                 container.put("size", totalSize);  
  35.                 int max = 0;  
  36.                 if (end < hits.length()) {  
  37.                     max = end;  
  38.                 } else {  
  39.                     max = hits.length();  
  40.                 }  
  41.   
  42.        if(type.equals("article")){  
  43.                     for (int i = start; i < max; i++) {  
  44.                         Article article = (Article) hits.data(i);  
  45.                         String title = hits.highlighter(i).fragment("title");  
  46.                         if (title != null) {  
  47.                             article.setTitle(title);  
  48.                         }  
  49.                         String content = hits.highlighter(i).setTextTokenizer(  
  50.                                 CompassHighlighter.TextTokenizer.AUTO)  
  51.                                 .fragment("content");  
  52.                         if (content != null) {  
  53.   
  54.                             article.setContent(content);  
  55.                         }  
  56.                         result.add(article);  
  57.                     }  
  58.                 }  
  59.                 container.put("result", result);  
  60.                 return container;  
  61.             }  
  62.         });  
  63.     }  
  64.   
  65.     public Compass getCompass() {  
  66.         return compass;  
  67.     }  
  68.   
  69.     public void setCompass(Compass compass) {  
  70.         this.compass = compass;  
  71.     }  
  72.   
  73. }  



索引的查詢主要是根據傳過來的參數,關鍵字keywords,是搜索的關鍵字,類型type,先判斷是不是要搜索文章,因爲一般來說,頁面的搜索引擎不單單隻搜索文章一個實體. 
至於int 和end是爲了分頁取出部分結果的. 
String title = hits.highlighter(i).fragment("title");這段是檢索titile這個屬性有沒有出現搜索的關鍵字,有就將它高亮(其實就是在關鍵字前後加個<font></font>的html標記設置顏色,等下可以看到在配置文件裏可以自由設置高亮的顏色). 
String content = hits.highlighter(i).setTextTokenizer( 
CompassHighlighter.TextTokenizer.AUTO) 
.fragment("content"); 

這段代碼和上面的title具有一樣的一樣的功能,另外還多了個很重要的功能,自動選擇正文中最匹配關鍵字的內容中的一部分輸出。因爲很多時候一篇文章幾千字,我們只想顯示有關鍵字的那部分的摘要,這時候這個功能就很方便. 


這之後還要寫一個建立索引的服務類,讓服務器啓動的時候或者定時重建索引. 

Java代碼  收藏代碼
  1. import org.compass.gps.CompassGps;  
  2. import org.springframework.beans.factory.InitializingBean;  
  3.   
  4. public class CompassIndexBuilder implements InitializingBean {    
  5.       
  6.     // 是否需要建立索引,可被設置爲false使本Builder失效.     
  7.     private boolean buildIndex = false;     
  8.     
  9.     // 索引操作線程延時啓動的時間,單位爲秒     
  10.     private int lazyTime = 10;     
  11.     
  12.     // Compass封裝     
  13.     private CompassGps compassGps;     
  14.     
  15.     // 索引線程     
  16.     private Thread indexThread = new Thread() {     
  17.     
  18.         @Override    
  19.         public void run() {     
  20.             try {     
  21.                 Thread.sleep(lazyTime * 1000);     
  22.                 System.out.println("begin compass index...");     
  23.                 long beginTime = System.currentTimeMillis();     
  24.                 // 重建索引.     
  25.                 // 如果compass實體中定義的索引文件已存在,索引過程中會建立臨時索引,     
  26.                 // 索引完成後再進行覆蓋.     
  27.                 compassGps.index();     
  28.                 long costTime = System.currentTimeMillis() - beginTime;     
  29.                 System.out.println("compss index finished.");     
  30.                 System.out.println("costed " + costTime + " milliseconds");     
  31.             } catch (InterruptedException e) {     
  32.                 e.printStackTrace();     
  33.             }     
  34.         }     
  35.     };     
  36.     
  37.     /**   
  38.      * 實現<code>InitializingBean</code>接口,在完成注入後調用啓動索引線程. 
  39.      */    
  40.     public void afterPropertiesSet() throws Exception {     
  41.         if (buildIndex) {     
  42.             indexThread.setDaemon(true);     
  43.             indexThread.setName("Compass Indexer");     
  44.             indexThread.start();     
  45.         }     
  46.     }     
  47.     
  48.     public void setBuildIndex(boolean buildIndex) {     
  49.         this.buildIndex = buildIndex;     
  50.     }     
  51.     
  52.     public void setLazyTime(int lazyTime) {     
  53.         this.lazyTime = lazyTime;     
  54.     }     
  55.     
  56.     public void setCompassGps(CompassGps compassGps) {     
  57.         this.compassGps = compassGps;     
  58.     }     
  59. }   


實現了spring的InitializingBean接口,讓服務器啓動,bean初始化的時候去建立索引 


剩下的就是配置文件了 

Java代碼  收藏代碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <beans xmlns="http://www.springframework.org/schema/beans"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xmlns:aop="http://www.springframework.org/schema/aop"  
  6.     xmlns:tx="http://www.springframework.org/schema/tx"  
  7.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  8.             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
  9.             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
  10.   
  11.     <bean id="annotationConfiguration"  
  12.         class="org.compass.annotations.config.CompassAnnotationsConfiguration">  
  13.     </bean>  
  14.   
  15.     <!-- compass Bean  -->  
  16.     <bean id="compass" class="org.compass.spring.LocalCompassBean">  
  17.         <property name="compassConfiguration"  
  18.             ref="annotationConfiguration" />  
  19.         <!-- 數據索引存儲位置 -->  
  20.         <property name="connection">  
  21.             <value>/compass/indexes</value>  
  22.         </property>  
  23.         <property name="transactionManager" ref="transactionManager" />  
  24.         <property name="compassSettings">  
  25.             <props>  
  26.                 <prop key="compass.transaction.factory">  
  27.                     org.compass.spring.transaction.SpringSyncTransactionFactory  
  28.                 </prop>  
  29.               
  30.                 <prop  
  31.                     key="compass.engine.highlighter.default.formatter.simple.pre">  
  32.                     <![CDATA[<span style='background-color:yellow;color:red;'>]]>  
  33.                 </prop>  
  34.                 <prop  
  35.                     key="compass.engine.highlighter.default.formatter.simple.post">  
  36.                     <![CDATA[</span>]]>  
  37.                 </prop>  
  38.     <!--定義分詞器-->            
  39. <prop  
  40.                     key="compass.engine.analyzer.default.type">  
  41.                     org.mira.lucene.analysis.IK_CAnalyzer  
  42.                 </prop>  
  43.             </props>  
  44.         </property>  
  45.         <property name="classMappings">  
  46.             <list>  
  47.               
  48.                 <value>cn.rgcenter.entity.Article</value>  
  49.             </list>  
  50.         </property>  
  51.     </bean>  
  52.   
  53.     <!--hibernate驅動-->  
  54.     <bean id="hibernateGpsDevice"  
  55.         class="org.compass.spring.device.hibernate.dep.SpringHibernate3GpsDevice">  
  56.         <property name="name">  
  57.             <value>hibernateDevice</value>  
  58.         </property>  
  59.         <property name="sessionFactory" ref="sessionFactory" />  
  60.         <property name="mirrorDataChanges">  
  61.             <value>true</value>  
  62.         </property>  
  63.     </bean>  
  64.   
  65.     <!-- 數據庫中的數據變化後同步更新索引 -->  
  66.     <bean id="hibernateGps"  
  67.         class="org.compass.gps.impl.SingleCompassGps" init-method="start"  
  68.         destroy-method="stop">  
  69.         <property name="compass">  
  70.             <ref bean="compass" />  
  71.         </property>  
  72.         <property name="gpsDevices">  
  73.             <list>  
  74.                 <bean  
  75.                     class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">  
  76.                     <property name="gpsDevice" ref="hibernateGpsDevice" />  
  77.                 </bean>  
  78.             </list>  
  79.         </property>  
  80.     </bean>  
  81.   
  82.     <!-- compass模版 -->  
  83.     <bean id="compassTemplate"  
  84.         class="org.compass.core.CompassTemplate">  
  85.         <property name="compass" ref="compass" />  
  86.     </bean>  
  87.   
  88.     <!-- 定時重建索引(利用quartz)或隨Spring ApplicationContext啓動而重建索引 -->  
  89.     <bean id="compassIndexBuilder"  
  90.         class="cn.rgcenter.compass.service.CompassIndexBuilder"  
  91.         lazy-init="false">  
  92.         <property name="compassGps" ref="hibernateGps" />  
  93.         <property name="buildIndex" value="true" />  
  94.         <property name="lazyTime" value="5" />  
  95.     </bean>  
  96.   
  97.     <!-- 搜索引擎服務類 -->  
  98.     <bean id="searchService"  
  99.         class="cn.rgcenter.compass.service.SearchServiceBean">  
  100.         <property name="compass">  
  101.             <ref bean="compass" />  
  102.         </property>  
  103.     </bean>  
  104.   
  105.     <!-- 搜索引擎Action -->  
  106.     <bean id="searchAction" class="cn.rgcenter.action.SearchAction">  
  107.         <property name="searchService">  
  108.             <ref bean="searchService" />  
  109.         </property>  
  110.     </bean>  
  111.   
  112. </beans>  


至於action就不列出代碼了,很簡單了,只需要傳搜索方法的那幾個參數過去就可以了. 

最後看一下搜索結果示例圖: 



本文轉自於:http://jeemiss.iteye.com/blog/432634


發佈了77 篇原創文章 · 獲贊 215 · 訪問量 82萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章