Hibernate Search查询返回空列表问题求助
你用Spring Boot+Hibernate 5.1搭配Hibernate Search 5.5.3做全文检索时遇到了返回空列表的问题,我仔细看了你的代码,这里给你几个排查方向和修复建议:
1. 先确认索引是否真的构建成功
你调用了startAndWait()触发索引构建,但得确保这一步真的完成,且数据库里确实存在符合条件的Application数据。可以给索引器加上进度监控,通过控制台日志确认索引进度:
MassIndexer indexer = fullTextEntityManager.createIndexer(); // 添加进度监控,控制台会打印索引的条数和进度 indexer.progressMonitor(new SimpleIndexingProgressMonitor()); indexer.startAndWait();
另外,检查Hibernate Search配置的索引存储目录(比如你配置的./lucene/indexes),如果目录是空的,说明索引根本没构建成功,得先排查索引生成的基础问题。
2. 字段注解配置影响查询匹配
你的reference字段用了@Field(index = Index.YES, analyze = Analyze.NO, store = Store.YES),这个配置意味着:
- 字段会被索引,但不会做分词处理,是原样存储到索引中的
- 没有做大小写转换,你的通配符查询
matching("di*")只会匹配reference值完全以小写"di"开头的记录
如果数据库里的reference是大写(比如DI123)或混合大小写(比如DiAbc),就会匹配不到。解决这个问题有两种思路:
思路一:给字段添加大小写归一化
在实体类中定义小写归一化器,让索引时自动把reference转成小写:
import org.hibernate.search.annotations.NormalizerDef; import org.hibernate.search.annotations.TokenFilterDef; import org.hibernate.search.annotations.LowerCaseFilterFactory; @Entity @Indexed @NormalizerDef(name = "lowercase", filters = @TokenFilterDef(factory = LowerCaseFilterFactory.class)) @Table(name = "application",uniqueConstraints = {@UniqueConstraint(columnNames = "reference")}) public class Application implements Serializable { // ... @Field(index = Index.YES, analyze = Analyze.NO, store = Store.YES) @Normalizer(definition = "lowercase") // 应用小写归一化器 @Column(name = "reference") private String reference; // ... }
这样不管数据库里的reference是什么大小写,索引里都会存成小写,你用di*就能匹配到所有以di(不区分大小写)开头的记录。
思路二:修改查询的匹配值
如果不想改动索引配置,可以把查询的匹配值改成和数据库里一致的大小写,比如数据库里是大写开头,就用DI*查询:
org.apache.lucene.search.Query luceneQuery = queryBuilder.keyword().wildcard() .onField("reference") .matching("DI*") // 和数据库值大小写保持一致 .createQuery();
3. 验证生成的Lucene查询是否符合预期
可以在代码里打印出生成的Lucene查询字符串,确认查询的字段和匹配规则是否符合你的预期:
org.apache.lucene.search.Query luceneQuery = queryBuilder.keyword().wildcard() .onField("reference") .matching("di*") .createQuery(); System.out.println("生成的Lucene查询:" + luceneQuery.toString());
如果输出的查询不是针对reference字段的通配符查询,那可能是QueryBuilder的调用逻辑有问题。
4. 检查事务的影响
如果你是在同一个事务里先插入Application数据,然后立即执行索引构建,可能因为事务未提交,Hibernate Search看不到未提交的数据。确保执行索引构建前,数据已经提交到数据库(比如插入数据后调用em.flush()和em.clear(),或者在单独的事务中执行索引构建)。
内容的提问来源于stack exchange,提问作者fatma pico

