多个实体的 Hibernate 搜索查询
Hibernate Search query for multiple entities
我想对具有实体特定限制的多个实体构建休眠查询。理想情况下,所有结果都将从同一个查询返回,以便可以根据相关性对它们进行排序。
实体是 Event、Group 和 Place(每个 subclass 的 Postable)和 Profile。对事件的限制是它们从今天或将来开始。 Postables 的限制是它们都具有 PostableVisibility.PUBLIC 的可见性。
个人资料 class 没有可见性字段,只有事件 class 有 schedule.startDate。此外,Profiles 和 Postables 具有不同的搜索字段('name' 是共同的)。我已经能够单独创建 visibility/start 日期限制,但无法同时应用这两个限制并从所有 class 中获得结果。
下面是领域模型的一些细节:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "postables")
public abstract class Postable{
/**
* determines who can see the postable in relation to the creatorId
*/
@Column(name = "visibility", nullable = false)
@Enumerated(EnumType.STRING)
@Field(analyze=Analyze.NO)
protected PostableVisibility visibility;
@Column(name = "name", nullable = false)
@Field
protected String name;
@Column(name = "type", nullable = false)
@Field
protected String type;
@Column(name = "description", nullable = false)
@Field
protected String description;
}
@Entity
@Table(name = "events")
@Indexed
public class Event extends Postable {
@IndexedEmbedded
private Schedule schedule;
}
@Embeddable
public class Schedule {
@Column(name = "end_date")
private LocalDate endDate;
@Column(name = "end_time")
private LocalTime endTime;
@Column(name = "start_date")
@Field
private LocalDate startDate;
@Column(name = "start_time")
@Field
private LocalTime startTime;
}
@Entity
@Table(name = "groups")
@Indexed
public class Group extends Postable {
}
@Entity
@Table(name = "places")
@Indexed
public class Place extends Postable {
}
public class Profile {
@Column(name = "name")
@Field
private String name;
@Column(name = "username")
@Field(analyze= Analyze.NO)
private String username;
}
最后,尝试构建查询。我已经尝试过使用不同的查询构建器组合但没有成功。对于下面的查询,用户查询、可见性限制和当前事件限制都已应用,但我只获得事件的结果。
public List<Object> searchAll(String userQueryString) {
int maxResults = 20;
Session session = this.currentSession();
FullTextSession fullTextSession = Search.getFullTextSession(session);
// Query builders:
QueryBuilder postableQB = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Postable.class).get();
QueryBuilder eventQB = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Event.class).get();
// Filter queries
Query publicPostableQuery = postableQB.keyword().onField("visibility").matching(PostableVisibility.PUBLIC).createQuery();
String defaultTimeZone = "America/New_York";
LocalDate today = LocalDate.now(ZoneId.of(defaultTimeZone));
Query currentEventQuery = eventQB.range().onField("schedule.startDate").above(today).createQuery();
// User text query
Query userQuery = postableQB.simpleQueryString().onField("name").boostedTo(5f) // working
.andField("type").boostedTo(3f)
.andField("description")
.andField("username").boostedTo(5f)
.matching(userQueryString)
.createQuery();
Query combinedQuery = postableQB.bool()
.must(userQuery)
.must(publicPostableQuery)
.must(currentEventQuery)
.createQuery();
FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(combinedQuery, Postable.class, Profile.class);
fullTextQuery.setFirstResult(0).setMaxResults(maxResults);
return fullTextQuery.list();
}
您当前的查询要求所有结果都有一个 startDate
将来,即使它们不是事件。由于非事件没有 startDate
,它们不匹配。
表达您想要的内容的更好方法是询问 none 的结果有一个 startDate
过去。这样,没有 startDate
的文档也会匹配。可见性也是如此,它不包含在配置文件中。
Query privatePostableQuery = postableQB.bool()
.should(postableQB.keyword().onField("visibility").matching(PostableVisibility.FOLLOWERS).createQuery())
.should(postableQB.keyword().onField("visibility").matching(PostableVisibility.INVITE).createQuery())
.createQuery();
String defaultTimeZone = "America/New_York";
LocalDate today = LocalDate.now(ZoneId.of(defaultTimeZone));
Query pastEventQuery = eventQB.range().onField("schedule.startDate").below(today).excludeLimit().createQuery();
// User text query
Query userQuery = postableQB.simpleQueryString().onField("name").boostedTo(5f) // working
.andField("type").boostedTo(3f)
.andField("description")
.andField("username").boostedTo(5f)
.matching(userQueryString)
.createQuery();
Query combinedQuery = postableQB.bool()
.must(userQuery)
.must(privatePostableQuery).not()
.must(pastEventQuery).not()
.createQuery();
我想对具有实体特定限制的多个实体构建休眠查询。理想情况下,所有结果都将从同一个查询返回,以便可以根据相关性对它们进行排序。
实体是 Event、Group 和 Place(每个 subclass 的 Postable)和 Profile。对事件的限制是它们从今天或将来开始。 Postables 的限制是它们都具有 PostableVisibility.PUBLIC 的可见性。
个人资料 class 没有可见性字段,只有事件 class 有 schedule.startDate。此外,Profiles 和 Postables 具有不同的搜索字段('name' 是共同的)。我已经能够单独创建 visibility/start 日期限制,但无法同时应用这两个限制并从所有 class 中获得结果。
下面是领域模型的一些细节:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "postables")
public abstract class Postable{
/**
* determines who can see the postable in relation to the creatorId
*/
@Column(name = "visibility", nullable = false)
@Enumerated(EnumType.STRING)
@Field(analyze=Analyze.NO)
protected PostableVisibility visibility;
@Column(name = "name", nullable = false)
@Field
protected String name;
@Column(name = "type", nullable = false)
@Field
protected String type;
@Column(name = "description", nullable = false)
@Field
protected String description;
}
@Entity
@Table(name = "events")
@Indexed
public class Event extends Postable {
@IndexedEmbedded
private Schedule schedule;
}
@Embeddable
public class Schedule {
@Column(name = "end_date")
private LocalDate endDate;
@Column(name = "end_time")
private LocalTime endTime;
@Column(name = "start_date")
@Field
private LocalDate startDate;
@Column(name = "start_time")
@Field
private LocalTime startTime;
}
@Entity
@Table(name = "groups")
@Indexed
public class Group extends Postable {
}
@Entity
@Table(name = "places")
@Indexed
public class Place extends Postable {
}
public class Profile {
@Column(name = "name")
@Field
private String name;
@Column(name = "username")
@Field(analyze= Analyze.NO)
private String username;
}
最后,尝试构建查询。我已经尝试过使用不同的查询构建器组合但没有成功。对于下面的查询,用户查询、可见性限制和当前事件限制都已应用,但我只获得事件的结果。
public List<Object> searchAll(String userQueryString) {
int maxResults = 20;
Session session = this.currentSession();
FullTextSession fullTextSession = Search.getFullTextSession(session);
// Query builders:
QueryBuilder postableQB = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Postable.class).get();
QueryBuilder eventQB = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Event.class).get();
// Filter queries
Query publicPostableQuery = postableQB.keyword().onField("visibility").matching(PostableVisibility.PUBLIC).createQuery();
String defaultTimeZone = "America/New_York";
LocalDate today = LocalDate.now(ZoneId.of(defaultTimeZone));
Query currentEventQuery = eventQB.range().onField("schedule.startDate").above(today).createQuery();
// User text query
Query userQuery = postableQB.simpleQueryString().onField("name").boostedTo(5f) // working
.andField("type").boostedTo(3f)
.andField("description")
.andField("username").boostedTo(5f)
.matching(userQueryString)
.createQuery();
Query combinedQuery = postableQB.bool()
.must(userQuery)
.must(publicPostableQuery)
.must(currentEventQuery)
.createQuery();
FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(combinedQuery, Postable.class, Profile.class);
fullTextQuery.setFirstResult(0).setMaxResults(maxResults);
return fullTextQuery.list();
}
您当前的查询要求所有结果都有一个 startDate
将来,即使它们不是事件。由于非事件没有 startDate
,它们不匹配。
表达您想要的内容的更好方法是询问 none 的结果有一个 startDate
过去。这样,没有 startDate
的文档也会匹配。可见性也是如此,它不包含在配置文件中。
Query privatePostableQuery = postableQB.bool()
.should(postableQB.keyword().onField("visibility").matching(PostableVisibility.FOLLOWERS).createQuery())
.should(postableQB.keyword().onField("visibility").matching(PostableVisibility.INVITE).createQuery())
.createQuery();
String defaultTimeZone = "America/New_York";
LocalDate today = LocalDate.now(ZoneId.of(defaultTimeZone));
Query pastEventQuery = eventQB.range().onField("schedule.startDate").below(today).excludeLimit().createQuery();
// User text query
Query userQuery = postableQB.simpleQueryString().onField("name").boostedTo(5f) // working
.andField("type").boostedTo(3f)
.andField("description")
.andField("username").boostedTo(5f)
.matching(userQueryString)
.createQuery();
Query combinedQuery = postableQB.bool()
.must(userQuery)
.must(privatePostableQuery).not()
.must(pastEventQuery).not()
.createQuery();