Project Reactor:用Mono的结果丰富通量的结果

我正在努力将反应式编程引入我的公司。我正在构建一个活动推荐系统的简单演示,以证明其性能优势。

我要面对的挑战之一是在一个流中增加另一个流的结果。我有一个工作示例,如下所示,但是我不确定这种方法是否存在任何问题。有人可以看看并提供任何潜在的改进。

    public Flux<Integer> getRecommendedactivities(Long userId,String location,Integer limit) {
        Flux<activityData> activities = activityDatabaseService.getByLocation(location);
        Mono<Map<String,BigInteger>> userCategoryScores = userScoresDatabaseService.get(userId);

        return activities
            .zipWith(userCategoryScores.cache().repeat(),this::scoreactivitiesBasedOnUserCategoryScores)
            .sort(compareactivityScoreStrength)
            .map(ScoredactivityData::getactivityId)
            .take(limit);
    }

    private ScoredactivityData scoreactivitiesBasedOnUserCategoryScores(activityData deal,Map<String,BigInteger> categoryScores){
        //This method combines the deal score and user category scores to come up with a final score
    }

谢谢, 卡尔

iCMS 回答:Project Reactor:用Mono的结果丰富通量的结果

您那里的代码天生没有错。一些可能不会有用的样式点:

  • 反应式编程的“规范”是使用流利的样式并内联所有内容,而不是在方法顶部声明单独的局部变量并在反应式链中使用它们。
  • x.zipWith(y.cache().repeat())模式可以很好地工作,但是如果可以避免的话,我发现它有点难看(zipWith()暗示了两个 real {{1} }数据存储在我的脑海中,而不是Flux被任意缓存和重复的数据-因此,该行为不一定像它看起来那样“突出”。)相反,我更喜欢Mono-它使您更清楚地了解一个值,并通过 real y.flatMapMany(x)将转换应用于多个值。因此,在您的情况下,可能看起来像这样:

    Flux
  • userScoresDatabaseService.get(userId) .flatMapMany(c -> activityDatabaseService.getByLocation(location) .map(a -> scoreActivitiesBasedOnUserCategoryScores(a,c)) ) .sort() //etc. 确实应该是“不得已而为之”的操作,尤其是因为您将性能优势作为探索被动因素的原因。 (从数据库服务读取整个数据,然后对其进行排序,然后仅采用第一个Flux.sort()值会导致效率低下-您最好对数据层中的值进行排序和限制。) {1}}将必须等待整个源n完成,然后再对值进行排序和返回,将每个值存储在内存中,这样就失去了许多好处。 Flux.sort()首先。无需担心排序和限制,这也使您的反应链更短,更简单。
  • Nit:您的某些方法名称和变量名称似乎很长。如果可能的话,我会尽量缩短它们-我发现这在反应链的背景下使事情更容易阅读。

基于以上几点,您整个Flux都可以读到以下内容:

Flux

...至少对我来说,读起来更短更简单。

本文链接:https://www.f2er.com/2188375.html

大家都在问