如何过滤Hibernate搜索结果只包括在排序过程中具有特殊字段值的对象之后的对象?

时间:2015-12-21 17:52:36

标签: java hibernate lucene hibernate-search

我在我的存储库中有一个curent方法:

List<Record> getSortedByDate(int limit, int lastId){ 

    FullTextSession fullTextSession = fullTextSession();
    QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Record.class).get();
    // some extra matching

    FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(finalQuery, Record.class);
    fullTextQuery.setMaxResults(limit);
    fullTextQuery.setSort(new Sort(new SortField("created", SortField.Type.LONG, false)));

    // ??? here I have to restrict results to include all records with id
    // which is after lastId in context of current sort

    return fullTextQuery.list(); 
}

我现有实体:

@Entity
@Indexed
public class Record{

    @Id
    @GeneratedValue
    private int id;

    @Field
    @SortableField
    @DateBridge(resolution = DAY)
    private Date created;

    ***
}

我正在使用“已创建”字段对搜索结果进行排序:

我只需要返回那些在此排序的上下文中具有给定“id”字段值的对象之后的对象。例如,如果索引中有3条记录:

{"id": 3, "created": "27.04.13"},
{"id": 1, "created": "29.04.15"},
{"id": 4, "created": "7.10.15"}

我的方法收到lastId 1它必须只返回最后一条记录。

我需要这样做,因为我必须对排序实施适当的分页。

更新 此外,将来我需要不仅按日期实现排序,还要通过其他字段实现排序,例如rating(整数)和reviewsCount(整数),因此按范围限制结果可能不是解决方案,因为一些记录可能具有相同的评级或相同的评论。

更新2 我把@Gunnar的答案与这种过滤相结合,似乎很有效。

Date limitValue = session().get(Record.class, lastId).getCreated();
mainJunction.must(queryBuilder.range().onField("created").above(limitValue).createQuery());
mainJunction.must(queryBuilder.phrase().onField("id").sentence(String.valueOf(lastId)).createQuery()).not();

..其中session()是Hibernate数据库会话。现在我可以安全地使用ratingreviewsCount排序。

1 个答案:

答案 0 :(得分:2)

您可以加载具有给定ID的Record,然后将查询结果限制为在该日期之后创建的记录:

Record lastRecord = ...;

QueryBuilder queryBuilder = fullTextSession
    .getSearchFactory()
    .buildQueryBuilder()
    .forEntity(Record.class).get();

Query query = queryBuilder.range()
    .onField( "created" )
    .above( lastRecord.getCreated() )
    .createQuery();

FullTextQuery fullTextQuery = fulllTextSession.createFullTextQuery(
    query, Record.class
);

您只需选择比DAY更精细的日期分辨率,以便在将页面包装在同一天创建的多个记录中时获得正确的排序。