如何将@Facet 与嵌入式实体一起使用?
How to use @Facet with embedded entities?
我正在尝试从 HS 4 升级到 HS 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,但似乎没有任何效果 - 我想知道这是如何设置的,谢谢。
我想出了一个解决办法。我不知道这是否是推荐的方式,也许@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");
在这种情况下,我还必须将该字段编码为字符串以允许使用离散分面,而不是范围,因为默认情况下它是一个数字字段。
您在中提到的解决方案是正确的。
另一个解决方案是从 child 到 parent 有一个 @IndexedEmbedded
,直接在 parent id [=32= 上添加 @Facet
],并在分面请求中使用 parent.parentId
作为字段名称,如 the PR I just sent.
中所示
你的解决方案的主要优点是,如果 Parent
本身被索引(如果它有自己的索引),parent 的索引不会被分面污染不必要的字段(与我的解决方案相反)。
您的解决方案的主要缺点是您实际上在实体中的瞬态字段上声明了索引字段(JPA 意义上的瞬态,即未直接映射到数据库列)。这意味着 Hibernate Search 无法确定该值何时会更改,因此 Hibernate Search 将禁用某些优化,并会在 Child
的 属性 更改时重新索引 Child
实体, 任何 属性,甚至无关。
但是,如果您的实体很小、很少更新或实例数量有限,那么这可能无关紧要。如果您注意到将来似乎无缘无故地读取大量数据库,请记住这一点。
我正在尝试从 HS 4 升级到 HS 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,但似乎没有任何效果 - 我想知道这是如何设置的,谢谢。
我想出了一个解决办法。我不知道这是否是推荐的方式,也许@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");
在这种情况下,我还必须将该字段编码为字符串以允许使用离散分面,而不是范围,因为默认情况下它是一个数字字段。
您在
另一个解决方案是从 child 到 parent 有一个 @IndexedEmbedded
,直接在 parent id [=32= 上添加 @Facet
],并在分面请求中使用 parent.parentId
作为字段名称,如 the PR I just sent.
你的解决方案的主要优点是,如果 Parent
本身被索引(如果它有自己的索引),parent 的索引不会被分面污染不必要的字段(与我的解决方案相反)。
您的解决方案的主要缺点是您实际上在实体中的瞬态字段上声明了索引字段(JPA 意义上的瞬态,即未直接映射到数据库列)。这意味着 Hibernate Search 无法确定该值何时会更改,因此 Hibernate Search 将禁用某些优化,并会在 Child
的 属性 更改时重新索引 Child
实体, 任何 属性,甚至无关。
但是,如果您的实体很小、很少更新或实例数量有限,那么这可能无关紧要。如果您注意到将来似乎无缘无故地读取大量数据库,请记住这一点。