11

我试图理解 spring 5 的反应部分。我创建了简单的休息端点,用于使用 springweb-flux和 spring 数据反应 (mongo) 查找所有实体,但看不到如何实现分页。

这是我在 Kotlin 中的简单示例:

@GetMapping("/posts/")
fun getAllPosts() = postRepository.findAll()

这是否意味着反应式端点不需要分页?是否有某种方法可以使用此堆栈从服务器端实现分页?

4

2 回答 2

14

Spring Data 中的响应式支持不提供Page返回类型的方法。尽管如此,该Pageable参数在传递给驱动程序的方法签名中得到支持,limit因此也支持offset存储本身,返回一个Flux<T>发出请求范围的 a。

Flux<Person> findByFirstname(String firstname, Pageable pageable);

有关更多信息,请查看当前的 2.0.RC2 参考文档Spring Data Examples

于 2017-08-29T06:32:00.367 回答
6

Flux提供skiptake方法来获得分页支持,您还可以使用filterandsort对结果进行过滤和排序。 下面的过滤和排序不是一个很好的例子,但使用skipPageable作为第二个参数没有什么不同。

以下代码对我有用。

@GetMapping("")
public Flux<Post> all(
//@RequestParam(value = "q", required = false) String q,
                      @RequestParam(value = "page", defaultValue = "0") long page,
                      @RequestParam(value = "size", defaultValue = "10") long size) {
    return this.postRepository.findAll()
        //.filter(p -> Optional.ofNullable(q).map(key -> p.getTitle().contains(key) || p.getContent().contains(key)).orElse(true))//(replace this with query parameters)
        .sort(comparing(Post::getCreatedDate).reversed())
        .skip(page * size).take(size);
}

更新:底层驱动程序应该负责以反应流的方式处理结果。

正如您在 Christoph 的回答中看到的那样,如果使用findByXXX方法,Spring Data Mongo Reactive 提供了一个变体来接受pageable参数,但是findAll(反应式版本)不包含这样的变体,如果您必须skip在以后的操作中执行真的需要分页功能。当切换到Flux而不是 List 时,将 Flux 中的数据想象为河流中的活水或管道中的石油,或者 twitter.com 中的推文。

Pageale在以下情况下,我尝试使用而不是比较查询。

this.postRepository.findByTitleContains("title")
                .skip(0)
                .limitRequest(10)
                .sort((o1, o2) -> o1.getTitle().compareTo(o2.getTitle()))


this.postRepository.findByTitleContains("title", PageRequest.of(0, 10, Sort.by(Sort.Direction.ASC, "title")))

启用日志记录logging.level.org.springframework.data.mongodb.core.ReactiveMongoTemplate=DEBUG并发现它们为查询打印相同的日志。

 find using query: { "title" : { "$regularExpression" : { "pattern" : ".*title.*", "options" : ""}}} fields: Document{{title=1}} for class: class com.example.demo.Post in collection: post

//other logging...

 find using query: { "title" : { "$regularExpression" : { "pattern" : ".*title.*", "options" : ""}}} fields: Document{{title=1}} for class: class com.example.demo.Post in collection: post

请记住,所有这些操作都应该委托给底层驱动程序(如果它已经实现了反应流规范)并在数据库端执行,而不是在应用程序端的内存中。

检查示例代码

我上面提供的早期示例代码可能不是一个很好的操作示例filtersortMongoDB 本身regularexpression为它提供了很好的操作)。但是反应变体中的分页与反应流规范中的概念并不匹配。在采用 Spring 反应式堆栈时,大多数时候,我们只是将工作转移到新的 API 集合中。在我看来,实时更新和弹性响应场景可以更好地匹配Reactive,例如。将它与 SSE、Websocket、RSocket、application/stream+json(新的 Spring 文档中缺少)协议等一起使用

于 2018-01-03T13:35:22.887 回答