Hibernate Search 6 中 FullTextQuery.setCriteriaQuery() 的替代品是什么?
What is replacement for FullTextQuery.setCriteriaQuery() in Hibernate Search 6?
我正在将 Hibernate Search 5 迁移到 Hibernate Search 6。
虽然 documentation 确实很有帮助,但我无法在 Hibernate Search 6 中找到标准查询的替代方法,也没有完全从文档中获得。
这是我要转换的 Hibernate Search 5 查询,
final Criteria criteria = entityManager.unwrap(Session.class).createCriteria(KnowledgeData.class);
criteria.add(Restrictions.eq("deleted", knowledgeSearchRequest.isDeleted()));
if (knowledgeSearchRequest.isPublished()) {
criteria.add(Restrictions.eq("published", knowledgeSearchRequest.isPublished()));
}
if (!allDesk) {
criteria.add(Restrictions.eq("deskId", deskId));
knowledgeSearchRequest.setDesk(deskId);
} else {
Disjunction orJunction = Restrictions.disjunction();
for (String desk : knowledgeSearchRequest.getDeskIds()) {
orJunction.add(Restrictions.eq("deskId", desk));
}
criteria.add(orJunction);
}
if (knowledgeSearchRequest.getLang() != null && knowledgeSearchRequest.getLang().size() > 0) {
criteria.createAlias("language", "lan");
Disjunction disJunction = Restrictions.disjunction();
for (String lang : knowledgeSearchRequest.getLang()) {
disJunction.add(Restrictions.eq("lan.elements", lang));
}
criteria.add(disJunction);
}
if (knowledgeSearchRequest.getTags() != null && knowledgeSearchRequest.getTags().size() > 0) {
criteria.createAlias("tags", "tag");
Disjunction disJunction = Restrictions.disjunction();
for (String tag : knowledgeSearchRequest.getTags()) {
disJunction.add(Restrictions.eq("tag.elements", tag));
}
criteria.add(disJunction);
}
criteria.add(Restrictions.ne("dataType", DataType.FOLDER));
// if (userProvider.getCurrentUser().isSystemUser() || visibleToUser) {
final List<DataVisibility> visibility = new ArrayList<>();
visibility.add(DataVisibility.PUBLIC);
if (knowledgeSearchRequest.isAddCpUserDocs()) {
visibility.add(DataVisibility.ALL_USERS_OF_CUSTOMER_PORTAL_ONLY);
}
if (knowledgeSearchRequest.isIncludeCpDocs()) {
visibility.add(DataVisibility.CUSTOMER_PORTAL);
visibility.add(DataVisibility.ALL_SIGNED_IN_USERS_OF_CUSTOMER_PORTAL_ONLY);
visibility.add(DataVisibility.ALL_USERS_OF_CUSTOMER_PORTAL_ONLY);
}
criteria.add(Restrictions.in("visibility", visibility));
// }
if (knowledgeSearchRequest.isPublished()) {
final long now = System.currentTimeMillis();
criteria.add(Restrictions.or(
Restrictions.and(Restrictions.isNotNull("validFrom"), Restrictions.lt("validFrom", now)),
Restrictions.isNull("validFrom")));
criteria.add(Restrictions.or(
Restrictions.and(Restrictions.isNotNull("validTo"), Restrictions.gt("validTo", now)),
Restrictions.isNull("validTo")));
}
而且,我到目前为止构建的谓词是,
searchPredicateFactory.bool(
f -> f.should(searchPredicateFactory.phrase().field(KnowledgeData.STANDARD_FIELD_NAME_NAME).boost(3)
.field(KnowledgeData.STANDARD_FIELD_NAME_DISPLAY_NAME).boost(3)
.field("description").boost(2).field("content").matching(resultantQuery))
.should(searchPredicateFactory.wildcard().field(KnowledgeData.STANDARD_FIELD_NAME_NAME).boost(3)
.field(KnowledgeData.STANDARD_FIELD_NAME_DISPLAY_NAME).boost(3)
.field("description").boost(2).field("content").matching(resultantQuery))).toPredicate();
感谢任何线索。
This is the Hibernate Search 5 query that I am trying to convert,
我会挑剔一点:这不是 Hibernate Search 5 查询,这是 Hibernate (ORM) Criteria 查询。这些限制是针对数据库执行的,而不是针对搜索索引执行的。
根据您的问题标题,我假设您正在使用 FullTextQuery.setCriteriaQuery()
将这些限制添加到您的 Hibernate 搜索查询中。请注意 the documentation in Hibernate Search 5 states "using restriction (ie a where clause) on your Criteria query should be avoided" and the javadoc goes even further by stating "No where
restriction can be defined".
无论如何...它似乎曾经在 Hibernate Search 5 中工作,至少在某些情况下是这样。
现在,要将其迁移到 Hibernate Search 6+,有一个详细的迁移指南,a section specifically about your problem:
Hibernate Search 6 does not allow adding a Criteria object to a search query.
[...]
If your goal is to apply a filter expressed by an SQL "where" clause executed in-database, rework your query to project on the entity ID, and execute a JPA/Hibernate ORM query after the search query to filter the entities and load them.
简而言之,做这样的事情:
List<Long> ids = Search.session(entityManager).search(MyEntity.class)
.select(f -> f.id(Long.class))
.where(f -> ...)
.fetchHits(20);
criteria.add(Restrictions.in("id", ids));
List<MyEntity> hits = criteria.list();
请注意,这只是一个快速修复:就像 Hibernate Search 5 中的 setCriteria
一样,它的性能可能非常差,分页效果非常差,并且可能导致命中计数不正确。
我建议索引您在 Criteria 查询中使用的属性,并仅使用 Hibernate Search 定义您的 whole 查询,以避免 运行 查询一次针对 Elasticsearch,然后再次针对您的数据库。
我正在将 Hibernate Search 5 迁移到 Hibernate Search 6。 虽然 documentation 确实很有帮助,但我无法在 Hibernate Search 6 中找到标准查询的替代方法,也没有完全从文档中获得。
这是我要转换的 Hibernate Search 5 查询,
final Criteria criteria = entityManager.unwrap(Session.class).createCriteria(KnowledgeData.class);
criteria.add(Restrictions.eq("deleted", knowledgeSearchRequest.isDeleted()));
if (knowledgeSearchRequest.isPublished()) {
criteria.add(Restrictions.eq("published", knowledgeSearchRequest.isPublished()));
}
if (!allDesk) {
criteria.add(Restrictions.eq("deskId", deskId));
knowledgeSearchRequest.setDesk(deskId);
} else {
Disjunction orJunction = Restrictions.disjunction();
for (String desk : knowledgeSearchRequest.getDeskIds()) {
orJunction.add(Restrictions.eq("deskId", desk));
}
criteria.add(orJunction);
}
if (knowledgeSearchRequest.getLang() != null && knowledgeSearchRequest.getLang().size() > 0) {
criteria.createAlias("language", "lan");
Disjunction disJunction = Restrictions.disjunction();
for (String lang : knowledgeSearchRequest.getLang()) {
disJunction.add(Restrictions.eq("lan.elements", lang));
}
criteria.add(disJunction);
}
if (knowledgeSearchRequest.getTags() != null && knowledgeSearchRequest.getTags().size() > 0) {
criteria.createAlias("tags", "tag");
Disjunction disJunction = Restrictions.disjunction();
for (String tag : knowledgeSearchRequest.getTags()) {
disJunction.add(Restrictions.eq("tag.elements", tag));
}
criteria.add(disJunction);
}
criteria.add(Restrictions.ne("dataType", DataType.FOLDER));
// if (userProvider.getCurrentUser().isSystemUser() || visibleToUser) {
final List<DataVisibility> visibility = new ArrayList<>();
visibility.add(DataVisibility.PUBLIC);
if (knowledgeSearchRequest.isAddCpUserDocs()) {
visibility.add(DataVisibility.ALL_USERS_OF_CUSTOMER_PORTAL_ONLY);
}
if (knowledgeSearchRequest.isIncludeCpDocs()) {
visibility.add(DataVisibility.CUSTOMER_PORTAL);
visibility.add(DataVisibility.ALL_SIGNED_IN_USERS_OF_CUSTOMER_PORTAL_ONLY);
visibility.add(DataVisibility.ALL_USERS_OF_CUSTOMER_PORTAL_ONLY);
}
criteria.add(Restrictions.in("visibility", visibility));
// }
if (knowledgeSearchRequest.isPublished()) {
final long now = System.currentTimeMillis();
criteria.add(Restrictions.or(
Restrictions.and(Restrictions.isNotNull("validFrom"), Restrictions.lt("validFrom", now)),
Restrictions.isNull("validFrom")));
criteria.add(Restrictions.or(
Restrictions.and(Restrictions.isNotNull("validTo"), Restrictions.gt("validTo", now)),
Restrictions.isNull("validTo")));
}
而且,我到目前为止构建的谓词是,
searchPredicateFactory.bool(
f -> f.should(searchPredicateFactory.phrase().field(KnowledgeData.STANDARD_FIELD_NAME_NAME).boost(3)
.field(KnowledgeData.STANDARD_FIELD_NAME_DISPLAY_NAME).boost(3)
.field("description").boost(2).field("content").matching(resultantQuery))
.should(searchPredicateFactory.wildcard().field(KnowledgeData.STANDARD_FIELD_NAME_NAME).boost(3)
.field(KnowledgeData.STANDARD_FIELD_NAME_DISPLAY_NAME).boost(3)
.field("description").boost(2).field("content").matching(resultantQuery))).toPredicate();
感谢任何线索。
This is the Hibernate Search 5 query that I am trying to convert,
我会挑剔一点:这不是 Hibernate Search 5 查询,这是 Hibernate (ORM) Criteria 查询。这些限制是针对数据库执行的,而不是针对搜索索引执行的。
根据您的问题标题,我假设您正在使用 FullTextQuery.setCriteriaQuery()
将这些限制添加到您的 Hibernate 搜索查询中。请注意 the documentation in Hibernate Search 5 states "using restriction (ie a where clause) on your Criteria query should be avoided" and the javadoc goes even further by stating "No where
restriction can be defined".
无论如何...它似乎曾经在 Hibernate Search 5 中工作,至少在某些情况下是这样。
现在,要将其迁移到 Hibernate Search 6+,有一个详细的迁移指南,a section specifically about your problem:
Hibernate Search 6 does not allow adding a Criteria object to a search query.
[...]
If your goal is to apply a filter expressed by an SQL "where" clause executed in-database, rework your query to project on the entity ID, and execute a JPA/Hibernate ORM query after the search query to filter the entities and load them.
简而言之,做这样的事情:
List<Long> ids = Search.session(entityManager).search(MyEntity.class)
.select(f -> f.id(Long.class))
.where(f -> ...)
.fetchHits(20);
criteria.add(Restrictions.in("id", ids));
List<MyEntity> hits = criteria.list();
请注意,这只是一个快速修复:就像 Hibernate Search 5 中的 setCriteria
一样,它的性能可能非常差,分页效果非常差,并且可能导致命中计数不正确。
我建议索引您在 Criteria 查询中使用的属性,并仅使用 Hibernate Search 定义您的 whole 查询,以避免 运行 查询一次针对 Elasticsearch,然后再次针对您的数据库。