在休眠的FullTextEntityManager查询中使用子查询

时间:2019-05-28 14:52:56

标签: hibernate hibernate-search

我正在尝试使用休眠的FullTextEntityManager查询修改一些代码。从本质上讲,它目前可以正常工作,但我想将结果限制为表中记录的子集(给定类型的最新记录)。

例如,要搜索的底层数据查询可能与此类似(仅用于演示,我还没有对此进行解析!)

SELECT name, address 
FROM Persons p
WHERE p.name = sq.name
FROM 
(SELECT name, max(datemodified)
 FROM Persons 
  GROUP BY name) sq

当前,java代码只是从原始表中选择(本质上,这就是我认为的forEntity选项)

FullTextEntityManager ftem = Search.getFullTextEntityManager(getEntityManager());

SearchFactory sf= ftem.getSearchFactory();
QueryContextBuilder qcb = sf.buildQueryBuilder();
QueryBuilder qb= qcb.forEntity(entityClass).get();

//processSearchExpression builds a lucene style full text search
org.apache.lucene.search.Query q= processSearchExpression();

FullTextQuery ftq= ftem.createFullTextQuery(q, entityClass);

所以从本质上讲,我认为我已经非常忠实地将要点放入其中。我不能完全解决的是如何添加子查询或产生类似功能的东西,以便我可以查询每种类型的最新记录?

1 个答案:

答案 0 :(得分:1)

目前,将ORM查询与搜索查询结合的最简单的解决方案是在搜索查询中添加一个子句以按ID进行过滤。

FullTextEntityManager ftem = Search.getFullTextEntityManager(getEntityManager());

SearchFactory sf= ftem.getSearchFactory();
QueryBuilder qb= sf.buildQueryBuilder().forEntity(entityClass).get();

BooleanJunction<?> idJunction = qb.bool();
for (Long id : listIdsYouWant()) {
   idJunction.must(qb.match().onField("id").matching(id).createQuery());
}

org.apache.lucene.search.Query q = qb.bool()
   //processSearchExpression builds a lucene style full text search
    .must(processSearchExpression())
    .filteredBy(idJunction.createQuery)
    .createQuery();

FullTextQuery ftq= ftem.createFullTextQuery(q, entityClass);

如果这不是一个选择,则应该寻找一种方法来索引需要使用全文查询来重现SQL查询的数据。

在您的情况下,您似乎正在使用定制的版本控制系统。

一种解决方案是改用Hibernate Envers,这是我上次检查与Hibernate Search完全兼容的方法。参见http://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#envers

另一种解决方案是将相同的文档ID分配给您认为相同的所有人。这样,索引中将永远只有一个人:最后一个被修改的人。参见https://docs.jboss.org/hibernate/search/5.11/reference/en-US/html_single/#id-annotation 但是,在获取与给定文档匹配的实体时,您可能会遇到麻烦,因为会匹配多个实体。这就是使用Envers会是一个更好的主意的原因。