本人正在做一个互动问答平台,类似百度知道那样,所以站内搜索变的尤为关键了,我采用了基于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(); org.hibernate.Query 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; }已经测试成功了,效果很好。