5

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

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

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

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

我已经能够看到的功能。

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

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

4

3 回答 3

4

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

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

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

    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);
于 2013-06-23T18:58:20.543 回答
2

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

interface PersonRepository extends Repository<Person, Long> {

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

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

于 2013-06-24T07:14:21.757 回答
0

如果您无法在@Query-Annotation 中表达您的查询,您可以使用 Spring RepositoryPageableExecutionUtils进行自定义查询。

例如像这样:

@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.of(query).limit(-1).skip(-1), XXX.class));
}

就像在原始的 Spring Data Repository 中一样,PageableExecutionUtils它将执行一个单独的count请求并将其包装成一个 nice Pagefor you。

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

于 2017-09-24T23:31:46.033 回答