HibernateSearch 中的查询不按更新数据排序
The query in HibernateSearch does not sort by updated data
我正在使用 HibernateSearch 5.7.1.Final
和来自 Java 的 ElasticSearch。
我的模型中有两种主要类型的 object,
Book
和 Journal
,继承自 class Record
并共享一些共同的属性:rank
和 title
。
一本书的典型排名是 1
和期刊的典型值
是 2
,但有时可能不同。
我创建了一些具有默认排名的数据,但对于一本书
我想测试是否会尊重排名值的更新
在查询结果中。
保存前我先把它的值设为0
:
...
Book book03 = new Book("Special Book", prus);
book03.setRank(0);
session.save(book03);
然后我使用 Hibernate(不是 HibernateSearch)获得 object
机制,并更新值:
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();
现在我想获取所有的书籍和期刊,并按排名排序。
我使用布尔查询组合了书籍查询和期刊查询。
我不知道如何在不包含任何条件的情况下获取特定类型的所有 object,所以我查询
object 标题中有任何内容。
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
(这个值在打印时显示object),
但在排序过程中使用了值 0
(这就是 Special Book
登上顶峰的原因)。
如您所见,我尝试重置 session 以便不缓存任何内容,
但它没有帮助。
我的另一个假设是 rank
不是唯一的元素
这会影响排序,但也会考虑一些 相关性 ,
因为当我不使用布尔值时问题不会发生
询问。当我只求书时,Special Book
是最后一个
在结果列表中。但我更愿意使用组合查询
这样我就可以对结果进行分页了。
默认情况下,Elasticsearch(和 Hibernate Search,当它使用 Elasticsearch 时)接近实时,这意味着在您更新之前会有轻微的延迟(默认情况下为 1 秒)影响搜索查询的结果。考虑更新的时刻称为 "refresh".
您是否尝试在更新后添加轻微的停顿(例如 2 秒)?
如果它解决了问题,那么就是刷新延迟导致的。在现实世界的情况下,延迟可能不是问题,因为您很少会执行更新,然后在需要索引完全最新的情况下立即执行查询。
如果你确实有这样的需求,你可以将 属性 hibernate.search.default.elasticsearch.refresh_after_write
设置为 true
。不过请注意,这会对性能产生负面影响。
我正在使用 HibernateSearch 5.7.1.Final
和来自 Java 的 ElasticSearch。
我的模型中有两种主要类型的 object,
Book
和 Journal
,继承自 class Record
并共享一些共同的属性:rank
和 title
。
一本书的典型排名是 1
和期刊的典型值
是 2
,但有时可能不同。
我创建了一些具有默认排名的数据,但对于一本书 我想测试是否会尊重排名值的更新 在查询结果中。
保存前我先把它的值设为0
:
...
Book book03 = new Book("Special Book", prus);
book03.setRank(0);
session.save(book03);
然后我使用 Hibernate(不是 HibernateSearch)获得 object 机制,并更新值:
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();
现在我想获取所有的书籍和期刊,并按排名排序。 我使用布尔查询组合了书籍查询和期刊查询。 我不知道如何在不包含任何条件的情况下获取特定类型的所有 object,所以我查询 object 标题中有任何内容。
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
(这个值在打印时显示object),
但在排序过程中使用了值 0
(这就是 Special Book
登上顶峰的原因)。
如您所见,我尝试重置 session 以便不缓存任何内容, 但它没有帮助。
我的另一个假设是 rank
不是唯一的元素
这会影响排序,但也会考虑一些 相关性 ,
因为当我不使用布尔值时问题不会发生
询问。当我只求书时,Special Book
是最后一个
在结果列表中。但我更愿意使用组合查询
这样我就可以对结果进行分页了。
默认情况下,Elasticsearch(和 Hibernate Search,当它使用 Elasticsearch 时)接近实时,这意味着在您更新之前会有轻微的延迟(默认情况下为 1 秒)影响搜索查询的结果。考虑更新的时刻称为 "refresh".
您是否尝试在更新后添加轻微的停顿(例如 2 秒)?
如果它解决了问题,那么就是刷新延迟导致的。在现实世界的情况下,延迟可能不是问题,因为您很少会执行更新,然后在需要索引完全最新的情况下立即执行查询。
如果你确实有这样的需求,你可以将 属性 hibernate.search.default.elasticsearch.refresh_after_write
设置为 true
。不过请注意,这会对性能产生负面影响。