HibernateSearch中的查询不按更新的数据排序

时间:2017-08-07 15:34:43

标签: java elasticsearch hibernate-search

我将HibernateSearch 5.7.1.Final与来自Java的ElasticSearch一起使用。 我的模型中有两种主要类型的对象, BookJournal,继承自班级Record 并分享一些常见属性:ranktitle。 一本书的典型排名是1和期刊的典型值 是2,但有时可能会有所不同。

我创建了一些默认排名的数据,但对于一本书 我想测试是否会尊重排名值的更新 在查询结果中。

我首先将值设置为0,然后保存:

...
Book book03 = new Book("Special Book", prus);
book03.setRank(0);
session.save(book03);

然后我使用Hibernate(而不是HibernateSearch)获取对象 机制,并更新值:

session.clear();
session.beginTransaction();
Criteria specialCriteria = session.createCriteria(Book.class);
Book special = (Book) specialCriteria.add(Restrictions.eq("title", "Special Book")).uniqueResult();
special.setRank(6);
session.saveOrUpdate(special);
session.getTransaction().commit();

现在我想获得所有书籍和期刊,并按等级排序。 我使用布尔查询组合书籍查询和期刊查询。 我不知道如何获取特定类型的所有对象,而不包括任何标准,所以我查询 对于标题中包含任何内容的对象。

session.clear();
sessionFactory.getCache().evictEntityRegions();

FullTextSession fullTextSession = Search.getFullTextSession(session);
fullTextSession.clear();

QueryBuilder bookQueryBuilder = fullTextSession.getSearchFactory()
    .buildQueryBuilder().forEntity(Book.class).get();

QueryBuilder journalQueryBuilder = fullTextSession.getSearchFactory()
    .buildQueryBuilder().forEntity(Journal.class).get();

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

org.apache.lucene.search.Query bookLuceneQuery 
    = bookQueryBuilder.keyword().wildcard().onField("title").matching("*").createQuery();
org.apache.lucene.search.Query journalLuceneQuery 
    = journalQueryBuilder.keyword().wildcard().onField("title").matching("*").createQuery();

org.apache.lucene.search.Query combinedLuceneQuery = generalQueryBuilder
    .bool()
        .should( bookLuceneQuery )
        .should( journalLuceneQuery )
    .createQuery();

FullTextQuery combinedQuery = fullTextSession.createFullTextQuery(combinedLuceneQuery, Record.class);
Sort sort = generalQueryBuilder.sort()
    .byField("rank").asc()
    .createSort();

combinedQuery.setSort(sort);      

List result = combinedQuery.list();

System.out.println("\n\nSearch results for books and journals:");
for(Object object : result)
{
    Record record = (Record) object;
    System.out.println(record.getTitle());
    System.out.println(record.getRank());
    System.out.println();
}

问题是我获得了以下结果:

Special Book
6

book01
1

book02
1

book04
1

journal01
2

journal02
2

看起来价值最终更新为6打印对象时显示此值), 但在排序期间,使用值0 (这就是为什么Special Book达到顶峰的原因。)

正如您所看到的,我尝试重置会话以便不会缓存任何内容, 但它没有帮助。

我的另一个假设是rank不是唯一的元素 这会影响排序,但也会考虑一些相关性, 因为当我不使用布尔值时,问题不会发生 查询。当我只要求书时,Special Book是最后一本 在结果列表中。但我更喜欢使用组合查询 这样我就可以对结果进行分页。

1 个答案:

答案 0 :(得分:2)

默认情况下,Elasticsearch(和Hibernate Search,当它使用Elasticsearch时)接近实时,这意味着在更新影响搜索结果之前会有一点延迟(默认为1秒)查询。将更新考虑在内的时刻称为“刷新”。

您是否尝试在更新后添加一些暂停(例如2秒)? 如果它解决了问题,那么刷新延迟就会导致它。在实际情况下,延迟可能不是问题,因为您很少会执行更新,然后在此之后执行查询,要求索引完全是最新的。 如果您确实有此类要求,则可以将属性hibernate.search.default.elasticsearch.refresh_after_write设置为true。但请注意,这会对性能产生负面影响。