我正在通过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();
答案 0 :(得分:1)
您可以使用Index Projections让查询仅返回选定的属性。 ID是一个选项:
javax.persistence.Query persistenceQuery = fullTextEntityManager.createFullTextQuery(query, typeParameterClass);
query.setProjection(ProjectionConstants.ID, [other fields...])
persistenceQuery.setMaxResults(100);
这将使您的查询返回数组。数组的第一个元素将包含每个匹配的ID。
您也可以加载其他字段,只要它们已使用
标记为已存储@Field(store=Store.YES)
始终存储ID,因此如果您只想投影ID,则无需添加此ID。
顺便说一句,如果您的加载时间很短,那么您的映射会出现问题。我猜你有太多急切的关系被加载。一般建议是将大部分映射为懒惰,并使用一些二级缓存是合适的。
答案 1 :(得分:0)
您需要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);