使用SpringData mongodb 分页聚合查询事记

在使用springdata 构建mongodb聚合分页查询时,由于擅自创建PageImpl而引发的分页血案。。

 

现象:后台得到的总记录数不正常,数据库查询19条,接口查询返回29条

事发现场:

 Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.sort(sort), //排序
                Aggregation.lookup("cps_config", "configId", "id", "configModel"),//关联表
                Aggregation.match(criteria),//查询条件
                Aggregation.skip(skip), //跳过文档数量
                Aggregation.limit(pageSize)//每页显示数量  
        );
 AggregationResults queryResult = mongoTemplate
                .aggregate(aggregation, "cps_config", CpsConfigDetail.class);

  AggregationResults countResult = mongoTemplate
                .aggregate(countAggregation, "cps_config", CpsConfigDetail.class);

        Page pager;
        if(!CollectionUtils.isEmpty(queryResult.getMappedResults())){
           //在这里手动构建 spring data pageImpl对象
            pager = new PageImpl<> 
           (queryResult.getMappedResults(),pageBale,countResult.getMappedResults().size());
          。。。。。           
        }

 勘查过程:

       接口返回的总记录数与数据库不一致,于是debug PageImpl 构造方法,发现 构造方法中 计算总记录数采用了Pageable对象的方法

       

	public PageImpl(List content, Pageable pageable, long total) {

		super(content, pageable);
         // 如果pageable的offset加上 pageSize 大于数据库总记录数,则total= pageable.offset + 
         // content.size(),否则直接返回total 
		this.total = pageable.toOptional().filter(it -> !content.isEmpty())
				.filter(it -> it.getOffset() + it.getPageSize() > total)
				.map(it -> it.getOffset() + content.size())
				.orElse(total);
	}

  于是追查源码找到getOffset实现 ----》

	public long getOffset() {
		return page * size;
	}

 最终发现,是由于前段传递page参数为1,而mongodb 分页从0开始,offset的计算应该为 page -1 * size 才对。

最终统一初始化Pageable,解决问题!

 总结:1.spring data 分页查询的pageable对象一般由 spring data 接口实现内部调用

            2.在复杂查询时并未构建pageable对象作为查询参数,封装分页结果时使用了 springdata 的 Page,要注意 offset 的计算是否正确。

            3.你能想象玩意我弄了一下午???吐血

你可能感兴趣的:(不定期关键点记录,java,spring)