在 WebFlux 中使用聚合

Posted

技术标签:

【中文标题】在 WebFlux 中使用聚合【英文标题】:Using Aggregation in WebFlux 【发布时间】:2018-07-26 11:52:04 【问题描述】:

我正在使用 WebFlux 从 mongoDB 数据库加载数据,我的问题是如何在这种情况下使用存储库对许多集合进行聚合?

package com.example.demo.web;

import com.example.demo.domain.*;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.util.ArrayList;
import java.util.List;

@RestController
public class CountryController 

    private final CountryRepository countryRepository;
    private final AirportRepository airportRepository;
    private final RunwayRepository runwayRepository;

    public CountryController(CountryRepository countryRepository, AirportRepository airportRepository, RunwayRepository runwayRepository) 
        this.countryRepository = countryRepository;
        this.airportRepository = airportRepository;
        this.runwayRepository = runwayRepository;
    

    @CrossOrigin(origins = "http://localhost:4200")
    @GetMapping("/request")
    public Flux<Country> getAll(@RequestParam String name)
        Flux<Country> countries = this.countryRepository.findAllByNameIsStartingWith(name);
        countries.map(country ->
        
            List<Airport> airportList = new ArrayList<Airport>();
            Airport airport =  new  Airport();
            airport.setIsoCountry(country.code);
            country.setAirports(airportList);
            return country;
        );
        return countries;
    

【问题讨论】:

【参考方案1】:

如果你只询问数据聚合,你可以试试这个:

public Flux<Country> getAll(@RequestParam String name) 
    return countryRepository.findAllByNameIsStartingWith(name)
            .flatMap(country ->
                    airportRepository.findAllByCountryId(country.getId())
                            .map(addAirportToCountry(country))
                            .reduce((country1, country2) -> country2) // it is the same country
            );


private Function<Airport, Country> addAirportToCountry(Country country) 
    return airport -> 
        country.addAirport(airport);
        return country;
    ;

我们在这里:

请求国家/地区, 为每个国家/地区提出其机场请求 减少机场通量以按国家/地区分组

但在 NoSQL DB 的情况下,最好使用非规范化的 DB 模式。 在这种情况下,国家实体应包含相关机场的列表。所以请求:

countryRepository.findAllByNameIsStartingWith(name);

会返回你需要的一切。

【讨论】:

但是我需要了解为什么我们不能在 Spring 的 bean 中制作一个简单的聚合 mongodb 并将其作为函数添加到 Repository 接口中? 所以你想在一些集合上进行 MongoDB 聚合。仅创建具有正确名称的存储库方法不支持它。 Spring Data Examples 项目有示例如何进行 MongoDB 聚合:github.com/spring-projects/spring-data-examples/tree/master/… 官方文档中有更多关于聚合支持的详细信息:docs.spring.io/spring-data/mongodb/docs/current/reference/html/… 我尝试了一个代码,但我没有得到任何东西只有国家,但机场没有人,也许那个 mongodb 数据库比春天更快地返回数据,我也尝试使用日志调试代码并订阅捕获他们,但没有人了!

以上是关于在 WebFlux 中使用聚合的主要内容,如果未能解决你的问题,请参考以下文章

如何在 webflux 中调试?

为啥在 webflux 中使用 WebFilter corsFilter 时请求返回 404 状态?

Webflux postgresql

SpringBoot2使用WebFlux函数式编程

在 Webflux 中使用 bean 验证时 BlockHound 抛出阻塞调用异常

spring-webflux 中处理错误的正确方法是啥