如何解决使用Hibernate Search进行部分日期匹配
我们有以下要求
作为搜索的一部分,用户可以搜索一个人的出生日期。一般而言,用户从前端的日期选择器中选择此方法效果很好,并且搜索按预期进行。
但是,我们现在有一个要求,即用户可能不知道确切的出生日期,例如,他们可能只知道出生的年份。
我尝试过的
@Basic
@Field
@Field(name = "dob_string",bridge = @FieldBridge(impl = CustomDateStringBridge.class),analyzer = @Analyzer(definition = "dob_string_analyzer"))
@Column(name = "date_of_birth")
private Date dateOfBirth;
CustomDateStringBridge类仅以字符串形式返回日期,例如19780418,它可以正常工作。
问题是当我们尝试在dob_string字段上查询时
我们在整体查询中包含以下内容
partialDOB = DIGIT_ONLY_PATTERN.matcher(partialDOB).replaceAll("");
bool.must(queryBuilder.keyword()
.wildcard()
.onField("datesOfBirth.dob_string")
.ignoreFieldBridge()
.ignoreAnalyzer()
.matching("*"+partialDOB+"*")
.createQuery());
但这会导致以下错误
"type": "parse_exception","reason": "failed to parse date field [*1979*] with format [
strict_date_optional_time||epoch_millis]"
我尝试了不使用ignoreAnalyzer和ignoreFieldBridge,但是最终出现了不同的错误
只是想知道是否有可能在日期上进行这种通配符搜索?如果有人对此有任何想法。
谢谢
解决方法
首先,我建议使用另一种方法,因为通配符查询(尤其是带前导通配符的查询)的性能可能非常差。
请保留日期字段,并利用数字查询。
- 卸下桥,以便日期保留为日期
- 依靠range queries查找特定年份,月份或日期内的日期。
例如,要搜索给定年份:
// Input
int yearAsInteger = ...;
// Replace this with the user timezone if your Date instances
// are created for a user timezone different from the system default
ZoneId timezone = ZoneId.systemDefault();
Year year = Year.of( yearAsInteger );
Date startOfYear = Date.from( year.atDay( 1 ).atStartOfDay( timezone ).toInstant() );
Date startOfNextYear = Date.from( year.plusYear( 1L ).atDay( 1 ).atStartOfDay( timezone ).toInstant() );
bool.must(queryBuilder.range()
.onField("datesOfBirth.dateOfBirth")
.from(startOfYear)
.to(startOfNextYear).excludeLimit()
.createQuery());
现在,如果您真的想使用字符串字段...问题出在您的Elasticsearch映射中。字段dob_string
在Elasticsearch的映射中注册为“日期”字段,而您希望它是一个字符串。
通过在网桥中实现MetadataProvidingFieldBridge
并以这种方式提供字段类型,您应该能够告诉Hibernate Search这是一个字符串字段:
@Override
public void configureFieldMetadata(String name,FieldMetadataBuilder builder) {
builder.field( name,FieldType.STRING );
}
在此更改之后,别忘了删除并重新创建您的Elasticsearch索引。
或者,您也可以移至Hibernate Search 6。它处于测试阶段,但是已经稳定,即将发布,并且那里的Elasticsearch支持要好得多(不再是实验性的)。但是,API是不同的,因此,如果您已经拥有扩展的代码库,则将需要大量工作进行迁移。我正在写我们正在编写的迁移指南。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。