【问题标题】:Pagination with mongoTemplate使用 mongoTemplate 进行分页
【发布时间】:2015-05-15 20:02:52
【问题描述】:

我有一个带有 Pageable 的查询:

Query query = new Query().with(new PageRequests(page, size))

如何使用 MongoTemplate 执行它?我没有看到返回 Page<T> 的单一方法。

【问题讨论】:

    标签: java spring-data spring-data-mongodb


    【解决方案1】:

    MongoTemplate 没有返回Page 的方法。 find() 方法返回一个普通的 List

    with(new PageRequests(page, size) 在内部使用 MongoDB 查询来调整 skiplimit(我认为是由计数查询进行的)

    Page 可以与 MongoDB repositories 结合使用,MongoDB repositories 是 Spring 数据存储库的一个特例。

    因此,您必须使用MongoRepositoryPage findAll(Pageable pageable) 来获得分页结果(实际上继承自PagingAndSortingRepository)。

    【讨论】:

      【解决方案2】:

      MongoTemplate 确实没有带有 Pageables 的 findXXX

      但您可以使用 Spring Repository PageableExecutionUtils

      在您的示例中,它看起来像这样:

      Pageable pageable = new PageRequests(page, size);
      Query query = new Query().with(pageable);
      List<XXX> list = mongoTemplate.find(query, XXX.class);
      return PageableExecutionUtils.getPage(
                             list, 
                             pageable, 
                             () -> mongoTemplate.count(Query.of(query).limit(-1).skip(-1), XXX.class));
      

      就像在原始 Spring Data Repository 中一样,PageableExecutionUtils 将执行计数请求并将其包装成一个漂亮的 Page 供您使用。

      Here你可以看到spring也在做同样的事情。

      【讨论】:

      • PageableExecutionUtils 类在哪里?
      • 这不会导致查询在 MongoDB 端运行两次并增加网络开销吗?
      • @checklist 是的,查询运行了两次。由于查询应该针对索引集合运行,因此应该没什么大不了的。好的,如果您是 facebook 或 twitter,这可能是一件大事;D。我没有其他解决方案
      • 这很有趣,但是如果您的查询返回数十万或数百万行不带分页,当它试图将所有这些文档读入内存时,这将削弱您的服务器。使用聚合框架要好得多
      【解决方案3】:

      基于 d0x 的回答并查看 spring code。我正在使用这种变体,它可以消除 spring-boot-starter-data-mongodb 依赖项,而无需添加 spring data commons。

      @Autowired
      private MongoOperations mongoOperations;
      
      @Override
      public Page<YourObjectType> searchCustom(Pageable pageable) {
          Query query = new Query().with(pageable);
          // Build your query here
      
          List<YourObjectType> list = mongoOperations.find(query, YourObjectType.class);
          long count = mongoOperations.count(query, YourObjectType.class);
          Page<YourObjectType> resultPage = new PageImpl<YourObjectType>(list , pageable, count);
          return resultPage;
      }
      

      【讨论】:

      • 仅供参考:为了获得正确的计数值 - 查询应该重置:跳过,限制值。计数调用应为:mongoOperations.count(query.skip(-1).limit(-1), YourObjectType.class)。否则它将返回不正确的查询计数。
      【解决方案4】:
      return type Mono<Page<Myobject>>...
      
      return this.myobjectRepository.count()
              .flatMap(ptiCount -> {
                return this.myobjectRepository.findAll(pageable.getSort())
                  .buffer(pageable.getPageSize(),(pageable.getPageNumber() + 1))
                  .elementAt(pageable.getPageNumber(), new ArrayList<>())
                  .map(ptis -> new PageImpl<Myobject>(ptis, pageable, ptiCount));
              });
      

      【讨论】:

        【解决方案5】:

        spring mongo模板默认没有分页查找的方法。它搜索并返回整个记录列表。我试过这个,它工作:

        Pageable pageable = new PageRequests(0, 10);                              
        Query query = new Query(criteria); 
        query.with(pageable);   
        List<User> lusers = mt.find(query, User.class);   
        Page<User> pu = new PageImpl<>(lusers, pageable, mongoTemplate.count(newQuery(criteria), User.class));
        

        【讨论】:

          【解决方案6】:

          此处提供的解决方案均不适用于我自己的情况。 我尝试在下面的中型帖子中使用此解决方案,它从未返回分页结果,但返回所有结果,这不是我所期望的

          return PageableExecutionUtils.getPage(
                  mongoTemplate.find(query, ClassName.class),
                  pageable,
                  () -> mongoTemplate.count(query.skip(0).limit(0), ClassName.class)
          );
          

          所以我找到了一个更好的方法来解决这个问题,它在我的情况下很有效:

          return PageableExecutionUtils.getPage(
                      mongoTemplate.find(query.with(pageable), ClassName.class),
                      pageable,
                      () -> mongoTemplate.count(query, ClassName.class));
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-10-13
            • 1970-01-01
            • 2014-09-01
            • 2017-08-16
            • 2016-11-20
            • 2013-04-14
            • 2010-09-19
            • 2018-08-08
            相关资源
            最近更新 更多