本人正在做一个互动问答平台,类似百度知道那样,所以站内搜索变的尤为关键了,我采用了基于Lucene的hibernate search来实现站内搜索的功能。
我使用的版本是hibernate search4.1和Lucene3.5.
这个问答平台的搜索需求就是能够找到自己感兴趣的问题。所以支持对question表中的title和content也就是标题和内容的检索。
下面是核心代码:
public List<Question> search(String queryString) throws IOException{
Session session=sessionFactory.openSession();
FullTextSession fullTextSession = Search.getFullTextSession(session);
QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Question.class).get();
//在这里修改要查询的字段
System.out.println(queryString);
Query luceneQuery = queryBuilder.keyword().onFields("title","content").matching(queryString).createQuery();
FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(luceneQuery, Question.class);
List<Question> rsList = fullTextQuery.list();
//上面是搜索功能的代码,下面是结果集关键字高亮的实现代码
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
QueryScorer queryScorer = new QueryScorer(luceneQuery);
Highlighter highlighter = new Highlighter(formatter, queryScorer);
Analyzer analyzer = new ChineseAnalyzer();
String[] fieldNames={"title","content"};
for (Question q : rsList) {
for (String fieldName : fieldNames) {
//运用反射得到具体的标题内容
Object fieldValue = ReflectionUtils.invokeMethod(BeanUtils.getPropertyDescriptor(Question.class, fieldName).getReadMethod(), q); //ReflectionUtils.getField(ReflectionUtils.findField(searchResultClass, fieldName), e);
String hightLightFieldValue = null;
if(fieldValue instanceof String){
try {
//获得高亮关键字
hightLightFieldValue = highlighter.getBestFragment( analyzer, fieldName , ObjectUtils.toString(fieldValue, null));
} catch (IOException e1) {
e1.printStackTrace();
} catch (InvalidTokenOffsetsException e1) {
e1.printStackTrace();
}
//这个判断很关键,否则如果标题或内容中没有关键字的话,就会出现不显示的问题。
if(hightLightFieldValue!=null){
//运用反射设置结果集中的关键字高亮
ReflectionUtils.invokeMethod(BeanUtils.getPropertyDescriptor(Question.class, fieldName).getWriteMethod(), q, hightLightFieldValue); //setField(ReflectionUtils.findField(searchResultClass, fieldName), e, hightLightFieldValue);
}
}
}
}
fullTextSession.close();
return rsList;
}
已经测试成功了,效果很好。