是否可以使用SpringData MongoDB存储库执行任意查询,并使用分页?

时间:2013-06-22 22:31:13

标签: mongodb pagination spring-data

我们有一个用例,用户可以传递集合的任意搜索条件,并希望输出分页。使用Spring Data存储库,如果我们提前知道他们可以通过简单扩展的MongoRepository搜索哪些属性,并声明:

,这非常简单。

Page<Thing> findByFooAndBarAndBaz(Type foo, Type bar, Type baz, Pageable page)

但是,如果我们自己使用fluent接口生成查询或构造mongo字符串并将其包装在BasicQuery类中,我找不到将其转换为存储库实例的方法。没有:

Page<Thing> findByQuery(Query q, Pageable page)

我能够看到的功能。

我也无法看到如何使用Page抽象来挂钩MongoTemplate查询功能。

我希望我不必滚动自己的分页(计算跳过和限制参数,我猜这并不难)并直接调用模板,但我想我可以,如果那&# 39;是最好的选择。

3 个答案:

答案 0 :(得分:4)

我不认为这可以按照我希望的方式完成,但我想出了一个解决方法。作为背景,我们将所有方法都放在DAO中进行数据访问,一些方法委托给存储库,一些委托给模板。

  • 写了一个DAO方法,该方法接受我们的任意过滤字符串(我有一个实用程序将其转换为标准的mongo JSON查询语法。
  • 在BasicQuery中包装它以获得“countQuery”。
  • 使用countQuery获取使用MongoTemplate#count(Query, Class)
  • 的记录总数
  • 附加我的分页条件,使用Query#with(Pageable)
  • 创建“pageQuery”
  • 使用MongoTemplate#find(Query, Pageable)
  • 运行pageQuery
  • 从中获取List<T>结果,用于查询的Pageable和从countQuery运行返回的count,并构造一个新的PageImp以返回致来电者。

基本上,这个(DocDbDomain是用于测试文档db内容的测试域类):

    Query countQuery = new BasicQuery(toMongoQueryString(filterString));
    Query pageQuery = countQuery.with(pageRequest);
    long total = template.count(countQuery, DocDbDomain.class);

    List<DocDbDomain> content = template.find(pageQuery, DocDbDomain.class);

    return new PageImpl<DocDbDomain>(content, pageRequest, total);

答案 1 :(得分:2)

您可以使用@Query注释通过存储库方法执行任意查询:

interface PersonRepository extends Repository<Person, Long> {

  @Query("{ 'firstname' : ?0 }")
  Page<Person> findByCustomQuery(String firstname, Pageable pageable);
}

一般来说,@Query可以包含您可以通过shell执行的任何JSON查询,但使用?0种语法来替换参数值。您可以在reference documentation中找到有关基本机制的更多信息。

答案 2 :(得分:0)

如果您无法在@Query - 注释中表达您的查询,则可以使用Spring存储库PageableExecutionUtils进行自定义查询。

例如:

@Override
public Page<XXX> findSophisticatedXXX(/* params, ... */ @NotNull Pageable pageable) {

    Query query = query(
            where("...")
            // ... sophisticated query ...
    ).with(pageable);

    List<XXX> list = mongoOperations.find(query, XXX.class);
    return PageableExecutionUtils.getPage(list, pageable,
              () -> mongoOperations.count(query, XXX.class));
}

与最初的Spring Data Repository一样,PageableExecutionUtils将执行一个单独的count请求,并将其包装成一个不错的Page

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