1

I'm using Spring 5 webflux with ReactiveMongoRepositories. Suppose I have 2 collections "Race" and "RaceParticipation":

    Race : {
    "_id" : "ID",
    "name" : "Name"
    }

    RaceParticipation : {
    "_id" : "ID",
    "userId" : "ID",
    "raceId" : "ID"
    }

I need to find a page of Races in which a given user has participated.

The solution I went with is call raceParticipationRepository.findByUserId("userId", PageRequest.of(0,10)) This returns a Flux<UserParticipation>. The I should collect the ids from the response and call raceRepository.findAllById(ids).

Here is a snippet:

Flux<Race> findUserRaces(String userId, int page){
    return raceParticipationRepository.findByUserId(userId, status,
                PageRequest.of(page, 6))
            .collectList()
            .map(list -> list.stream()
                    .map(ParticipationRepository::getRaceId)
                    .collect(Collectors.toList()))
            .flatMap(list -> raceRepository.findAllById(list));
}

This code doesn't compile. "Required Flux<Race> but flatMap was inferred to Mono..."

Any idea on what I'm missing or how should I do?

Monta
  • 1,136
  • 1
  • 12
  • 28
  • If you can, please don't code something in Java that you can do in SQL - its less performant by a huge factor, although it's more entertaining to write java. – Frischling Mar 11 '19 at 08:24
  • It's a MongoDB database with no DBRef. How would u do that without Java? – Monta Mar 11 '19 at 08:44
  • Ah, overread the "Mongo" part, sorry for that; I also posted an answer, since I guessed that you need the Java part anyways. – Frischling Mar 11 '19 at 08:46

1 Answers1

2

Your problem is the collectList() part, since it makes a Mono from your Flux, which you obviously don't want - you're making a stream from the list immediately after collection. This here should do the same, plus mapping the Mono to a Flux with flatMapMany:

raceParticipationRepository.findByUserId(userId, status,
            PageRequest.of(page, 6))
      .map(ParticipationRepository::getRaceId)
                .collectList(Collectors.toList()) // returns Mono<List>
      .flatMapMany(list -> raceRepository.findAllById(list)); // Mono -> Flux again
Frischling
  • 2,100
  • 14
  • 34
  • I'm using collectList before ParticipationRepository::getRaceId because I don't want to make a database for each raceParticipation object. I want to collect the results of the 1st call then make 1 call with the list of Ids to get all the races in 1 shot – Monta Mar 11 '19 at 08:50
  • Yes, I gathered, but I think you're doing the collectList one time to much, since you can do the mapping to getRacId in the flux, and then collectList. you then have a Mono, that you can put in a flatMapMany, and get a Flux of the data back. – Frischling Mar 11 '19 at 08:52