问题描述
假设我们有一个目录和类别。 每个类别都可以有子类别。
文档来自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)));
CatalogConverter
和CategoryConverter
是实现java.util.Function
的简单类,以便将数据库模型映射到API模型。
但是现在我需要递归地加载每个类别的子项,并将其设置为CategoryConverter
的构造函数参数,以设置其子项。
我已经尝试使用expand
和expandDeep
,但是我不知道该如何工作。由于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": [ ]
}
]
}
]
}
如果还有改进的空间,请告诉我。