如何从Spring Reactive Programming中的两个Flux(Object)中获取Flux或List?

ace*_*ace 8 reactor spring-boot project-reactor spring-webflux

我是Spring Reactive Project的新手.在我的Spring Boot Controller类中

Flux<House> ( list of all houses in the database) and Flux<Image>

来自服务层,其中给定的Flux<Image>是给定房屋的图像,例如房屋列表,每个房屋都有自己的图像集合.这意味着我必须迭代Flux<House>才能获得home的id,然后在Image上调用findByHouseId来获取Flux<Image>,每个Image都有houseId属性.每个图像对象具有字符串值"是"或"否"的属性"覆盖",并且具有诸如"卧室"的各种字符串值的另一属性"类型".我想收集一个

list of Flux<Image> like List<Flux<Image>> or List<List<Image>>
Run Code Online (Sandbox Code Playgroud)

仅包含"cover"=="yes"或"type"=="bedroom"的图像.怎么做到这一点?编程代码将回答这个问题.

下面尝试作为解决方案的一部分,但即使这个部分解决方案也不起作用:

List<Flux<Image>> imagesList= new ArrayList<Flux<Image>>();
        Flux<House> houses = houseService.findAllHouses();

        houses.map(house ->  house.getId()).subscribe(id -> imageService.findByHouseId(id))
        .map(imageFlux ->imagesList.add(imageFlux));
Run Code Online (Sandbox Code Playgroud)

请注意,我正在寻找不涉及调用block()的解决方案(否定被动反应的好处),除非这是唯一的方法.

在非反应情况下,这就是我想要的:

List<House> houses  --> List of all houses
Map<String,List<Image>> mapOfImages  --> where key is houseId 
Run Code Online (Sandbox Code Playgroud)

因此,对于每个房子,我可以轻松地获取该房屋的图像,同时在视图模板中迭代房屋.

这些(house和mapOfImages)将传递给模型

model.addAttribute("houses",houses);
model.addAttribute("mapOfImages",mapOfImages);
Run Code Online (Sandbox Code Playgroud)

所以现在在thyemleaf视图模板中我可以:

<div data-th-each="house : ${houses}">
        <h3 data-th-text="${house.title}"></h3>
        <div data-th-each="image : ${mapOfImages.get(house.houseId)}">
          <h5 data-th-text="${image.fileName}"></h5>
          <h5 data-th-text="${image.type}"></h5>
        </div>
 </div>   
Run Code Online (Sandbox Code Playgroud)

正在使用的数据库是Mongodb,它有两个独立的集合:house和image,即没有嵌入式集合,唯一将图像绑定到房子的是图像上的houseId属性.

Mur*_*kan 5

您基本上希望将House对象流转换为对象流Image

因此,请使用flatMap()Flux<Flux<T>>(或Flux<Mono<T>>)转换为Flux<T>

Mono<List<Image>> images = houseService.findAllHouses() // returns Flux<House>
  .flatMap(house -> imageService.findByHouseId(id)      // returns Flux<Image>
                        .filter(image -> "yes".equals(image.getCover()) && ... )) 
  .collectList();                                       //returns Mono<List<Image>>
Run Code Online (Sandbox Code Playgroud)

可以在collectList()这里使用它,因为您很可能仍然想转换images为单个Mono<ServerResponse>对象:

return images.map(imageList -> ServerResponse.ok()
                                       .body(fromObject(imageList)));
Run Code Online (Sandbox Code Playgroud)

另外,我建议阅读有关何时使用哪个运算符的Project Reactor参考


编辑:

因此,您想要一个Mono<Map<String, Collection<Image>>代替。我的答案将取决于Image该类是否具有对的引用House。否则,仍然可以,但是答案会更加冗长。

我将描述Image不包含HouseID 的困难方式。我们需要……来链接属于特定房屋的图像列表。您可以为此目的定义一个类,也可以仅使用reactor.util.function.Tuple2。有了这些,我们可以使用collectMap()

Mono<Map<String, Collection<Image>>> images = houseService.findAllHouses()
     .flatMap(house -> imageService.findByHouseId(id)
                           .filter(...)
                           .map(image -> Tuples.of(id, image)))
     .collectMultiMap(tuple -> tuple.getT1(), 
                      tuple -> tuple.getT2());
Run Code Online (Sandbox Code Playgroud)

当然,如果您有对的引用House,则可以省略掉它map()collectMultiMap直接使用:

...
    .collectMultiMap(image -> image.getHouseId(), image -> image);
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

4755 次

最近记录:

7 年,6 月 前