java - Hibernate 搜索多个实体的查询

标签 java hibernate lucene hibernate-search

我想在具有特定于实体的限制的多个实体上构建 hibernate 查询。理想情况下,所有结果都将从同一查询返回,以便可以根据相关性对它们进行排序。

实体是事件、组和地点(Postable 的每个子类)和配置文件。对事件的限制是它们在今天或将来开始。 Postables 的限制是它们都具有 PostableVisibility.PUBLIC 的可见性。

Profile 类没有可见性字段,只有 Event 类有 Schedule.startDate。此外,个人资料和帖子有不同的搜索字段(共同点是“名称”)。我已经能够单独创建可见性/开始日期限制,但无法应用这两个限制并获取所有类(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,因此它们不匹配。

表达您想要的内容的更好方法是要求所有结果都没有过去的 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();

关于java - Hibernate 搜索多个实体的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53414076/

相关文章:

java - 隐式调用父类(super class)中的无参构造函数

java - 没有 JDBC 类型 : 1111 的方言映射

solr - Apache Solr : More Like This customization

java - Hibernate 无法使用 Spring Boot 在编译的 jar 中创建entityManagerFactory bean

java - 何时在 lucene 中进行索引

algorithm - 为非英语字符启用 soundex/metaphone

java - 在 Java 客户端和 .NET 服务器之间建立通信

java - 尝试比较两个数组并打印第一个数组的行(如果它们匹配)并为整个第一个数组循环它

Java 新手需要友好的帮助建议,在文本字段中阅读以使按钮出现/更改

java - PagingAndSortingRepository (Spring MVC) 和 Hibernate