【发布时间】:2021-10-04 10:43:05
【问题描述】:
我必须编写一个休眠搜索查询(用于弹性搜索数据库后端),其中包括这种条件排序:
Date dateOfBirth = new Date('01/01/2000');
Integer age = 10;
if (dateOfBirth == null) {
//then sort by age
}
else {
//sort by date of birth
}
我在 Hibernate Search Reference 中找到了一个对这种条件排序进行编码的示例,可以这样完成(引用示例):
List<Author> hits = searchSession.search( Author.class )
.where( f -> f.matchAll() )
.sort( f -> f.field( "books.pageCount" )
.mode( SortMode.AVG )
.filter( pf -> pf.match().field( "books.genre" )
.matching( Genre.CRIME_FICTION ) ) )
.fetchHits( 20 );
我的问题是我休眠搜索在运行时引发异常。我的排序过滤器代码:
case DATE_SIGNATURE:
FieldSortOptionsStep bivSortFirst = f.field(Depot_.VENTE + "." + Vente_.DATE_SIGNATURE)
.filter(fa ->
{
PredicateFinalStep a = fa.bool(bo -> bo.must(fa.exists().field(Depot_.VENTE + "." + Vente_.DATE_SIGNATURE)));
return fa.bool(b0 -> b0.must(a));
}
);
FieldSortOptionsStep bivSortSecond = f.field(Depot_.VENTE + "." + Vente_.ACTE + "." + Acte_.SIGNATURE)
.filter(fa ->
{
PredicateFinalStep a = fa.bool(bo -> bo.mustNot(fa.exists().field(Depot_.VENTE + "." + Vente_.DATE_SIGNATURE)));
PredicateFinalStep b = fa.bool(bo -> bo.must(fa.exists().field(Depot_.VENTE + "." + Vente_.ACTE + "." + Acte_.SIGNATURE)));
return fa.bool(b0 -> b0.must(a).must(b));
}
);
sortFieldOrderedList.add(bivSortFirst);
sortFieldOrderedList.add(bivSortSecond);
break;
在上面的示例中,我按优先级对两个字段进行排序。第一个可同化为“出生日期”,第二个可同化为“年龄”。在运行时,过滤器不被休眠搜索接受,然后抛出如下异常:
错误信息:
HSEARCH400604:排序过滤器无效:字段“vente.acte.signature”为 不包含在嵌套对象中。排序过滤器仅在以下情况下可用 要排序的字段包含在嵌套对象中。上下文:字段 'vente.acte.signature'
我是这样做的,我需要使用“inner_hits”查询来进行弹性搜索。但是如何使用休眠搜索 API 做到这一点?
谢谢。
编辑:类的休眠映射:
@Entity
@Indexed
public class Depot {
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "vente_fk")
protected Vente vente;
@IndexedEmbedded(includePaths = {
Vente_.ID,
Vente_.DATE_SIGNATURE,
Vente_.DATE_SIGNATURE_ACTE,
Vente_.ACTE + "." + Acte_.SIGNATURE,
and much more
}
public Vente getVente() {
return this.vente;
}
...
}
@Entity
public class Vente {
@OneToMany(mappedBy = Depot_.VENTE, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
protected Set<Depot> depot = new HashSet<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "acte_fk")
protected Acte acte;
...
@AssociationInverseSide(inversePath = @ObjectPath(@PropertyValue(propertyName = Acte_.VENTE)))
@IndexedEmbedded
public Acte getActe() {
return this.acte;
}
...
}
@Entity
public class Acte {
...
@GenericField(projectable = Projectable.YES, sortable = Sortable.YES, aggregable = Aggregable.YES)
protected Date signature;
@OneToMany(mappedBy = Vente_.ACTE)
protected Set<Vente> vente = new HashSet<>();
public Date getSignature() {
return this.signature;
}
...
}
【问题讨论】:
-
您需要展示您的模型,以便人们了解您要做什么。特别是:
Vente、Acte,以及任何超类或超接口。 -
当然还有
Depot。 -
Depot 是根文档(@Indexed)。 Vente 是@indexEmbedded。 Acte 是@IndexEmbedded。索引文档看起来像 json (_source 是 Depot): _source { vente: { acte: { signature: { } } } 是否足够?
-
恐怕不是。我需要查看实际的注释属性,例如
Depot#vente、Vente#acte等。 -
ok 添加到编辑部分。
标签: elasticsearch hibernate-search