Hibernate Search:搜索时只查询实体ID
Hibernate Search: Query only entity IDs when searching
我正在通过 Hibernate Search 和 Lucene 实现全文搜索功能。搜索看起来像这样并且效果很好。我的问题是我们的实体 类 大多非常庞大,因此提供 100 个结果的搜索花费的时间太长,因为查询找到的实体非常耗时。
打开表单时,我用 HQL 查询加载了最后 20 个编辑的实体,这首先也花费了太长时间,所以我创建了一个只包含我需要在结果列表中显示的字段的实体和实际实体的 ID。仅当用户单击结果以查看详细信息时,才会加载实际实体。这将查询时间加快到原来时间的 1/100 甚至更少。
有没有办法以同样的方式加快Hibernate Search查询速度,所以我搜索一个实体,但只查询对象的ID而不是整个实体?
EntityManager em = EntityManagerUtil.getEntityManager();
List<T> returnList=new ArrayList<>();
FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
em.getTransaction().begin();
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(typeParameterClass).get();
TermMatchingContext onFields = qb.keyword().wildcard().onFields(getSearchFields());
BooleanJunction<BooleanJunction> bool = qb.bool();
org.apache.lucene.search.Query query = null;
String[] searchTerms = searchString.split("\s+");
for (int j = 0; j < searchTerms.length; j++) {
String currentTerm = searchTerms[j];
bool.must(onFields.matching(currentTerm).createQuery());
}
query = bool.createQuery();
javax.persistence.Query persistenceQuery = fullTextEntityManager.createFullTextQuery(query, typeParameterClass);
persistenceQuery.setMaxResults(100);
returnList = persistenceQuery.getResultList();
您可以使用 Index Projections 让您的查询 return 只选择属性。 ID是一个选项:
javax.persistence.Query persistenceQuery = fullTextEntityManager.createFullTextQuery(query, typeParameterClass);
query.setProjection(ProjectionConstants.ID, [other fields...])
persistenceQuery.setMaxResults(100);
这将包含您的查询 return 数组。数组的第一个元素将包含每个匹配项的 ID。
您也可以加载其他字段,只要它们被标记为使用
存储
@Field(store=Store.YES)
ID 始终被存储,因此如果您只想投影 ID,则无需添加此内容。
顺便说一句,如果您的加载时间如此之短,则表明您的映射有问题。我猜你加载了太多急切的关系。一般的建议是将它们中的大多数映射为惰性的,并使用一些二级缓存是合适的。
您需要 org.hibernate.search.jpa.FullTextQuery 而不是 javax.persistence.Query
org.hibernate.search.jpa.FullTextQuery persistenceQuery = fullTextEntityManager.createFullTextQuery(query, typeParameterClass);
persistenceQuery.setProjection(ProjectionConstants.ID);
persistenceQuery.setMaxResults(100);
我正在通过 Hibernate Search 和 Lucene 实现全文搜索功能。搜索看起来像这样并且效果很好。我的问题是我们的实体 类 大多非常庞大,因此提供 100 个结果的搜索花费的时间太长,因为查询找到的实体非常耗时。
打开表单时,我用 HQL 查询加载了最后 20 个编辑的实体,这首先也花费了太长时间,所以我创建了一个只包含我需要在结果列表中显示的字段的实体和实际实体的 ID。仅当用户单击结果以查看详细信息时,才会加载实际实体。这将查询时间加快到原来时间的 1/100 甚至更少。
有没有办法以同样的方式加快Hibernate Search查询速度,所以我搜索一个实体,但只查询对象的ID而不是整个实体?
EntityManager em = EntityManagerUtil.getEntityManager();
List<T> returnList=new ArrayList<>();
FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
em.getTransaction().begin();
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(typeParameterClass).get();
TermMatchingContext onFields = qb.keyword().wildcard().onFields(getSearchFields());
BooleanJunction<BooleanJunction> bool = qb.bool();
org.apache.lucene.search.Query query = null;
String[] searchTerms = searchString.split("\s+");
for (int j = 0; j < searchTerms.length; j++) {
String currentTerm = searchTerms[j];
bool.must(onFields.matching(currentTerm).createQuery());
}
query = bool.createQuery();
javax.persistence.Query persistenceQuery = fullTextEntityManager.createFullTextQuery(query, typeParameterClass);
persistenceQuery.setMaxResults(100);
returnList = persistenceQuery.getResultList();
您可以使用 Index Projections 让您的查询 return 只选择属性。 ID是一个选项:
javax.persistence.Query persistenceQuery = fullTextEntityManager.createFullTextQuery(query, typeParameterClass);
query.setProjection(ProjectionConstants.ID, [other fields...])
persistenceQuery.setMaxResults(100);
这将包含您的查询 return 数组。数组的第一个元素将包含每个匹配项的 ID。
您也可以加载其他字段,只要它们被标记为使用
存储@Field(store=Store.YES)
ID 始终被存储,因此如果您只想投影 ID,则无需添加此内容。
顺便说一句,如果您的加载时间如此之短,则表明您的映射有问题。我猜你加载了太多急切的关系。一般的建议是将它们中的大多数映射为惰性的,并使用一些二级缓存是合适的。
您需要 org.hibernate.search.jpa.FullTextQuery 而不是 javax.persistence.Query
org.hibernate.search.jpa.FullTextQuery persistenceQuery = fullTextEntityManager.createFullTextQuery(query, typeParameterClass);
persistenceQuery.setProjection(ProjectionConstants.ID);
persistenceQuery.setMaxResults(100);