在休眠搜索中查找嵌入式实体的计数
Finding counts of embedded entities in hibernate search
我有以下两个实体定义。从 Attribute 到 AttributeValue 的关系是一对多的。我想按指定的属性类别和 return 全部搜索属性实体
匹配具有至少一个关联属性值的属性实体。
我试过的:
我尝试了一种天真的方法,即首先搜索与指定属性类别匹配的所有属性,然后对于每个此类属性,按属性和 return 所有匹配的实体搜索属性值。这样,我就可以确定一个属性是否至少有一个属性值与其相关联。这种方法虽然很慢。
问题:
在休眠搜索中有更好的方法吗? (最好是在搜索属性之后,我已经有了所有属性值计数信息 returned。)我已经阅读了最新休眠中的 Embedded and associated objects 部分查了官方文档也没找到明确的方法。感谢任何帮助。
public class Attribute {
@Id
@DocumentId
@Column(name = "ID")
private Long id;
@Field
@Column(name = "ATTRIBUTE_NAME", unique = true, nullable = false)
private String attributeName;
@Field
@FieldBridge(impl = EnumBridge.class)
@Enumerated(EnumType.STRING)
@Column(name = "ATTRIBUTE_CATEGORY", nullable = false)
private AttributeCategory attributeCategory;
@IndexedEmbedded(includePaths = {"id"})
@OneToMany(fetch = FetchType.LAZY, mappedBy = "attribute", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<AttributeValue> attributeValues = new HashSet<>(); }
public class AttributeValue {
@Id
@DocumentId
@Column(name = "ID")
private Long id;
@Field
@Column(name = "ATTRIBUTE_VALUE_NAME")
private String attributeValueName;
@IndexedEmbedded(includePaths = {"id", "attributeName"})
@ManyToOne
@JoinColumn(name = "ATTRIBUTE_ID")
private Attribute attribute; }
假设所有 AttributeValue
都有一个 ID,您可以尝试这样的操作:
AttributeCategory expectedCategory = ...;
QueryBuilder qb = ...;
Query luceneQuery = qb.bool()
.must( qb.keyword().onField( "attributeCategory" )
.matching( expectedCategory ).createQuery() )
.must( qb.keyword().wildcard().onField( "attributeValues.id" )
.matching( "*" ).createQuery() )
.createQuery();
FullTextQuery query = Search.getSearchEntityManager( entityManager )
.createFullTextQuery( luceneQuery, Attribute.class );
query.setMaxResults( 20 );
List<Attribute> hits = query.getResultList();
在 Hibernate Search 6(Beta 版)中使用 exists
predicate 更直观(并且可能更有效)。但这需要您更改大部分代码,因为 API 不同:
AttributeCategory expectedCategory = ...;
List<Attribute> hits = Search.session( entityManager )
.search( Attribute.class )
.where( f -> f.bool()
.must( f.match().field( "attributeCategory" )
.matching( expectedCategory ) )
.must( f.exists().field( "attributeValue" ) ) )
.fetchHits( 20 );
我有以下两个实体定义。从 Attribute 到 AttributeValue 的关系是一对多的。我想按指定的属性类别和 return 全部搜索属性实体 匹配具有至少一个关联属性值的属性实体。
我试过的:
我尝试了一种天真的方法,即首先搜索与指定属性类别匹配的所有属性,然后对于每个此类属性,按属性和 return 所有匹配的实体搜索属性值。这样,我就可以确定一个属性是否至少有一个属性值与其相关联。这种方法虽然很慢。
问题:
在休眠搜索中有更好的方法吗? (最好是在搜索属性之后,我已经有了所有属性值计数信息 returned。)我已经阅读了最新休眠中的 Embedded and associated objects 部分查了官方文档也没找到明确的方法。感谢任何帮助。
public class Attribute {
@Id
@DocumentId
@Column(name = "ID")
private Long id;
@Field
@Column(name = "ATTRIBUTE_NAME", unique = true, nullable = false)
private String attributeName;
@Field
@FieldBridge(impl = EnumBridge.class)
@Enumerated(EnumType.STRING)
@Column(name = "ATTRIBUTE_CATEGORY", nullable = false)
private AttributeCategory attributeCategory;
@IndexedEmbedded(includePaths = {"id"})
@OneToMany(fetch = FetchType.LAZY, mappedBy = "attribute", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<AttributeValue> attributeValues = new HashSet<>(); }
public class AttributeValue {
@Id
@DocumentId
@Column(name = "ID")
private Long id;
@Field
@Column(name = "ATTRIBUTE_VALUE_NAME")
private String attributeValueName;
@IndexedEmbedded(includePaths = {"id", "attributeName"})
@ManyToOne
@JoinColumn(name = "ATTRIBUTE_ID")
private Attribute attribute; }
假设所有 AttributeValue
都有一个 ID,您可以尝试这样的操作:
AttributeCategory expectedCategory = ...;
QueryBuilder qb = ...;
Query luceneQuery = qb.bool()
.must( qb.keyword().onField( "attributeCategory" )
.matching( expectedCategory ).createQuery() )
.must( qb.keyword().wildcard().onField( "attributeValues.id" )
.matching( "*" ).createQuery() )
.createQuery();
FullTextQuery query = Search.getSearchEntityManager( entityManager )
.createFullTextQuery( luceneQuery, Attribute.class );
query.setMaxResults( 20 );
List<Attribute> hits = query.getResultList();
在 Hibernate Search 6(Beta 版)中使用 exists
predicate 更直观(并且可能更有效)。但这需要您更改大部分代码,因为 API 不同:
AttributeCategory expectedCategory = ...;
List<Attribute> hits = Search.session( entityManager )
.search( Attribute.class )
.where( f -> f.bool()
.must( f.match().field( "attributeCategory" )
.matching( expectedCategory ) )
.must( f.exists().field( "attributeValue" ) ) )
.fetchHits( 20 );