给定两个实体
Organization
和 Job
及其使用 Hibernate Search 的索引(我被迫仍然使用 HS 5.12)。
@Entity
@Indexed(index = "idx_organization")
public class Organization {
// ...
@OneToMany(mappedBy = "orga", cascade = CascadeType.ALL, orphanRemoval = true)
@IndexEmbedded
final private Set<Job> jobs = new HashSet<>();
}
@Entity
@Indexed(index = "idx_job")
public class Job {
// ...
@NotNull
@ManyToOne
@JoinColumn(nullable = false)
@ContainedIn
private Organization orga;
@NotNull
@Column(nullable = false)
private String title;
@Nullable
@Field
private OffsetDateTime archivedOn;
@Nullable
@Field
private OffsetDateTime publishedOn;
}
我想要获取所有至少拥有一项
Job
a
以及 a.publishedOn != null
和 a.archivedOn == null
的组织(即至少拥有一项已发布且非存档作业的组织)
这是我尝试过的,但结果不包括拥有 2 个已发布职位且其中一个已存档的组织。
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
QueryBuilder qb = fullTextEntityManager
.getSearchFactory()
.buildQueryBuilder()
.forEntity(Organization.class)
.get()
final var q = qb.bool();
q.must(qb.keyword()
.wildcard()
.onField(Organization_.JOBS + "." + Job_.PUBLISHED_ON)
.ignoreFieldBridge()
.matching("*")
.createQuery()
);
q.must(qb.bool().must(
qb.keyword()
.wildcard()
.onField(Organization_.JOBS + "." + Job_.ARCHIVED_ON)
.ignoreFieldBridge()
.matching("*")
.createQuery()
).not() // <-- note the "not"
.createQuery()
);
我被迫仍然使用 HS 5.12
我猜你的意思是 5.11,因为 5.12 不存在。
我想要获取所有至少拥有一项作业 a 且 a.publishedOn != null 且 a.archivedOn == null 的组织
这在 Hibernate Search 5 中的查询时是不可能的。
nested
谓词。
在 Hibernate Search 5 中您能做的最好的事情就是在索引时执行两个条件的组合,如下所示。
@Entity
@Indexed(index = "idx_job")
public class Job {
// ...
@NotNull
@ManyToOne
@JoinColumn(nullable = false)
@ContainedIn
private Organization orga;
@NotNull
@Column(nullable = false)
private String title;
@Nullable
@Field
private OffsetDateTime archivedOn;
@Nullable
@Field
private OffsetDateTime publishedOn;
@Field
@javax.persistence.Transient
public boolean isLive() {
return publishedOn != null && archivedOn == null;
}
}
重新索引您的数据,然后您可以使用新字段,如下所示。
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
QueryBuilder qb = fullTextEntityManager
.getSearchFactory()
.buildQueryBuilder()
.forEntity(Organization.class)
.get()
final var q = qb.bool();
q.must(qb.keyword()
.wildcard()
.onField(Organization_.JOBS + ".live")
.matching(true)
.createQuery()
);