HibernateSearch全文检索

隆选
2023-12-01

HibernateSearch全文检索技术-工作单索引的建立和搜索

全文检索

我们在向表中插入数据的同时,向外置索引库中也放入响应的数据。等查询的时候,先查询索引库,然后再查询表。

第一步:建立索引:
向表中插入数据的同时,向外置索引库中也放入相应的数据。
表:
id arrivecity
1 上海浦东
2 深圳宝安

索引库:(先分词-再存储,分词的效果依赖于中文分词器)
id name
1 1
2 上海
3 浦东

第二步:通过索引查询
当要模糊查询:到达地带有“上海”,
先从索引库中直接查询有没有叫“上海”,获取了该词条所在的数据在数据库中的主键值。
接着:拿主键到数据库中查询,select * from table where id in(,,,,,,,)
因为:oracle主键上自动带有唯一索引,因此,根据主键查询,自动会使用索引,效率很高。

对工作单数据建立索引

技术:Lucene(建立索引)+hibernate Search(操作的api)
Hibernate Search是给Hibernate持久化模型架构来使用的一套全文检索工具,其全文检索依赖于Lucence引擎。

引入Maven坐标(引入hibernate search和IK分词器的jar包)

        <properties>
            <hibernate-search.version>3.4.2.Final</hibernate-search.version>
            <IKAnalyzer.version>3.2.8</IKAnalyzer.version>  </properties>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-search</artifactId>
            <version>${hibernate-search.version}</version>
        </dependency>
        <!-- ik分词器 -->  
        <dependency>
          <groupId>IKAnalyzer</groupId>
          <artifactId>IKAnalyzer</artifactId>
          <version>${IKAnalyzer.version}</version>
        </dependency>

lucence版本必须和Hibernate版本对应

        <!--IK分词器-->
        <dependency>
            <groupId>com.janeluo</groupId>
            <artifactId>ikanalyzer</artifactId>
            <version>2012_u6</version>
        </dependency>

IK分词器的配置:
将IKAnalyzer.cfg.xml和stopword.dic复制到src/resources下.

索引存放的基础目录配置:

        <!-- 索引文件存放的目录 -->
        <prop key="hibernate.search.default.indexBase">f:/index</prop>

索引的内容配置(通过注解方式配置实体类,可对哪些数据进行索引)
@Indexed 对实体建立索引
@DocumentId id
@Field 字段
@Analyzer 使用分词器

Hibernate Search是基于lucence的,无需手动编写lucence代码即可进行Hibernate操作,会自动创建索引、修改索引、删除索引。
测试原理:在保存数据的时候,Hibernate Search,会在向数据库保存数据(完整)的同时,在索引库中也保存索引数据(分词后的数据,部分数据)。

查看索引:使用lukeall工具。Luke 是查询LUCENE索引文件的工具, 而且用 Luke 的Search可以做查询.
执行:
java -jar lukeall-3.5.0.jar
在path中输入索引的文件夹的路径

实现搜索

        //自定义的Spring Data实现类无需实现接口,只需要类名以Impl结尾,
        //且被<jpa:repositories base-package="cn.aric.bos.dao"/>扫描到即可
        //原理:spring data jpa会自动到<jpa:repositories base-package="cn.aric.bos.dao"/>中,
        //优先寻找接口类名+Impl后缀的类,作为实现类,并自动继承simple。。。Repository
        public class WorkOrderManageDAOImpl{
            //想在spring data jpa中获取EntityManager
            @PersistenceContext//自动注入
            private EntityManager entityManager;

            /**
             * 通过luncence查询数据
             * 说明:
             * @return
             */
            public Page<WorkOrderManage> searchByLucence(Pageable pageable, String conditionName,
                    String conditionValue){
                //分析:将关键字和值交给lucence(Hibernatesearch的api),绑定数据库的表查询,
                //Hibernate search会“自动”先从全文搜索中找id,然后通过id查询数据库
                //-----lucence的query对象
                //---第一类搜索:一类长词分词模糊匹配
                //参数1:lucence版本
                //参数2:索引的字段的名字(查询的字段的名字)
                //参数3:分词器
                QueryParser queryParser = new QueryParser(Version.LUCENE_31, conditionName, new IKAnalyzer());
                //查询的关键字(解析器会自动分词后再查询)
                Query fenciQuery=null;
                try {
                    fenciQuery = queryParser.parse(conditionValue);
                } catch (ParseException e) {
                    throw new RuntimeException("不能解析分词这个关键字: " + conditionValue, e);
                }
                ---第二类搜索:短词直接匹配

                //参数:直接字段名和值
                Query duanciQuery=new WildcardQuery(new Term(conditionName,"*"+conditionValue+"*"));

                //将两个query结合起来---生成lunce的最终查询对象
                BooleanQuery query = new BooleanQuery();
                query.add(fenciQuery, Occur.SHOULD);//must:相当于and,SHOULD相当于or
                query.add(duanciQuery, Occur.SHOULD);

                //根据EntityManager来创建一个全文实体管理对象
                 FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);

                 //++++返回的是全文检索的查询对象---------最终要要Hibernate search。。。。---
                 //参数1。lucence Query对象
                 //参数2:实体类,带有索引注解的实体类
                 FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(query, WorkOrderManage.class);
                //-----上述代码,Hibernate search结合了lucence和jpa的查询数据库的查询,查询内部,都hs封装
                 //---封装结果集page对象
                 int total = fullTextQuery.getResultSize();//列表的总的数量
                 //现在分页数据,是Hibernate search来分调用jpa
                 fullTextQuery.setFirstResult(pageable.getPageNumber()*pageable.getPageSize());//起始索引
                 fullTextQuery.setMaxResults(pageable.getPageSize());//每页最大记录数
                 List<WorkOrderManage> content = fullTextQuery.getResultList();//数据列表

                 //结果—手动封装
                 Page<WorkOrderManage> page = new PageImpl<WorkOrderManage>(content, pageable, total);

                return page;
            }

        }

运行原理

1、构造LuceneQuery查询索引库
2、EntityManager 构造 FullTextEntityManager 查询数据库
3、合并EntityManager 和 LuceneQuery —– FullTextQuery 查询索引库和数据库
4、查询索引库 fullTextQuery.getResultSize(); 查询索引,去重id
5、查询数据库 fullTextQuery.getResultList(); 根据索引库返回 id ,查询数据库

 类似资料: