Hibernate Search 教程

本文我们讨论Hibernate Search 基础知识、配置及查询搜索功能。

如果我们已经在ORM中使用Hibernate和JPA,那么离Hibernate Search只有一步之遥。Hibernate Search集成了Apache Lucene,一个高性能、可扩展的全文检索引擎。其结合了Lucene的强大功能和Hibernate和JPA的简单性,因此仅需在领域类上增加一些注解,数据库与索引的同步工作会自动完成。

Hibernate Search 也提供了Elasticsearch的集成,本文聚焦Lucene的实现。无论那种方式实现全文检索,使用我们熟悉的工具总是不错的选型。

1. 配置

1.1. 依赖

首先增加一些必要的依赖:

<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-search-orm</artifactId><version>5.8.2.Final</version>
</dependency>

为了示例简单,我们使用H2内存数据库:

<dependency><groupId>com.h2database</groupId> <artifactId>h2</artifactId><version>1.4.196</version>
</dependency>

1.2. 配置

关键配置是Lucene索引存储位置,需要通过hibernate.search.default.directory_provider属性进行设置。

我们将选择filesystem,这是最直接的选择。官方文件中列出了更多的选项。对于集群应用程序来说,filesystemi-master/filesystemi-slave和infinispan是值得注意的,其中索引必须在节点之间同步。示例配置如下:

hibernate.search.default.directory_provider = filesystem
hibernate.search.default.indexBase = /data/index/default

1.3. 搜索模型类

完成配置后,需要指定模型类。在JPA注解@Entity 和 @Table的基础上增加@Indexed 注解,其告诉Hibernate Search 该实体需要被索引。然后再定义需要被索引的属性,增加@Field注解:

@Entity
@Indexed
@Table(name = "product")
public class Product {@Idprivate int id;@Field(termVector = TermVector.YES)private String productName;@Field(termVector = TermVector.YES)private String description;@Fieldprivate int memory;// getters, setters, and constructors
}

1.4. 生成Lucene索引

开始执行查询之前,需触发Lucene生成反向索引:

FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
fullTextEntityManager.createIndexer().startAndWait();

初始化完成之后,当通过EntityManager创建、修改或删除实体时,Hibernate Search 会负责索引实时更新。
需要注意的是:必须确保实体被完全提交至数据库才能让Lucene生成索引,因此测试时需要使用@Commit注解。

2. 构建并执行查询

完成上面的配置之后,下面准备创建查询,先介绍构建查询流程。

2.1. 构建查询流程

主要包括四个步骤:

  1. 从FullTextEntityManager获取QueryBuilder
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory() .buildQueryBuilder().forEntity(Product.class).get();
  1. 通过 Hibernate query DSL创建Lucene查询:
org.apache.lucene.search.Query query = queryBuilder.keyword().onField("productName").matching("iphone").createQuery();
  1. 包装Lucene 查询至 Hibernate查询:
org.hibernate.search.jpa.FullTextQuery jpaQuery= fullTextEntityManager.createFullTextQuery(query, Product.class);
  1. 执行查询
List<Product> results = jpaQuery.getResultList();

默认情况下Lucene按照相关性进行排序。步骤1、3、4对所有查询类型都一样,后面我们聚集步骤2实现不同的查询。

2.2. 关键词查询

即搜索特定关键词,代码如下:

Query keywordQuery = queryBuilder.keyword().onField("productName").matching("iphone").createQuery();

keyword()指定搜索特定词,onField()告诉Lucene在哪里搜索,matching匹配需要搜索的关键词。

2.3. 近似查询

近似查询与关键词查询类似,只是可以定义一个“模糊”的限制,在这个限制内Lucene将接受两个术语为匹配结果。

通过ditdistanceupto(),可以定义术语之间的偏离程度。它可以设置为0、1和2,默认值为2(注意:这个限制来自Lucene的实现)。
通过withPrefixLength(),定义前缀的长度,这个长度是由模糊性所忽略的:

Query fuzzyQuery = queryBuilder.keyword().fuzzy().withEditDistanceUpTo(2).withPrefixLength(0).onField("productName").matching("iPhaen").createQuery();

2.4. 通配符查询

Hibernate Search也支持通配符查询,?号表示单个字符,*号表示任意字符:

Query wildcardQuery = queryBuilder.keyword().wildcard().onField("productName").matching("Z*").createQuery();

2.5. 短语搜索

如果想搜索多个词,可以使用短语搜索。使用phrase() 和 withSlop()方法,可以实现精确查询或近似句子。slop因子定义句子中允许其他词数量:

Query phraseQuery = queryBuilder.phrase().withSlop(1).onField("description").sentence("with wireless charging").createQuery();

2.5. 简单查询字符串搜索

前面的查询方式都需要指定查询类型。使用简单查询字符串可以实现更强大的搜索功能,即实现运行时查询能力。其支持的查询类型如下:

  • 布尔类型(and 使用 +, or 使用 | , not 使用-
  • 前缀查询(前缀*)
  • 短语查询(“一些短语”)
  • 优先级(使用括号)
  • 近似查询(近似词语~2)
  • 短语查询的近邻运算符(“某些短语”~3)
下面示例综合了近似查询、词组查询以及布尔查询:Query simpleQueryStringQuery = queryBuilder.simpleQueryString().onFields("productName", "description").matching("Aple~2 + \"iPhone X\" + (256 | 128)").createQuery();

2.7. 范围查询

范围查询在一定范围内搜索值,可以应用于数值、日期、时间以及字符串:

Query rangeQuery = queryBuilder.range().onField("memory").from(64).to(256).createQuery();

2.8. 同类词查询

最后一个查询类型是同类词查询(More Like This)。提供一个实体,Hibernate Search 返回类似的实体列表,每个元素带有相似度评分。
前面已经提及,在模型属性上需要增加termVector = TermVector.YES,其告诉Lucene索引时存储每个词条的频率。
基于此,相似度将在查询执行时计算:

Query moreLikeThisQuery = queryBuilder.moreLikeThis().comparingField("productName").boostedTo(10f).andField("description").boostedTo(1f).toEntity(entity).createQuery();
List<Object[]> results = (List<Object[]>) fullTextEntityManager.createFullTextQuery(moreLikeThisQuery, Product.class).setProjection(ProjectionConstants.THIS, ProjectionConstants.SCORE).getResultList();

2.9. 基于多个字段查询

目前为止我们一直使用onField()方法在一个字段上执行查询,实际应用中也能基于多个字段:

Query luceneQuery = queryBuilder.keyword().onFields("productName", "description").matching(text).createQuery();

而且,也可以针对每个字段分别搜索。如我们可以对不同字段定义不同的加权因子(boost):

Query moreLikeThisQuery = queryBuilder.moreLikeThis().comparingField("productName").boostedTo(10f).andField("description").boostedTo(1f).toEntity(entity).createQuery();

2.10. 组合查询

最后Hibernate Search也支持使用不同策略实现组合查询:

  • SHOULD: 查询应该包括子查询匹配的元素
  • MUST: 查询必须包含子查询匹配的元素
  • MUST NOT: 查询不必包含子查询的元素

三者类似于布尔运算:and、or和not,但使用不同名称是为了强调它们也对相关性有影响。
举例:should在两个查询之间,只有有一个匹配则被返回,但如果两个都匹配,其相关性评分要高于只有一个匹配情况。

Query combinedQuery = queryBuilder.bool().must(queryBuilder.keyword().onField("productName").matching("apple").createQuery()).must(queryBuilder.range().onField("memory").from(64).to(256).createQuery()).should(queryBuilder.phrase().onField("description").sentence("face id").createQuery()).must(queryBuilder.keyword().onField("productName").matching("samsung").createQuery()).not().createQuery();

3. 总结

本文介绍了Hibernate Search的基础知识及相关配置,同时也通过示例展示各类查询功能。

Hibernate Search 教程相关推荐

  1. 如何在Hibernate Search 5.5.2 / Apache Lucene 5.4.x中处理停用词?

    停用词,例如[" a"," an"," and"," are"," as"," at&qu ...

  2. Hibernate Search 4.2最终发布:支持空间查询

    JBoss已宣布发布Hibernate Search 4.2 final. 您可以从Sourceforge下载它或使用Maven构件 . 在新版本中,包含了一些有趣的功能: Hibernate Sea ...

  3. Hibernate初学者教程

    Hibernate初学者教程 欢迎来到Hibernate初学者教程.Hibernate是最广泛使用的Java ORM工具之一.大多数应用程序使用关系数据库来存储应用程序信息,在较低级别,我们使用JDB ...

  4. Hibernate Search 6.0.0.Alpha3 发布,数据检索框架

    Hibernate Search 6.0.0.Alpha3 已发布,这是仍处于开发中的 6.0 分支的第三个版本.该版本主要增加了对更多字段类型和谓词的支持,并带来更一致.更简洁的 API. 入门 H ...

  5. Hibernate Search v.4.2.0.CR1 发布

    Hibernate Search v.4.2.0.CR1 发布了,该版本大部分是 bug 修复和性能的提升,同时提供一个更简单的方法以便发布到 JBoss AS 7 和 EAP 6 上. Hibern ...

  6. iOS 9 App Search教程

    原文链接 : iOS 9 App Search Tutorial: Introduction to App Search 原文作者 : Chris Wagner 译文出自 : 开发技术前线 www.d ...

  7. hibernate Search 继续研究 增加 hibernate memcache 二级缓存 配置成功 附件maven代码(2)...

    首先安装 memecached 服务端: 之前写过的 文章,centos 安装memcached服务 : http://toeo.iteye.com/blog/1240607 然后 在 前几天的 弄的 ...

  8. Java | 使用 Hibernate Search 构建一个带有全文搜索的 Spring Boot REST API (二)

    6 定义业务层 现在,让我们声明一个服务,使用刚才定义的数据层创建业务代码. package com.mozen.springboothibernatesearch.service;import co ...

  9. hibernate jpa_教程:Hibernate,JPA –第1部分

    hibernate jpa 这是关于使用Hibernate和JPA的教程的第一部分. 这部分是对JPA和Hibernate的介绍. 第二部分将研究使用Spring ORM组合一个Spring MVC应 ...

  10. Hibernate 系列教程9-自关联

    自关联:本质还是原来双向一对多,原来要配置两个类,现在全部都配置在一个类里面 Employee public class Employee {private Long id;private Strin ...

最新文章

  1. php移除所有子节点,PHP 循环删除无限分类子节点的实现代码
  2. 超全整理|Python 操作 Excel 库 xlwings 常用操作详解!
  3. Halcon学习笔记:1D Measuring一维测量_fuse.hdev灯丝测量示例
  4. 多线程:CopyOnWriteArrayList
  5. 泛泰A880S升级官方4.4.2 binx教程
  6. linux block挂io,linux:在qemu中运行自编译内核:VFS:无法在未知的wn-block(0,0)上挂载root fs...
  7. 条件语句的多层嵌套问题优化,助你写出不让同事吐槽的代码
  8. 02-03 Python json格式转化
  9. 重装Microsoft .NET Framework 4.0
  10. 微信小程序滚动条返回顶部
  11. 开源.NET项目 CSS、JS资源优化类库及工具
  12. Mac10.12开启NTFS读写
  13. Python项目开发基础 -- 函数参数与数据库连接参数
  14. SLG手游策略游戏-分析思维
  15. 计算机分盘介质受写入保护,“介质受写入保护”的解决(适用于U盘或移动硬盘)...
  16. 小学计算机课打字游戏,小学信息技术打字游戏教案
  17. 我在职场上的所表达出来的个性
  18. 计算机考研 | 2020我计算机考研为什么会失败+复盘(备战2022)
  19. 河北计算机软件职业技术学院,河北软件职业技术学院
  20. Hibernate开发之创建POJO-配置文件-映射文件

热门文章

  1. 线切割计算机传输出错,为什么线切割单板机总传不了或出错?解开传送数据之迷...
  2. Linux环境下如何使用 ffmpeg 处理音视频的合成问题
  3. 你有多自律,就有多自由
  4. notepad 快速新建html,notepad编写html
  5. 使用DALSA采集卡进行采图(C#版)
  6. flashfxpFTP链接显示PASV、列表错误
  7. 佳能g2810打印机扫描怎么用_佳能g2810怎么自动清洗
  8. java类与对象实验报告心得体会_java实验报告心得体会
  9. 定积分计算(谭浩强c语言第5版p272)
  10. 把live2D模型放上网页