Compass实现站内全文搜索(二)

接下来是要建立搜索的服务类
    import java.util.ArrayList;  
    import java.util.HashMap;  
    import java.util.List;  
    import java.util.Map;  
    import org.compass.core.Compass;  
    import org.compass.core.CompassCallback;  
    import org.compass.core.CompassException;  
    import org.compass.core.CompassHighlighter;  
    import org.compass.core.CompassHits;  
    import org.compass.core.CompassQuery;  
    import org.compass.core.CompassSession;  
    import org.compass.core.CompassTemplate;  
    import org.compass.core.CompassTransaction;  
    import cn.rgcenter.entity.Article;  
      
    public class SearchServiceBean {  
      
        private Compass compass;  
        /** 索引查询 * */  
        public Map find(final String keywords, final String type, final int start,  
                final int end) {  
            CompassTemplate ct = new CompassTemplate(compass);  
            return ct.execute(new CompassCallback<Map>() {  
      
                public Map doInCompass(CompassSession session)  
                        throws CompassException {  
                    List result = new ArrayList();  
                    int totalSize = 0;  
                    Map container = new HashMap();  
                    CompassQuery query = session.queryBuilder().queryString(  
                            keywords).toQuery();  
                    CompassHits hits = query.setAliases(type).hits();  
                    totalSize = hits.length();  
                    container.put("size", totalSize);  
                    int max = 0;  
                    if (end < hits.length()) {  
                        max = end;  
                    } else {  
                        max = hits.length();  
                    }  
      
           if(type.equals("article")){  
                        for (int i = start; i < max; i++) {  
                            Article article = (Article) hits.data(i);  
                            String title = hits.highlighter(i).fragment("title");  
                            if (title != null) {  
                                article.setTitle(title);  
                            }  
                            String content = hits.highlighter(i).setTextTokenizer(  
                                    CompassHighlighter.TextTokenizer.AUTO)  
                                    .fragment("content");  
                            if (content != null) {  
      
                                article.setContent(content);  
                            }  
                            result.add(article);  
                        }  
                    }  
                    container.put("result", result);  
                    return container;  
                }  
            });  
        }  
      
        public Compass getCompass() {  
            return compass;  
        }  
      
        public void setCompass(Compass compass) {  
            this.compass = compass;  
        }  
      
    }  


索引的查询主要是根据传过来的参数,关键字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具有一样的一样的功能,另外还多了个很重要的功能,自动选择正文中最匹配关键字的内容中的一部分输出。因为很多时候一篇文章几千字,我们只想显示有关键字的那部分的摘要,这时候这个功能就很方便.


这之后还要写一个建立索引的服务类,让服务器启动的时候或者定时重建索引.
    import org.compass.gps.CompassGps;  
    import org.springframework.beans.factory.InitializingBean;  
      
    public class CompassIndexBuilder implements InitializingBean {    
          
        // 是否需要建立索引,可被设置为false使本Builder失效.     
        private boolean buildIndex = false;     
        
        // 索引操作线程延时启动的时间,单位为秒     
        private int lazyTime = 10;     
        
        // Compass封装     
        private CompassGps compassGps;     
        
        // 索引线程     
        private Thread indexThread = new Thread() {     
        
            @Override    
            public void run() {     
                try {     
                    Thread.sleep(lazyTime * 1000);     
                    System.out.println("begin compass index...");     
                    long beginTime = System.currentTimeMillis();     
                    // 重建索引.     
                    // 如果compass实体中定义的索引文件已存在,索引过程中会建立临时索引,     
                    // 索引完成后再进行覆盖.     
                    compassGps.index();     
                    long costTime = System.currentTimeMillis() - beginTime;     
                    System.out.println("compss index finished.");     
                    System.out.println("costed " + costTime + " milliseconds");     
                } catch (InterruptedException e) {     
                    e.printStackTrace();     
                }     
            }     
        };     
        
        /**   
         * 实现<code>InitializingBean</code>接口,在完成注入后调用启动索引线程. 
         */    
        public void afterPropertiesSet() throws Exception {     
            if (buildIndex) {     
                indexThread.setDaemon(true);     
                indexThread.setName("Compass Indexer");     
                indexThread.start();     
            }     
        }     
        
        public void setBuildIndex(boolean buildIndex) {     
            this.buildIndex = buildIndex;     
        }     
        
        public void setLazyTime(int lazyTime) {     
            this.lazyTime = lazyTime;     
        }     
        
        public void setCompassGps(CompassGps compassGps) {     
            this.compassGps = compassGps;     
        }     
    }   




实现了spring的InitializingBean接口,让服务器启动,bean初始化的时候去建立索引


剩下的就是配置文件了
    <?xml version="1.0" encoding="UTF-8"?>  
      
    <beans xmlns="http://www.springframework.org/schema/beans"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xmlns:aop="http://www.springframework.org/schema/aop"  
        xmlns:tx="http://www.springframework.org/schema/tx"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
      
        <bean id="annotationConfiguration"  
            class="org.compass.annotations.config.CompassAnnotationsConfiguration">  
        </bean>  
      
        <!-- compass Bean  -->  
        <bean id="compass" class="org.compass.spring.LocalCompassBean">  
            <property name="compassConfiguration"  
                ref="annotationConfiguration" />  
            <!-- 数据索引存储位置 -->  
            <property name="connection">  
                <value>/compass/indexes</value>  
            </property>  
            <property name="transactionManager" ref="transactionManager" />  
            <property name="compassSettings">  
                <props>  
                    <prop key="compass.transaction.factory">  
                        org.compass.spring.transaction.SpringSyncTransactionFactory  
                    </prop>  
                  
                    <prop  
                        key="compass.engine.highlighter.default.formatter.simple.pre">  
                        <![CDATA[<span style='background-color:yellow;color:red;'>]]>  
                    </prop>  
                    <prop  
                        key="compass.engine.highlighter.default.formatter.simple.post">  
                        <![CDATA[</span>]]>  
                    </prop>  
        <!--定义分词器-->            
    <prop  
                        key="compass.engine.analyzer.default.type">  
                        org.mira.lucene.analysis.IK_CAnalyzer  
                    </prop>  
                </props>  
            </property>  
            <property name="classMappings">  
                <list>  
                  
                    <value>cn.rgcenter.entity.Article</value>  
                </list>  
            </property>  
        </bean>  
      
        <!--hibernate驱动-->  
        <bean id="hibernateGpsDevice"  
            class="org.compass.spring.device.hibernate.dep.SpringHibernate3GpsDevice">  
            <property name="name">  
                <value>hibernateDevice</value>  
            </property>  
            <property name="sessionFactory" ref="sessionFactory" />  
            <property name="mirrorDataChanges">  
                <value>true</value>  
            </property>  
        </bean>  
      
        <!-- 数据库中的数据变化后同步更新索引 -->  
        <bean id="hibernateGps"  
            class="org.compass.gps.impl.SingleCompassGps" init-method="start"  
            destroy-method="stop">  
            <property name="compass">  
                <ref bean="compass" />  
            </property>  
            <property name="gpsDevices">  
                <list>  
                    <bean  
                        class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">  
                        <property name="gpsDevice" ref="hibernateGpsDevice" />  
                    </bean>  
                </list>  
            </property>  
        </bean>  
      
        <!-- compass模版 -->  
        <bean id="compassTemplate"  
            class="org.compass.core.CompassTemplate">  
            <property name="compass" ref="compass" />  
        </bean>  
      
        <!-- 定时重建索引(利用quartz)或随Spring ApplicationContext启动而重建索引 -->  
        <bean id="compassIndexBuilder"  
            class="cn.rgcenter.compass.service.CompassIndexBuilder"  
            lazy-init="false">  
            <property name="compassGps" ref="hibernateGps" />  
            <property name="buildIndex" value="true" />  
            <property name="lazyTime" value="5" />  
        </bean>  
      
        <!-- 搜索引擎服务类 -->  
        <bean id="searchService"  
            class="cn.rgcenter.compass.service.SearchServiceBean">  
            <property name="compass">  
                <ref bean="compass" />  
            </property>  
        </bean>  
      
        <!-- 搜索引擎Action -->  
        <bean id="searchAction" class="cn.rgcenter.action.SearchAction">  
            <property name="searchService">  
                <ref bean="searchService" />  
            </property>  
        </bean>  
      
    </beans>  

于action就不列出代码了,很简单了,只需要传搜索方法的那几个参数过去就可以了.

最后看一下搜索结果示例图:

猜你喜欢

转载自junshang.iteye.com/blog/1750426