2017-03-09 78 views
0

我正在通过Hibernate Search和Lucene实现全文搜索功能。搜索看起来像这样,工作得很好。我的问题是我们的实体类大部分非常庞大,因此搜索提供100个结果需要很长时间,因为查询找到的实体非常耗时。Hibernate搜索:搜索时只查询实体ID

当打开表单时,我用HQL查询加载了最后20个编辑过的实体,而这个查询首先花费的时间太长,所以我创建了一个实体,只包含我需要在结果列表中显示的字段以及ID的实体。只有当用户点击一个结果才能看到它时,实际的实体才会被加载。这加快了查询时间到原始时间的1/100和更少。

有没有办法加速Hibernate搜索查询以相同的方式,所以我搜索一个实体,但只查询对象的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(); 

回答

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。

顺便说一句,如果你的加载时间很差,那么你的映射就有问题了。我猜想你有太多渴望加载的关系。一般的建议是将其大部分映射为懒惰,并且还使用一些二级缓存是合适的。