我必須編寫一個休眠搜索查詢(用於彈性搜索數據庫後端),其中包括這種條件類型:
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;
}
...
}
據我所知,對於每個Depot
,最多只有一個Acte
和一個Vente
。所以你想要做的有點奇怪,因為排序過濾通常用於多值嵌套對象。
它不起作用的原因是您沒有將@IndexedEmbedded
對象 (vente, acte)標記為“嵌套”;如文檔中所述,過濾僅適用於嵌套對象。並且“嵌套”有一個非常精確的含義,它與“索引嵌入”不是同義詞。
但是,我認為在這種情況下整個方法是錯誤的:您不應該使用過濾。我很確定,即使您將@IndexedEmbedded
對象標記為“嵌套”,您也會面臨其他問題,因為您嘗試做的並不是過濾的預期目的。這些問題之一可能是性能;嵌套文檔意味著運行時連接,並且運行時連接並不便宜。
相反,請考慮在編制索引時解決此問題。在搜索時不要試圖找出每個文檔使用哪個日期,而是在索引時這樣做:
@Entity
@Indexed
public class Depot {
//...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "vente_fk")
protected Vente vente;
@IndexedEmbedded(includePaths = {
Vente_.ID,
Vente_.DATE_FOR_SORT, // <================= ADD THIS
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;
}
// v================= ADD THIS
@Transient
@IndexingDependency(derivedFrom = {
@ObjectPath(@PropertyValue(propertyName = Vente_.DATE_SIGNATURE)),
@ObjectPath(@PropertyValue(propertyName = Vente_.ACTE), @PropertyValue(propertyName = Acte_.SIGNATURE)),
})
public Date getDateForSort() {
if ( getDateSignature() != null ) {
return getDateSignature();
}
else {
return getActe().getSignature();
}
}
// ^================= ADD THIS
//...
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句