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
