我试图理解 spring 5 的反应部分。我创建了简单的休息端点,用于使用 springweb-flux
和 spring 数据反应 (mongo) 查找所有实体,但看不到如何实现分页。
这是我在 Kotlin 中的简单示例:
@GetMapping("/posts/")
fun getAllPosts() = postRepository.findAll()
这是否意味着反应式端点不需要分页?是否有某种方法可以使用此堆栈从服务器端实现分页?
我试图理解 spring 5 的反应部分。我创建了简单的休息端点,用于使用 springweb-flux
和 spring 数据反应 (mongo) 查找所有实体,但看不到如何实现分页。
这是我在 Kotlin 中的简单示例:
@GetMapping("/posts/")
fun getAllPosts() = postRepository.findAll()
这是否意味着反应式端点不需要分页?是否有某种方法可以使用此堆栈从服务器端实现分页?
Spring Data 中的响应式支持不提供Page
返回类型的方法。尽管如此,该Pageable
参数在传递给驱动程序的方法签名中得到支持,limit
因此也支持offset
存储本身,返回一个Flux<T>
发出请求范围的 a。
Flux<Person> findByFirstname(String firstname, Pageable pageable);
有关更多信息,请查看当前的 2.0.RC2 参考文档和Spring Data Examples。
Flux提供skip
和take
方法来获得分页支持,您还可以使用 下面的过滤和排序不是一个很好的例子,但使用filter
andsort
对结果进行过滤和排序。skip
和Pageable
作为第二个参数没有什么不同。
以下代码对我有用。
@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
请记住,所有这些操作都应该委托给底层驱动程序(如果它已经实现了反应流规范)并在数据库端执行,而不是在应用程序端的内存中。
检查示例代码。
我上面提供的早期示例代码可能不是一个很好的操作示例filter
(sort
MongoDB 本身regularexpression
为它提供了很好的操作)。但是反应变体中的分页与反应流规范中的概念并不匹配。在采用 Spring 反应式堆栈时,大多数时候,我们只是将工作转移到新的 API 集合中。在我看来,实时更新和弹性响应场景可以更好地匹配Reactive,例如。将它与 SSE、Websocket、RSocket、application/stream+json
(新的 Spring 文档中缺少)协议等一起使用