Поисковый запрос Hibernate для нескольких объектов - PullRequest
0 голосов
/ 21 ноября 2018

Я хотел бы построить запрос гибернации по нескольким объектам с ограничениями для конкретных объектов.В идеале все результаты должны быть возвращены из одного и того же запроса, чтобы их можно было отсортировать по релевантности.

Объектами являются Событие, Группа и Место (каждый подкласс Postable) и Профиль.Ограничение на События состоит в том, что они начинаются сегодня или в будущем.Ограничение на Postables заключается в том, что все они имеют видимость PostableVisibility.PUBLIC.

Класс Profile не имеет поля видимости, и только класс Event имеет schedule.startDate.Кроме того, профили и таблицы имеют различные поля для поиска (с общим именем).Я смог создать ограничения видимости / даты начала отдельно, но не смог применить оба ограничения и получить результаты для всех классов.

Вот некоторые подробности о модели предметной области:

@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();
}

1 Ответ

0 голосов
/ 21 ноября 2018

Ваш текущий запрос требует, чтобы все результаты имели в будущем 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...