如何在嵌入式实体中使用@Facet?

时间:2019-02-25 17:50:02

标签: hibernate-search

我正在尝试从HS 4升级到5,但是在多方面搜索方面遇到了麻烦。我知道@Facet需要添加到多面字段中,例如,已经看到this。但是我要使用的多面字段向下嵌入了2个级别,而我得到的只是这个错误:

org.hibernate.search.exception.SearchException: HSEARCH000268: Facet request 'ClientId' tries to facet on  field 'scan.clientGroup.id' which either does not exist or is not configured for faceting (via @Facet). Check your configuration.

我已经在嵌入式实体中尝试过@Facet了许多不同的风格,但是似乎没有任何作用-我想知道应该如何设置它,谢谢。

2 个答案:

答案 0 :(得分:1)

您在your answer中提到的解决方案是正确的。

另一种解决方案是让@IndexedEmbedded从子级到父级,直接在父级id属性上添加@Facet,并在构面请求中使用parent.parentId作为字段名称,如the PR I just sent所示。

您的解决方案的主要优点是,如果Parent本身已被索引(如果它具有自己的索引),则父级的索引不会不必要地被构面字段污染(与我的解决方案相反) )。

该解决方案的主要缺点是,您实际上是在实体的瞬态字段上声明一个索引字段(在JPA的意义上是瞬态的,即,不直接映射到数据库列)。这意味着Hibernate Search无法确定何时更改该值,因此,每当Child的属性发生更改时,Hibernate Search将禁用某些优化并重新索引Child实体, any 属性,甚至无关。 但是,如果您的实体很小,很少更新或实例数量有限,则这可能无关紧要。请记住这一点,如果您以后发现似乎无缘无故地发现大量数据库读取。

答案 1 :(得分:0)

我想出了一个解决方案。我不知道这是否是推荐的方法,也许@yrodiere可以发表评论?

基本上只需在根实体上添加带有相关@Facet注释的getter方法:

@Indexed
@Entity
public class Child {

...

    @ManyToOne
    @IndexedEmbedded(includeEmbeddedObjectId = true)
    Parent parent;

    @Field(analyze = Analyze.NO)
    @Facet(encoding = FacetEncodingType.STRING)
    public Long getParentId() {
        return parent != null ? parent.getId() : null;
    }
}

然后在查询中:

FullTextQuery fullTextQuery = ftem.createFullTextQuery(luceneQuery);

        FacetingRequest facetingRequest = builder.facet()
                .name("facetRequest")
                .onField("parentId")
                .discrete()
                .orderedBy(FacetSortOrder.COUNT_DESC)
                .includeZeroCounts(false)
                .maxFacetCount(10)
                .createFacetingRequest();

        FacetManager facetManager = fullTextQuery.getFacetManager();
        facetManager.enableFaceting(facetingRequest);

        List<Facet> facets = facetManager.getFacets("facetRequest");

在这种情况下,我还必须将字段编码为字符串,以允许使用离散构面(而不是范围),因为默认情况下它是数字字段。