写在前面
最近在排查生产问题的时候发现,基于spring-data-es(版本:spring-data-elasticsearch-3.0.8.RELEASE.jar)的ElasticsearchRepository的查询有bug,如下方法:
1 2 3 4
| public interface IiapImplTemplateDeviceRepository extends ElasticsearchRepository<IiapTemplateDeviceDoc, String> { List<IiapTemplateDeviceDoc> findByXXId(String id);
}
|
这个方法原本是需要返回全量数据,但是它最多只会返回了10条数据,跟踪源码最终发现了此问题。
bug定位
首先根据之前的文章spring-data-es的源码浅析 分析,我们直接去该组件的RepositoryQuery的实现类去看问题ElasticsearchPartQuery。
拦截后最终执行的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
public Object execute(Object[] parameters) { ParametersParameterAccessor accessor = new ParametersParameterAccessor(this.queryMethod.getParameters(), parameters); CriteriaQuery query = this.createQuery(accessor); if (this.tree.isDelete()) { Object result = this.countOrGetDocumentsForDelete(query, accessor); this.elasticsearchOperations.delete(query, this.queryMethod.getEntityInformation().getJavaType()); return result; } else if (this.queryMethod.isPageQuery()) { query.setPageable(accessor.getPageable()); return this.elasticsearchOperations.queryForPage(query, this.queryMethod.getEntityInformation().getJavaType()); } else if (this.queryMethod.isStreamQuery()) { Class<?> entityType = this.queryMethod.getEntityInformation().getJavaType(); if (query.getPageable().isUnpaged()) { int itemCount = (int)this.elasticsearchOperations.count(query, this.queryMethod.getEntityInformation().getJavaType()); query.setPageable(PageRequest.of(0, Math.max(1, itemCount))); }
return StreamUtils.createStreamFromIterator(this.elasticsearchOperations.stream(query, entityType)); } else if (this.queryMethod.isCollectionQuery()) { if (accessor.getPageable() == null) { int itemCount = (int)this.elasticsearchOperations.count(query, this.queryMethod.getEntityInformation().getJavaType()); query.setPageable(PageRequest.of(0, Math.max(1, itemCount))); } else { query.setPageable(accessor.getPageable()); }
return this.elasticsearchOperations.queryForList(query, this.queryMethod.getEntityInformation().getJavaType()); } else { return this.tree.isCountProjection() ? this.elasticsearchOperations.count(query, this.queryMethod.getEntityInformation().getJavaType()) : this.elasticsearchOperations.queryForObject(query, this.queryMethod.getEntityInformation().getJavaType()); } }
|
看到这里又判断了一遍是否分页: accessor.getPageable() == null
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public Pageable getPageable() { if (!this.parameters.hasPageableParameter()) { return Pageable.unpaged(); } else { Pageable pageable = (Pageable)this.values.get(this.parameters.getPageableIndex()); return pageable == null ? Pageable.unpaged() : pageable; } }
static Pageable unpaged() { return Unpaged.INSTANCE; }
|
可以看到这个判断: accessor.getPageable() == null 永远不会成立!
所以就算我们前面定义了全量查询,这里也会设置为分页查询:query.setPageable(accessor.getPageable());
解决方案
可以看到spring-data本身没问题,是spring-data-es的组件代码出错了,我们可否升级其中一个呢?
看到spring-data-es的pom里已经写明了spring-data的版本号,
如下:
所以我们还是要升级spring-data-es
1、升级版本:在github上也找到了这个问题的修复描述,可以看到修复这个bug影响的版本为:3.1.5.RELEASE,我们可以在github上对下3.1.4和3.1.5的该处不同即可发现:
https://github.com/spring-projects/spring-data-elasticsearch/blob/3.1.5.RELEASE/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchPartQuery.java
修改记录明细为:https://github.com/spring-projects/spring-data-elasticsearch/commit/519a2a11a4eb3648ea330854bf30f0d461836e7f
2、如果怕升级版本麻烦。需要自己封装queryBuilder然后调用template的search方法即可全量查询