Unrolling a Paginated Result
Consider a Spring Data based repository on a model called City:import org.springframework.data.jpa.repository.JpaRepository; import samples.geo.domain.City; public interface CityRepo extends JpaRepository<City, Long> { }This repository provides a way to retrieve the paginated result, along the following lines:
cityRepo.findAll(PageRequest.of(0, 5))
Now, if I were to unroll multiple pages into a result, the way to do it would be the following kind of a loop:
var pageable: Pageable = PageRequest.of(0, 5) do { var page: Page<City> = cityRepo.findAll(pageable) page.content.forEach { city -> LOGGER.info("City $city") } pageable = page.nextPageable() } while (page.hasNext())
An equivalent unroll of a paginated result can be done using the Reactor expand operator the following way:
val result: Flux<City> = Mono .fromSupplier { cityRepo.findAll(PageRequest.of(0, 5)) } .expand { page -> if (page.hasNext()) Mono.fromSupplier { cityRepo.findAll(page.nextPageable()) } else Mono.empty() } .flatMap { page -> Flux.fromIterable(page.content) } result.subscribe( { page -> LOGGER.info("City ${page}") }, { t -> t.printStackTrace() } )
Here the first page of results expands to the second page, the second page to the third page and so on until there are no pages to retrieve.
Traversing a Tree
Consider a node in a tree structure represented by the following model:
data class Node( val id: String, val nodeRefs: List<String>, )
A sample data which looks like this:
can be traversed using a call which looks like this:
val rootMono: Mono<Node> = nodeService.getNode("1") val expanded: Flux<Node> = rootMono.expand { node -> Flux.fromIterable(node.childRefs) .flatMap { nodeRef -> nodeService.getNode(nodeRef) } } expanded.subscribe { node -> println(node) }
This is a breadth-first expansion, the output looks like this:
Node-1 Node-1-1 Node-1-2 Node-1-1-1 Node-1-1-2 Node-1-2-1 Node-1-2-2
An expandDeep variation would traverse it depth-first