You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoTemplate对LocalDateTime字段排序失效及分页功能异常问题排查

核心错误排查

你当前的代码存在两个优先级最高的基础错误,是所有异常的根源:

  1. 构造的Criteria条件列表没有添加到Query对象中,所有查询实际执行的是全表无条件查询
  2. 分页总条数计算逻辑错误,直接将当前页的结果条数作为全量符合条件的总记录数,导致Page元数据完全错误

各问题解决方案

1. 排序失效、分页重复问题

  • 先修正字段拼写错误:你实体类中声明的LocaleDateTime属于拼写错误,正确的JDK时间类是java.time.LocalDateTime,字段类型拼写错误会导致Mongo无法识别该字段,排序自然失效
  • 补充稳定排序规则:Mongo单字段排序为不稳定排序,若多条记录createdAt值相同,每次查询返回顺序可能不一致,导致分页重复。需要追加唯一字段作为第二排序条件:
    Sort sort = Sort.by(Sort.Direction.DESC, "createdAt")
                .and(Sort.by(Sort.Direction.DESC, "id"));
    Pageable pageable = PageRequest.of(skip == 0 ? skip : skip/first, first, sort);
    
  • 将Criteria条件添加到Query对象中:
    if (!criteria.isEmpty()) {
        query.addCriteria(new Criteria().andOperator(criteria.toArray(new Criteria[0])));
    }
    

2. 分页元数据错误问题

你之前使用() -> (long)users.size()作为总条数查询逻辑,返回的始终是当前页的结果条数,需要改为调用MongoTemplate的count方法查询全量符合条件的记录数:

return PageableExecutionUtils.getPage(users, page,
    () -> mongoTemplate.count(Query.of(query).limit(-1).skip(-1), UserDocument.class));

这里复制原Query并清空limit、skip参数,是为了复用查询条件,保证count结果和分页查询条件完全一致。

3. 直接返回Slice类型

可以直接构造Slice返回,无需经过Page转换,Slice不需要查询全量总条数,性能更高,实现逻辑如下:

public Slice<UserDocument> findUsersByPropertiesSlice(String name, String email, Pageable page) {
    final Query query = new Query().with(page);
    final List<Criteria> criteria = new ArrayList<>();
    // 省略Criteria构造逻辑,同上
    if (!criteria.isEmpty()) {
        query.addCriteria(new Criteria().andOperator(criteria.toArray(new Criteria[0])));
    }
    // 多查1条记录判断是否存在下一页
    query.limit(page.getPageSize() + 1);
    List<UserDocument> users = mongoTemplate.find(query, UserDocument.class);
    boolean hasNext = users.size() > page.getPageSize();
    if (hasNext) {
        users = users.subList(0, page.getPageSize());
    }
    return new SliceImpl<>(users, page, hasNext);
}

修正后完整Repository实现

@Repository
public class UserCustom implements UserRepository {

    @Autowired
    MongoTemplate mongoTemplate;

    public Page<UserDocument> findUsersByProperties(String name, String email, Pageable page) {
        final Query query = new Query().with(page);
        final List<Criteria> criteria = new ArrayList<>();

        if (name != null && !name.isEmpty()) {
            criteria.add(Criteria.where("name").is(name));
        }
        if (email != null && !email.isEmpty()) {
            criteria.add(Criteria.where("email").is(email));
        }
        
        // 补充添加Criteria到Query的逻辑
        if (!criteria.isEmpty()) {
            query.addCriteria(new Criteria().andOperator(criteria.toArray(new Criteria[0])));
        }

        List<UserDocument> users = mongoTemplate.find(query, UserDocument.class);

        return PageableExecutionUtils.getPage(users, page,
                // 修正总条数查询逻辑
                () -> mongoTemplate.count(Query.of(query).limit(-1).skip(-1), UserDocument.class));
    }
}

内容的提问来源于stack exchange,提问作者Barbi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 12:45:11