有没有办法在弹簧网络通量和弹簧数据反应中实现分页



我试图理解春季 5 的反应部分。我已经创建了简单的 rest 端点,用于使用 springweb-flux和 spring 数据反应式 (mongo) 查找所有实体,但看不到任何实现分页的方法。

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

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

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

Spring Data 中的响应式支持不提供Page返回类型的方法。尽管如此,Pageable参数在方法签名中仍受支持,该方法签名将limitoffset传递给驱动程序,从而传递存储本身,返回发出请求范围的Flux<T>

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

有关更多信息,请查看 2.0.RC2 的当前参考文档和 Spring 数据示例。

Flux提供了skiptake方法来获取分页支持,

您还可以使用filtersort对结果进行筛选和排序。下面的过滤器和排序不是一个很好的示例,但使用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而不是列表时,将 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

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

检查示例代码。

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

这效率不高,但在我寻找另一种解决方案时对我有用

服务

public Page<Level> getPage(int page, int size, Sort.Direction direction, String properties) {
var pageRequest = PageRequest.of(page, size, direction, properties);
var count = levelRepository.count().block();
var levels = levelRepository.findAllLevelsPaged(pageRequest).collectList().block();
return new PageImpl<>(Objects.requireNonNull(levels), pageRequest, Objects.requireNonNull(count));
}

回购

@Repository
public interface LevelRepository extends ReactiveMongoRepository<Level, String> {
@Query("{ id: { $exists: true }}")
Flux<Level> findAllLevelsPaged(final Pageable page);
}

引用示例

最新更新