我是Spring Reactive Project的新手。在我的Spring Boot Controller类中
Flux<House> ( list of all houses in the database) and Flux<Image>
来自服务层,其中给定的
Flux<Image>
是给定房屋的图像,例如房屋列表,每个房屋都有自己的图像集合。这意味着我必须遍历Flux<House>
以获得房屋的ID,然后在Image上调用findByHouseId以获得Flux<Image>
,每个Image都具有houseId属性。每个图像对象都具有字符串值"is"或“否”的属性“cover”,以及具有诸如“bedroom”之类的各种字符串值的另一个属性“type”。我想收集一个list of Flux<Image> like List<Flux<Image>> or List<List<Image>>
仅包含“封面” =="is"或“类型” ==“卧室”的那些图像。如何实现呢?编程代码将回答这个问题。
尝试将以下方法作为解决方案的一部分,但即使是部分解决方案也无法使用:
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));
请注意,除非这是唯一的方法,否则我正在寻找不涉及调用block()的解决方案(否定了被动响应的优势)。
在非 react 情况下,这就是我想要的:
List<House> houses --> List of all houses
Map<String,List<Image>> mapOfImages --> where key is houseId
因此,对于每个房屋,我都可以在 View 模板中遍历房屋时轻松获取该房屋的图像。
这些(房屋和mapOfImages)将传递给模型,例如
model.addAttribute("houses",houses);
model.addAttribute("mapOfImages",mapOfImages);
现在,在thyemleaf View 模板中,我可以:
<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>
正在使用的数据库是Mongodb,它具有两个独立的集合:房屋和图像,即没有嵌入式集合,并且将图像与房屋联系起来的唯一东西是图像上的houseId属性。
最佳答案
您基本上想将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>>
在这里使用
collectList()
是可以的,因为您很可能仍希望将images
转换为单个Mono<ServerResponse>
对象:return images.map(imageList -> ServerResponse.ok()
.body(fromObject(imageList)));
另外,我建议阅读有关Project Reactor reference的when to use which operator。
编辑:
因此,您需要一个
Mono<Map<String, Collection<Image>>
。我的答案将取决于Image
类是否具有对House
的引用。否则,仍然可以,但是答案会更加冗长。我将描述一种很难的方法,其中
Image
不包含House
id。我们需要……,它链接属于特定房屋的图像列表。您可以为此目的定义一个类,也可以只使用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());
当然,如果您有对
House
的引用,则可以再次省略map()
并直接使用collectMultiMap
:...
.collectMultiMap(image -> image.getHouseId(), image -> image);
关于spring-boot - 在Spring Reactive Programming中如何从两个Flux(Object)获取Flux或List?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49676422/