本文用的Hibernate Search
是 5.11 版本。根据官网指导(https://hibernate.org/search/releases/5.11/#getting_started):
- Hibernate ORM 5.4
- Apache Lucene 5.5
- Elasticsearch server 2.0 - 5.6 【我们没有用这个】
官方文档: https://docs.jboss.org/hibernate/search/5.11/reference/en-US/html_single/#preface
1 使用mavan引入依赖
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>{latest_stable}</version>
</dependency>
如果把索引保存到Elasticsearch,则需要引入下面这个依赖
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-elasticsearch</artifactId>
<version>{latest_stable}</version>
</dependency>
2 配置
2.1 配置文件
项目中使用了JPA,所以可以这样配置:
spring:
jpa:
properties:
# 目录提供者--文件系统
hibernate.search.default.directory_provider: filesystem
# 指定Lucene索引文件的存储目录
hibernate.search.default.indexBase: /var/lucene/indexes
如果只是用了Hibernate:
# 目录提供者--文件系统
hibernate.search.default.directory_provider: filesystem
# 指定Lucene索引文件的存储目录
hibernate.search.default.indexBase: /var/lucene/indexes
2.2 实体类注解配置
- 定义哪个实体类需要被索引 -- 加
@Indexed
注解 - 指定唯一标识 -- 默认是用
@Id
注解的字段,但我们可以用@DocumentId
注解来覆盖 - 选择要被索引搜索的字段 -- 用
@Field
注解来标识,参数如下:- index=Index.YES -- 表示内容将被索引
- analyze=Analyze.YES -- 表示内容会被Lucene默认的分析器去分析
- store=Store.NO -- 表示字段的原始数据不保存到索引中,不影响搜索查询【因为Hibernate Search在执行一个Lucene查询时,是以查找与查询匹配的实体的数据库标识符(主键ID),然后再到数据库中查询】。
- 非字符串类型要加对应的编码注解 -- Lucene的索引基本上是基于字符串的,非字符串类型被编码为更适合于范围查询的表示形式
- 数字类型 -- 如:@Field(bridge = @FieldBridge(impl = IntegerBridge.class))
- 布尔类型 -- 如:@Field(bridge = @FieldBridge(impl = BooleanBridge.class))
- 日期时间类型 -- @DateBridge
3 创建索引
3.1 重新成生Lucene索引
https://hibernate.org/search/documentation/getting-started/5.11/#indexing
FullTextSession fullTextSession = org.hibernate.search.Search.getFullTextSession((Session) entityManager.getDelegate());
fullTextSession.createIndexer().startAndWait();
JPA的话可以用下面的代码:
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
fullTextEntityManager.createIndexer().startAndWait();
3.2 Luke检查生成的索引
执行完代码后,就可以在前面配置的目录(/var/lucene/indexes)下看到生成的Lucene索引文件。 生成的索引可以用Luke(可以访问Lucene索引文件)来检查,Luke的功能:
- 浏览文档、索引字词和发布列表
- 在索引中搜索
- 执行索引维护:索引健康检查、索引优化(在运行此备份之前进行备份!
- 测试您的自定义 Lucene 分析器(Tokenizer/CharFilter/TokenFilter)
选择合适Luke版本下载:https://github.com/DmitryKey/luke/releases/
Lucene 5.5 对应 Luke:https://github.com/DmitryKey/luke/releases/tag/luke-5.5.0
4 搜索
流程如下:
// 获取全文实类管理对象
EntityManager em = entityManagerFactory.createEntityManager();
FullTextEntityManager fullTextEntityManager =
org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
// 开始事务
em.getTransaction().begin();
// 用查询DSL创建一个原生的Lucene查询 --create native Lucene query unsing the query DSL
// 也可以用Lucene查询解析类来写 --alternatively you can write the Lucene query using the Lucene query parser
// 用Lucene编辑API也可以,但推荐使用 Hibernate Search 的 DSL --or the Lucene programmatic API. The Hibernate Search DSL is recommended though
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity(Book.class).get();
org.apache.lucene.search.Query luceneQuery = qb
.keyword()
.onFields("title", "subtitle", "authors.name")
.matching("Java rocks!")
.createQuery();
// 包装Lucene查询 --wrap Lucene query in a javax.persistence.Query
javax.persistence.Query jpaQuery =
fullTextEntityManager.createFullTextQuery(luceneQuery, Book.class);
// 执行搜索 --execute search
List result = jpaQuery.getResultList();
// 提交事务
em.getTransaction().commit();
em.close();
5 分词
5.1 配置分词器
- 在配置文件里配置
hibernate.search.analyzer=org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer
- 在实体类上配置
@Analyzer
注解指定 - 在实体类的字段上配置
@Analyzer
注解指定
5.2 自定义分词器
@AnalyzerDef
注解可以在任何实体上定义声明分词器,然后可以在任意实体上通过@Analyzer
注解引用它。
如下:
@Entity
@Indexed
@AnalyzerDef(name = "customanalyzer",
tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = {
@Parameter(name = "language", value = "English")
})
})
public class Book {
@Id
@GeneratedValue
@DocumentId
private Integer id;
@Field
@Analyzer(definition = "customanalyzer")
private String title;
...
注意:本文归作者所有,未经作者允许,不得转载