用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就不列出代码了,很简单了,只需要传搜索方法的那几个参数过去就可以了.

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

[img]http://missangel.iteye.com/upload/attachment/128737/bd98a5ab-ca5b-3ba5-86bf-d680c8aaad4e.jpg[/img]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值