将Hibernate Search集成进已有项目中,实现全文检索功能

本来是准备使用Lucene的但是新版本的API过于繁琐,最后还是决定使用Hibernate Search来实现全文检索。这篇博文以我以前做的博客为例来实现全文检索。

1、修改Hibernate配置文件,因为我的系统采用的是SSH2来开发的所以我修改的是spring配置文件

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.search.default.directory_provider">filesystem</prop>
            <prop key="hibernate.search.default.indexBase">E:/index</prop>
        </props>
    </property>
    <property name="mappingResources">
        <list>
            <value>cn/harmel/blog/domain/User.hbm.xml</value>
            <value>cn/harmel/blog/domain/Category.hbm.xml</value>
            <value>cn/harmel/blog/domain/Article.hbm.xml</value>
            <value>cn/harmel/blog/domain/Comment.hbm.xml</value>
            <value>cn/harmel/blog/domain/Attachment.hbm.xml</value>
        </list>
    </property>
</bean>

其实就是配置如下两个属性:

hibernate.search.default.directory_provider = filesystem
hibernate.search.default.indexBase = 索引存储目录

2、给实体标注注解

package cn.harmel.blog.domain;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import org.hibernate.search.annotations.Analyzer;
import org.hibernate.search.annotations.DocumentId;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
 * 文章
 * 
 * @author Harmel
 *
 */
@Indexed
@Analyzer(impl = IKAnalyzer.class)
public class Article {

    @DocumentId
    private Long id;
    @Field
    private String title;
    @Field
    private String content;
    @Field
    private String description;
    private Date postTime;
    private Date lastEditTime;
    private int viewCount;

    private Category category;
    private Set<Comment> comments = new HashSet<Comment>();
    private Set<Attachment> attachments = new HashSet<Attachment>();

    // 此处省略一些getter和setter方法
    //........
}

注解说明:

@Indexed:让实体支持索引

@Analyzer :设置分词器,我这里使用的是开源的IK中文分词器

@DocumentID:索引文档ID

@Field :索引字段,该注解默认属性值为

store=Store.NO:是否将数据存储在索引中,经实验无论store=Store.NO还是store=Store.YES都不会影响最终的搜索。如果store=Store.NO值是通过数据库中获取,如果store=Store.YES值是直接从索引文档中获取。

index=Index.YES:是否索引

analyze=Analyze.YES:是否分词

标注了注解后的实体在保存和更新的时候,会自动生成或修改索引。

3、查询索引

public PageModel<Article> searchArticle(int pageNum, int pageSize, String keyword) {
    FullTextSession fts = Search.getFullTextSession(sessionFactory.getCurrentSession());
    QueryBuilder qb = fts.getSearchFactory().buildQueryBuilder().forEntity(Article.class).get();
    Query luceneQuery = qb.keyword().onFields("title", "content", "description").matching(keyword).createQuery();
    FullTextQuery query = fts.createFullTextQuery(luceneQuery, Article.class);
    query.setFirstResult((pageNum - 1) * pageSize);
    query.setMaxResults(pageSize);
    List<Article> data = query.list();
    //封装分页数据
    PageModel<Article> model = new PageModel<>(pageNum, pageSize, data.size());
    //将数据高亮
    model.setData(SearchUtils.hightLight(luceneQuery, data, "title", "content", "description"));
    return model;
}

将数据高亮工具方法

/**
* 高亮显示文章
* 
* @param query {@link org.apache.lucene.search.Query}
* @param data 未高亮的数据
* @param fields 需要高亮的字段
* @return 高亮数据
*/
public static List<Article> hightLight(Query query, List<Article> data, String... fields) {
    List<Article> result = new ArrayList<Article>();
    Formatter formatter = new SimpleHTMLFormatter("<b style=\"color:red\">", "</b>");
    QueryScorer queryScorer = new QueryScorer(query);
    Highlighter highlighter = new Highlighter(formatter, queryScorer);
    // 使用IK中文分词
    Analyzer analyzer = new IKAnalyzer();
    for (Article a : data) {
    // 构建新的对象进行返回,避免页面错乱(我的页面有错乱)
    Article article = new Article();
    for (String fieldName : fields) {
        // 获得字段值,并给新的文章对象赋值
        Object fieldValue = ReflectionUtils
            .invokeMethod(BeanUtils.getPropertyDescriptor(Article.class, fieldName).getReadMethod(),a);
        ReflectionUtils.invokeMethod(BeanUtils.getPropertyDescriptor(Article.class, fieldName).getWriteMethod(),
            article, fieldValue);
        String hightLightFieldValue = null;
        try {
            hightLightFieldValue = highlighter.getBestFragment(analyzer, fieldName, String.valueOf(fieldValue));
        } catch (Exception e) {
            throw new RuntimeException("高亮显示关键字失败", e);
        }
        // 如果高亮成功则重新赋值
        if (hightLightFieldValue != null) {
            ReflectionUtils.invokeMethod(BeanUtils.getPropertyDescriptor(Article.class, fieldName).getWriteMethod(),
                article,hightLightFieldValue);
        }
        }
        // 赋值ID
        ReflectionUtils.invokeMethod(BeanUtils.getPropertyDescriptor(Article.class, "id").getWriteMethod(),
            article, a.getId());
        result.add(article);
    }
    return result;
}

4、页面迭代显示

<s:iterator value="#request.pageModel.data">
<div class="article">
    <div class="article_title_area">
        <span class="article_title"><a href="${pageContext.request.contextPath }/article/show.action?id=${id }">${title }</a></span>
        <span class="article_date">发表时间:<s:date name="postTime" format="yyyy-MM-dd HH:mm:ss"/></span>
    </div>
    <div class="article_content">${description }</div>
    <div class="article_count_info">
        <span>阅读(${viewCount })</span>
        <span>评论(${comments.size() })</span>
    </div>
</div>
</s:iterator>
时间: 2024-08-27 07:14:19

将Hibernate Search集成进已有项目中,实现全文检索功能的相关文章

React-Native集成到已有项目中的总结

安装Python 从官网下载并安装python 2.7.x(3.x版本不行) 安装node.js 从官网下载node.js的官方V6.X.X版本或更高版本.安装完成后检测是否安装成功:node -v 安装完node后建议设置npm镜像以加速后面的过程(或使用科学上网工具). npm config set registry https://registry.npm.taobao.org --globalnpm config set disturl https://npm.taobao.org/di

Resx 文件无效。未能加载 .RESX 文件中使用的类型 System.Collections.Generic.List`1请确保已在项目中添加了必需的引用。

在C#程序编写过程中,会遇到:Resx 文件无效.未能加载 .RESX 文件中使用的类型 System.Collections.Generic.List1`请确保已在项目中添加了必需的引用. 主要原因很可能是使用了类的可序列化的原因,代码如下: [Serializable] public class TimeLineItem { public string Title; public string Content; public TimeLineItem(string content) { th

SpringMVC将一个项目集成在另一个项目中

将KissfloveUtil项目集成在自己项目中.在pom.xml中加入以下配置: <dependencies> <dependency> <groupId>com.kissflove</groupId> <artifactId>kissfloveUtil</artifactId> <version>0.0.1</version> </dependency> </dependencies>

ZXingObjC 64位 集成到自己的项目中(xcode 6.4)

参考  http://www.cocoachina.com/bbs/read.php?tid-280058-page-1.html 楼主发的DEMO中 ZXingObjC 支持64位  但是是以项目形式添加的. 1.从中拷贝  ScannerTest ? ScannerTest ? 公共模块 ? Scanner ? ZXingObjC   目录到自己的项目中 2.将ScannerTest-Prefix.pch  拷贝到自己项目中 3.Build Settings   找到 Precompile

提交本地文件至gitlab已有的项目中(更新gitlab)

gitlab代码更新 gitlab官网 1.安装git git官网 官网下载安装,安装过程一直next即可(路径自己选) 2.clone至本机 格式:git clone url(可转到指定目录克隆) 在本机将需要更新的内容放到指定目录下 3.添加提交至gitlab 命令如下 git add . git commit -m "commit" git push 如果是第一次会报如下错误: 只要输入图中报错给的两行代码就解决了. 然后继续执行上述命令 原文地址:https://www.cnb

[Hibernate Search] 初识Hibernate Search

初识Hibernate Search 要让你的应用具备Hibernate Search赋予的全文搜索的能力,需要做以下三件事: 给项目添加必要的依赖和配置信息 给你的实体类添加必要的信息,从而让Lucene知道如何对它们进行索引(Indexing) 在需要的地方使用符合Hibernate Search规范的查询来完成业务逻辑 对于需要添加的依赖信息,会在以后进行介绍.我们首先来看看代码该如何写. 我们会使用一个类似于经典的"Java Pet Store"那样的Web应用来展示Hiber

轨迹系列——记某真实项目中轨迹存储改造方案

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.    方案目标 该方案需要满足以下几点: 支持人员当天轨迹快速获取(查询). 支持轨迹高并发读.写(实际项目中轨迹高并发读情况很少). 保证所有(历史)轨迹数据的完整性.不丢失. 2.方案探讨详细描述 2.1支持轨迹快速查询--轨迹日志文件方案 海量数据高效存储.查询,这个场景本身是比较适合NoSQL数据库运用的,但是考虑到该方案实施的难度(对工程实施.维护.研发

Python+Selenium进行UI自动化测试项目中,常用的小技巧4:日志打印,longging模块(控制台和文件同时输出)

在前段时间,为了给项目中加入日志功能,就想到了 logging 模块,百度logging一大推,都是各种复制的,并没有找到自己想要的结果:我的目的很简单,就是:在把日志写入文件的同时在控制台输出,更加方便调试,我下面的代码就满足这个功能: 1 #coding=utf-8 2 3 import logging 4 import time 5 import commonparameter 6 7 class Log: 8 def __init__(self): 9 self.logname = co

在已有项目集成hessian

第一步骤:引入jar包,hessian-4.0.6.jar 第二步骤:在我们项目中web.xml,配置的拦截器是,过滤的是.ik路径,所以我们为了不让拦截器拦截,我们在添加一个后缀,放过. <filter> <filter-name>uriFilter</filter-name> <filter-class>com.cntaiping.life.interceptor.SessionFilter</filter-class> </filte