Spring Webflux – 如何使用Tuple3将三个Flux对象聚合为一个

huangapple go评论59阅读模式
英文:

Spring Webflux - How to aggregate three Flux objects into 1 using Tuple3

问题

我正在尝试使用Tuple3将3个Flux对象聚合成一个,但我仍然卡住了。我在网上搜索到可以使用Mono.zip(),但这不适用于Flux

public class OrderService {

    private final AppWebClient appWebClient;

    public Mono<OrderDetailsAggregate> getAggregatedOrderDetails(List<String> orderNoList1,
            List<String> orderNoList2, List<String> orderNoList3) {
        Flux<Map<String, List<String>>> fluxOne = this.appWebClient.getFluxOne(orderNoList1);
        Flux<Map<String, String>> fluxTwo = this.appWebClient.getFluxTwo(orderNoList2);
        Flux<Map<String, List<String>>> fluxThree = this.appWebClient.getFluxThree(orderNoList3);

        return Mono.zip(fluxOne, fluxTwo, fluxThree).map(this::combine); //error here
    }

    private OrderDetailsAggregate combine(
            Tuple3<Flux<Map<String, List<String>>>, Flux<Map<String, String>>, Flux<Map<String, List<String>>> > tuple) {
        return OrderDetailsAggregate.create(tuple.getT1(), tuple.getT2(), tuple.getT3()); 
    }
}

fluxOnefluxTwofluxThree有不同的数据类型。

OrderDetailsAggregate

@Data
@ToString
@AllArgsConstructor(staticName = "create")
public class OrderDetailsAggregate {

    private Flux<Map<String, List<String>>>  fluxOne;
    private Flux<Map<String, String>> fluxTwo;
    private Flux<Map<String, List<String>>> fluxThree;
}

如何将它们组合起来?

谢谢。

英文:

I am trying to aggregate 3 Flux objects into 1 using Tuple3
However, I am still stuck. I searched online and saw that you can use Mono.zip() but that doesn't apply to Flux.

public class OrderService {

	private final AppWebClient appWebClient;

	public Mono&lt;OrderDetailsAggregate&gt; getAggregatedOrderDetails(List&lt;String&gt; orderNoList1,
			List&lt;String&gt; orderNoList2, List&lt;String&gt; orderNoList3) {
		Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; fluxOne = this.appWebClient.getFluxOne(orderNoList1);
		Flux&lt;Map&lt;String, String&gt;&gt; fluxTwo = this.appWebClient.getFluxTwo(orderNoList2);
		Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; fluxThree = this.appWebClient.getFluxThree(orderNoList3);

		return Mono.zip(fluxOne, fluxTwo, fluxThree).map(this::combine); //error here
	}

	private OrderDetailsAggregate combine(
			Tuple3&lt; Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt;, Flux&lt;Map&lt;String, String&gt;&gt;, Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; &gt; tuple) {
		return OrderDetailsAggregate.create(tuple.getT1(), tuple.getT2(), tuple.getT3()); 
	}

}

fluxOne, fluxTwo, fluxThree have different data types.

OrderDetailsAggregate class

@Data
@ToString
@AllArgsConstructor(staticName = &quot;create&quot;)
public class OrderDetailsAggregate {

	private Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt;  fluxOne;
	private Flux&lt;Map&lt;String, String&gt;&gt; fluxTwo;
	private Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; fluxThree;
}

How do I combine them?

Thank you.

答案1

得分: 1

如果您需要从getAggregatedOrderDetails方法返回Mono&lt;OrderDetailsAggregate&gt;,那么为什么不只是创建Mono对象而不使用zip

public Mono&lt;OrderDetailsAggregate&gt; getAggregatedOrderDetails(List&lt;String&gt; orderNoList1,
                                                                 List&lt;String&gt; orderNoList2, List&lt;String&gt; orderNoList3) {
        Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; fluxOne = this.appWebClient.getFluxOne(orderNoList1);
        Flux&lt;Map&lt;String, String&gt;&gt; fluxTwo = this.appWebClient.getFluxTwo(orderNoList2);
        Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; fluxThree = this.appWebClient.getFluxThree(orderNoList3);
        OrderDetailsAggregate aggregate = OrderDetailsAggregate.create(fluxOne, fluxTwo, fluxThree);
        return Mono.just(aggregate);
    }
英文:

If you need to return Mono&lt;OrderDetailsAggregate&gt; from getAggregatedOrderDetails method, then why not just create Mono object without zip:

public Mono&lt;OrderDetailsAggregate&gt; getAggregatedOrderDetails(List&lt;String&gt; orderNoList1,
                                                                 List&lt;String&gt; orderNoList2, List&lt;String&gt; orderNoList3) {
        Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; fluxOne = this.appWebClient.getFluxOne(orderNoList1);
        Flux&lt;Map&lt;String, String&gt;&gt; fluxTwo = this.appWebClient.getFluxTwo(orderNoList2);
        Flux&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; fluxThree = this.appWebClient.getFluxThree(orderNoList3);
        OrderDetailsAggregate aggregate = OrderDetailsAggregate.create(fluxOne, fluxTwo, fluxThree);
        return Mono.just(aggregate);
    }

答案2

得分: 1

对我来看,你似乎是将appWebClient返回的Flux视为Mono的方式来处理。

我猜你想要在OrderDetailsAggregate中获取所有Flux的值。如果是这样的话,我建议将Flux收集到Mono中,使用Mono.zip获得一个元组,然后将其映射到你的OrderDetailsAggregate

public Mono<OrderDetailsAggregate> getAggregatedOrderDetails(List<String> orderNoList1,
            List<String> orderNoList2, List<String> orderNoList3) {
        Mono<Map<String, List<String>>> monoOne = this.appWebClient.getFluxOne(orderNoList1).collect(HashMap::new, Map::putAll);
        Mono<Map<String, String>> monoTwo = this.appWebClient.getFluxTwo(orderNoList2).collect(HashMap::new, Map::putAll);
        Mono<Map<String, List<String>>> monoThree = this.appWebClient.getFluxThree(orderNoList3).collect(HashMap::new, Map::putAll);

        return Mono.zip(monoOne, monoTwo, monoThree).map(tuple -> OrderDetailsAggregate.create(tuple.getT1(), tuple.getT2(), tuple.getT3()));
}

如果你只关心Flux中的一个值,那么你可以用next()替代collect()

编辑:我看到你正在向create()方法传递Flux。所以这个答案只适用于如果你也更改了那个方法。如果你的OrderDetailsAggregate是一个DTO而不是一个服务,那么也许最好不要在其中包含Flux逻辑,而是在getAggregatedOrderDetails方法中执行。

英文:

To me it looks like you are treating the Flux'es your appWebClient is returning as if they were Mono's.

I assume, you want to have all values of the fluxes in your OrderDetailsAggregate. Should that be the case, I would suggest to collect the Flux into a Mono, do a Mono.zip to get a tuple and map that to your OrderDetailsAggregate:

public Mono&lt;OrderDetailsAggregate&gt; getAggregatedOrderDetails(List&lt;String&gt; orderNoList1,
            List&lt;String&gt; orderNoList2, List&lt;String&gt; orderNoList3) {
        Mono&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; monoOne = this.appWebClient.getFluxOne(orderNoList1).collect(HashMap::new, Map::putAll);
        Mono&lt;Map&lt;String, String&gt;&gt; monoTwo = this.appWebClient.getFluxTwo(orderNoList2).collect(HashMap::new, Map::putAll);
        Mono&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; monoThree = this.appWebClient.getFluxThree(orderNoList3).collect(HashMap::new, Map::putAll);

        return Mono.zip(monoOne, monoTwo, monoThree).map(tuple -&gt; OrderDetailsAggregate.create(tuple.getT1(), tuple.getT2(), tuple.getT3()));
}

Should you just care about one value from the flux, then you can replace the collect() with next().

Edit: I see you are passing Flux to your create() method. So this answer only applies if you would change that as well. If your OrderDetailsAggregate is a Dto and not a service, then it would perhaps be a good idea to not have that flux logic in there but rather do it in the getAggregatedOrderDetails method.

huangapple
  • 本文由 发表于 2023年3月7日 11:47:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75657881.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定