通过动态查询在ReactiveMongoRepository上实现分页和排序。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过动态查询在ReactiveMongoRepository上实现分页和排序。相关的知识,希望对你有一定的参考价值。

我知道分页有点违背反应式原则,但由于需求,我必须让它以某种方式工作。我正在使用Spring Data 2.1.6,但我无法升级,所以 ReactiveQuerydslSpecification 的动态查询是不可能的。我想我可以用 ReactiveMongoTemplate 所以我想出了这个办法。

public interface IPersonRepository extends ReactiveMongoRepository<Person, String>, IPersonFilterRepository {
    Flux<Person> findAllByCarId(String carId);
}

public interface IPersonFilterRepository {
    Flux<Person> findAllByCarIdAndCreatedDateBetween(String carId, PersonStatus status,
                                                             OffsetDateTime from, OffsetDateTime to,
                                                             Pageable pageable);
}

@Repository
public class PersonFilterRepository implements IPersonFilterRepository {

    @Autowired
    private ReactiveMongoTemplate reactiveMongoTemplate;

    @Override
    public Flux<Person> findAllByCarIdAndCreatedDateBetween(String carId, PersonStatus status,
                                                                   OffsetDateTime from, OffsetDateTime to,
                                                                   Pageable pageable) {
        Query query = new Query(Criteria.where("carId").is(carId));

        if (status != null) {
            query.addCriteria(Criteria.where("status").is(status));
        }

        OffsetDateTime maxLimit = OffsetDateTime.now(ZoneOffset.UTC).minusMonths(3).withDayOfMonth(1); // beginning of month
        if (from == null || from.isBefore(maxLimit)) {
            from = maxLimit;
        }

        query.addCriteria(Criteria.where("createdDateTime").gte(from));

        if (to == null) {
            to = OffsetDateTime.now(ZoneOffset.UTC);
        }

        query.addCriteria(Criteria.where("createdDateTime").lte(to));

        // problem is trying to come up with a decent page-ish behavior compatible with Flux
        /*return reactiveMongoTemplate.count(query, Person.class)
                .flatMap(count -> reactiveMongoTemplate.find(query, Person.class)
                        .flatMap(p -> new PageImpl<Person>(p, pageable, count))
                        .collectList()
                        .map());*/

        /* return reactiveMongoTemplate.find(query, Person.class)
                .buffer(pageable.getPageSize(), pageable.getPageNumber() + 1)
                //.elementAt(pageable.getPageNumber(), new ArrayList<>())
                .thenMany(Flux::from);*/
    }

我试图返回一个 Page<Person> (假设这一次这个单一的方法可以是非反应式的,就这一次),它在运行测试时出现了以下错误(Spring上下文不能成功加载,原因是。InvalidDataAccessApiUsageException: 'IDocumentFilterRepository.findAllByCustomerIdAndCreatedDateBetween' must not use sliced or paged execution. Please use Flux.buffer(size, skip). 我也尝试过返回 Mono<Page<Person>> 进而失败 "Method has to use a either multi-item reactive wrapper return type or a wrapped Page/Slice type. Offending method: 'IDocumentFilterRepository.findAllByCustomerIdAndCreatedDateBetween'所以我想我唯一的选择就是返回一个 Flux根据 例133,片段3

答案

原来你可以在查询对象中添加以下内容就可以了。

query.with(pageable);

reactiveMongoTemplate.find(query, Person.class);

返回 Flux<T> 它将工作的盒子。

以上是关于通过动态查询在ReactiveMongoRepository上实现分页和排序。的主要内容,如果未能解决你的问题,请参考以下文章

通过动态创建 linq 查询,在 c# 中为 Sql Equivalent “column is null”创建 Linq 表达式

sqlalchemy 动态查询条件怎么写

22 Specifications动态查询

[Hibernate] 通过 properties 类和 hql 语句进行动态查询

Specifications动态查询

Specifications动态查询