Я пытаюсь изменить некоторый код, используя запрос 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);
Так что, по сути, я думаю, что вложил туда все самое необходимое. Чего я не могу понять, так это того, как добавить подзапрос или что-то, производящее аналогичную функциональность, чтобы я мог просто запрашивать самые последние записи каждого типа?
На данный момент самым простым решением для объединения запросов ORM с поисковыми запросами является добавление к вашему поисковому запросу предложения для фильтрации по идентификатору.
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
Другим решением может быть присвоение одного и того же идентификатора документа всем лицам, которых вы считаете идентичными. Таким образом, в индексе всегда будет только один человек: последний, который был изменен. См. https://docs.jboss.org/hibernate/search/5.11/reference/en-US/html_single/#id-annotation Однако вы можете столкнуться с некоторыми проблемами при извлечении объекта, соответствующего данному документу, поскольку совпадут несколько объектов. Вот почему использование Envers было бы лучшей идеей.
Спасибо, очень понятно и исчерпывающе. Я думаю, что попробую ваш подход к идентификации, поскольку я думаю, что кодовая база, над которой я работаю, находится в постоянном движении, и поэтому, даже если она немного неэффективна в моем сценарии, она будет функционально адекватной, и я подозреваю, что у нас будут изменения, которые сделают ее легче сделать это и/или подумать, является ли поиск подходящим инструментом для задачи, которую мы пытаемся выполнить. На данный момент я совершаю грех, опуская голову и пытаясь изменить то, что есть, просто «чтобы заставить это работать», и ваш ответ идеально подходит для этого!