我是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属性。每个图像对象都有一个属性&#34; cover&#34;字符串值&#34;是&#34;或&#34;不&#34;和另一个属性&#34;类型&#34;有各种字符串值,如&#34;卧室&#34;。我想收集一个
list of Flux<Image> like List<Flux<Image>> or List<List<Image>>
仅包含那些&#34;覆盖&#34; ==&#34;是&#34;或&#34;键入&#34; ==&#34;卧室&#34;。怎么做到这一点?编程代码将回答这个问题。
以下尝试作为解决方案的一部分,但即使是这个部分解决方案也不起作用:
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()的解决方案(否定被动反应的好处),除非这是唯一的方法。
在非反应情况下,这就是我想要的:
List<House> houses --> List of all houses
Map<String,List<Image>> mapOfImages --> where key is houseId
因此,对于每个房子,我可以轻松地获取该房屋的图像,同时在视图模板中迭代房屋。
这些(house和mapOfImages)将传递给类似
的模型model.addAttribute("houses",houses);
model.addAttribute("mapOfImages",mapOfImages);
所以现在在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>
正在使用的数据库是Mongodb,它有两个独立的集合:house和image,即没有嵌入式集合,唯一将图像绑定到房子的是图像上的houseId属性。
答案 0 :(得分:3)
您基本上希望将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);