休眠搜索:使用過濾器對嵌套對象進行排序,如何?

弗朗索瓦·F。

我必須編寫一個休眠搜索查詢(用於彈性搜索數據庫後端),其中包括這種條件類型:

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在javascript中過濾嵌套對象屬性並打印新對象

如何對雙重對象進行排序?

使用 lodash 對嵌套對象進行分組

如何按值過濾嵌套的對像數組並獲取根對象

如何根據對象屬性對對象列表進行排序?

過濾對象列表

類型錯誤:過濾器類型的對像不是 JSON 可序列化的 - 嵌套對象

如何按值按字母順序對對象進行排序?

如何對多個對象的屬性進行排序

從對像數組中組合未知的對象子數組並對其進行過濾

使用 VB.net 對對象列表進行排序

如何將 DF groupby 對象過濾到列表

React 使用過濾器時未呈現的對象列表

使用特殊規則過濾 Django 中的對象

使用 linq 過濾繁瑣的對象列表

Elasticsearch DSL,使用值列表過濾對象列表

基於過濾器對數組進行條件重新渲染

使用 Pandas 對 Excel 中的行進行高級過濾

如何使用計算屬性和道具過濾對象 [VueJS]

如何按 BigQuery 中不同字段中的值對字段進行分組過濾

按值過濾對象

在自定義對象的本機打字稿中搜索過濾器完成後無法分配數據

如何通過在js中使用reduce返回數組中的對象來創建嵌套對象

是否可以通過某些屬性的值過濾嵌套對象?(JS)

如何按對象鍵過濾對像數組?

如何根據特定對象過濾對像數組?

如何使用 jQuery 對多個表進行排序

如何使用 DataTables 插件對重音詞進行排序

使用 Angular 進行服務器端排序、分頁和過濾時,如何在重置過濾器時阻止多次調用