Reputation: 2130
I am trying to modify some code using a hibernate FullTextEntityManager query. Essentially it works currently but I would like to constrain the results to a subset of records in a table (the most recent of a given type).
So for example the underlying query of data to search might be something along these lines (for demonstration only, I haven't parsed this!)
SELECT name, address
FROM Persons p
WHERE p.name = sq.name
FROM
(SELECT name, max(datemodified)
FROM Persons
GROUP BY name) sq
Currently the java code is just selecting from the raw table (essentially this is what the forEntity option does I think)
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);
So essentially I think I've put the essentials in there quite faithfully. What I can't quite work out is how to add a sub query or something producing similar functionality so that I can just query the most recent records of each type ?
Upvotes: 0
Views: 532
Reputation: 9977
At the moment the easiest solution to combine ORM queries with Search queries is to add a clause to you search query to filter by 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);
If that is not an option, you should look for a way to index the data you need to reproduce the SQL query using a full-text query.
In your case, you seem to be using a custom-built versioning system.
One solution would be to use Hibernate Envers instead, which last time I checked was fully compatible with Hibernate Search. See http://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#envers
Another solution would be to assign the same document ID to all persons that you consider identical. That way, there would only ever be a single person in the index: the last that was modified. See https://docs.jboss.org/hibernate/search/5.11/reference/en-US/html_single/#id-annotation You may however run into some trouble when fetching the entity matching a given document, since multiple entities would match. That's why using Envers would be a better idea.
Upvotes: 1