写在前面
最近在排查生产问题的时候发现,基于spring-data-es(版本:spring-data-elasticsearch-3.0.8.RELEASE.jar)的ElasticsearchRepository的查询有bug,如下方法:
| 12
 3
 4
 
 | public interface IiapImplTemplateDeviceRepository extends ElasticsearchRepository<IiapTemplateDeviceDoc, String> {List<IiapTemplateDeviceDoc> findByXXId(String id);
 
 }
 
 | 
这个方法原本是需要返回全量数据,但是它最多只会返回了10条数据,跟踪源码最终发现了此问题。
bug定位
首先根据之前的文章spring-data-es的源码浅析 分析,我们直接去该组件的RepositoryQuery的实现类去看问题ElasticsearchPartQuery。
拦截后最终执行的代码如下:
| 12
 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
| 12
 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方法即可全量查询