在反应流上递归加载和映射

问题描述

假设我们有一个目录和类别。 每个类别都可以有子类别。

文档来自MongoDB:

@Data
@Builder
@Document("catalogs")
public class Catalog {
    private String catalogId;
}

@Data
@Builder
@Document("categories")
public class Category {
    private String categoryId;
    private Set<String> parentIds;
}

现在我还有其他API模型可以在前端中进一步使用:

@Getter
@Builder
public class ApiCatalog {
    private String id;
    private List<ApiCategory> categories;
}

@Getter
@Builder
public class ApiCategory {
    private String id;
    private List<ApiCategory> children;
}

我正在获得具有以下一级类别的目录:

catalogReactiveRepository
        .findByCatalogId(catalogId) // Mono<Catalog>
        .flatMap(catalog -> categoryReactiveRepository.findByParentIdsContains(catalog.getCatalogId()) // Flux<Category>
                .map(new CategoryConverter()) // Flux<ApiCategory>
                .collectList() // Mono<List<ApiCategory>>
                .map(categories -> new CatalogConverter(categories).apply(catalog)));

CatalogConverterCategoryConverter是实现java.util.Function的简单类,以便将数据库模型映射到API模型。

但是现在我需要递归地加载每个类别的子项,并将其设置为CategoryConverter的构造函数参数,以设置其子项。

我已经尝试使用expandexpandDeep,但是我不知道该如何工作。由于expand / expandDeep似乎还给我一些东西,所以我不再有亲子关系。

解决方法

使用以下代码我得到了我需要的结果:

return ok()
        .body(catalogReactiveRepository.findFirstByStoresContains(storeId)
                .zipWhen(catalog -> categoryReactiveRepository.findAllByCatalogsIdContainsOrderByCatalogsSequenceAsc(catalog.getId())
                        .collectList()
                        .doOnNext(catalog::setTree)
                        .flatMapMany(Flux::fromIterable)
                        .expand(category -> Flux.fromIterable(Optional.ofNullable(category.getChildren()).orElse(Collections.emptyList()))
                                .map(CategoryMember::getId)
                                .collectList()
                                .flatMapMany(categoryReactiveRepository::findAllByIdIn)
                                .collectList()
                                .doOnNext(category::setSubCategories)
                                .flatMapMany(Flux::fromIterable))
                        .collectList())
                .map(Tuple2::getT1)
                .map(catalogByStoreIdResponseMapper),CatalogByStoreIdResponse.class);

结果:

{

    "id": "DEMO_CATALOG","tree": [
        {
            "id": "DEMO_CATEGORY_1","children": [
                {
                    "id": "DEMO_CATEGORY_1_1","children": [ ]
                }
            ]
        },{
            "id": "DEMO_CATEGORY_2","children": [
                {
                    "id": "DEMO_CATEGORY_2_1","children": [ ]
                }
            ]
        }
    ]

}

如果还有改进的空间,请告诉我。