如何在Lucene查询与Hibernate Search中匹配数值、布尔等非文本字段
解答
非文本字段查询无结果问题
Hibernate Search 5及以上版本对数值、布尔、日期类型的字段默认采用专用的数值编码格式索引,不会存储为普通文本Term。你手动构造Lucene原生TermQuery传入字符串格式的匹配值,无法匹配到底层的编码值,这就是你移除非文本条件后查询正常的核心原因。
正确方案是不要手动构造原生Lucene TermQuery处理非文本字段,统一使用Hibernate Search提供的QueryBuilder构造查询,QueryBuilder会自动根据字段的索引类型生成对应格式的查询语句,不需要额外添加字符串类型的FieldBridge,同时性能比字符串索引更好。
修改后的代码参考:
1. 修改createLanguagePredicate方法
新增QueryBuilder入参,直接传入Long类型数值查询:
private Query createLanguagePredicate(Long languageId, QueryBuilder queryBuilder){ return queryBuilder.keyword() .onField("language.languageId") .matching(languageId) // 不需要调用toString(),直接传Long类型 .createQuery(); }
2. 修改getLanguageCondition方法
传入QueryBuilder,同时显式设置最小匹配数避免逻辑漏洞:
private BooleanQuery getLanguageCondition(Long preferredLanguageId, QueryBuilder queryBuilder) { return new BooleanQuery.Builder() .add(createLanguagePredicate(preferredLanguageId, queryBuilder), BooleanClause.Occur.SHOULD) .add(createLanguagePredicate(languageService.getDefaultLanguage().getId(), queryBuilder), BooleanClause.Occur.SHOULD) .setMinimumNumberShouldMatch(1) // 必须满足至少一个语言条件 .build(); }
3. 替换布尔字段的原生TermQuery
所有布尔字段的查询都通过QueryBuilder构造,直接传入布尔值:
BooleanQuery finalQuery = new BooleanQuery.Builder() .add(queryBuilder.keyword().onField("parentDeleted").matching(false).createQuery(), BooleanClause.Occur.MUST) .add(queryBuilder.keyword().onField("parentApproved").matching(true).createQuery(), BooleanClause.Occur.MUST) .add(queryBuilder.keyword().onField("childDeleted").matching(false).createQuery(), BooleanClause.Occur.MUST) .add(isPreferredOrDefaultLanguageTranslation, BooleanClause.Occur.MUST) .add(containsSearchString, BooleanClause.Occur.MUST) .build();
你之前传入Long到matching()仍无结果,是因为其他布尔字段还在使用原生TermQuery,那些条件本身无法匹配,替换所有非文本字段的查询逻辑即可恢复正常。
@IndexedEmbedded includeEmbeddedObjectId参数说明
你的理解完全正确:
- 将
@IndexedEmbedded(includeEmbeddedObjectId = true)标注在关联属性上时,关联实体的主键会自动索引到当前实体的Lucene文档中,不需要额外给关联实体的主键添加@Field注解,默认字段名为关联属性名.主键字段名。 - 用这个预存的主键字段做过滤条件时,查询速度确实更快:因为值已经直接存储在当前查询的实体对应的Lucene文档里,不需要查询时做跨实体关联,也不需要额外的关联计算,匹配效率和直接查当前实体的原生字段一致。
内容的提问来源于stack exchange,提问作者Maurice
相关产品推荐
相关产品推荐

