java 使用mongoTemplate分页

iqih9akk  于 2023-03-16  发布在  Java
关注(0)|答案(7)|浏览(189)

我有一个可分页的查询:

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

我怎么用MongoTemplate执行它呢?我没有看到一个方法返回Page<T>

iyr7buue

iyr7buue1#

的确,MongoTemplate没有带可分页功能的findXXX
但是您可以使用Spring存储库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将执行一个计数请求,并将其 Package 成一个漂亮的Page
在这里你可以看到Spring也在做同样的事情。

ttisahbt

ttisahbt2#

基于d 0x的回答,并查看spring代码,我使用了这个变体,它消除了spring-boot-starter-data-mongodb依赖,而不需要添加spring数据公共项。

@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;
}
6rvt4ljy

6rvt4ljy3#

MongoTemplate没有返回Page的方法。find()方法返回普通的List
with(new PageRequests(page, size)在内部用于通过MongoDB查询(我认为是通过计数查询进行)调整skiplimit
Page可以与MongoDB存储库结合使用,MongoDB存储库是Spring Data 存储库的一种特殊情况。
因此,必须使用MongoRepositoryPage findAll(Pageable pageable)来对结果进行分页(实际上是从PagingAndSortingRepository继承而来的)。

gwo2fgha

gwo2fgha4#

默认情况下,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));
qnzebej0

qnzebej05#

这里提供的解决方案都不适用于我自己的情况。我试着使用下面的解决方案从一个中等职位,它从来没有返回分页的结果,但返回所有的结果,这不是我所期望的

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));
cclgggtu

cclgggtu6#

到目前为止,所有答案都执行查询两次。这通常不是您想要的。下面是一个使用聚合只运行一次的解决方案。

public class Result<T> {
    int totalCount;
    List<T> objects;
}

public <T, R extends Result<T>> R executePaged(Class<T> inputType,
                                               Criteria criteria,
                                               Pageable pageable,
                                               Class<R> resultType) {
    var match = Aggregation.match(criteria);
    var facets = Aggregation
            .facet(
                    Aggregation.sort(pageable.getSort()),
                    Aggregation.skip(pageable.getOffset()),
                    Aggregation.limit(pageable.getPageSize())
            ).as("objects")
            .and(
                    Aggregation.count().as("count")
            ).as("countFacet");
    var project = Aggregation
            .project("objects")
            .and("$countFacet.count").arrayElementAt(0).as("totalCount");

    var aggregation = Aggregation.newAggregation(match, facets, project);
    return mongoTemplate.aggregate(aggregation, inputType, resultType)
            .getUniqueMappedResult();
}

注:

  • 扩展并参数化Result<T>以作为resultType传递,否则反序列化器不知道使用哪个类
  • 必须使用Sort创建pageable
  • 如果需要,您仍然可以在以后创建PageImpl

示例:

class Person {
    String name;
    Date birthdate;
}

class PersonResult extends Result<Person>{}

PersonResult result = executePaged(Person.class,
      Criteria.where("name").is("John"),
      PageRequest.of(3, 50).withSort(Sort.by("birthdate")),
      PersonResult.class);

System.out.println("Total #Johns: " + result.totalCount);
System.out.println("Johns on this page: " + result.objects);
kwvwclae

kwvwclae7#

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));
        });

相关问题