Reputation: 1095
I'm just getting started with reactive so please correct me if the question doesn't make sense.
I'm creating a rest controller with Spring WebFlux + Reactive MongoDB as a database and I have the following document structure in it.
{
"_id": {
"$oid": "5ee350839d3d4e34f0790566"
},
"customerId": "7777",
"contacts": [{
"_id": {
"$oid": "5ee350839d3d4e34f0790565"
},
"name": "Alice",
"mobileNumbers": "0123456789"
}, {
"_id": {
"$oid": "5ee3508a9d3d4e34f0790567"
},
"name": "Tom",
"mobileNumbers": "1123456789"
}
],
"_class": "com.demo.contact.model.Customer"
}
This sample document has a customer with his contacts. I'm trying to get a Flux when searching from the list of contact for a customer.
public Mono<List<Contact>> searchContacts(String customerId, String searchCriteria) {
return customerRepository.findById(customerId).map(existingCustomer -> {
List<Contact> contacts= existingCustomer.getContacts().stream()
.filter( // some filtering code )
.sorted(Comparator.comparing(Contact::getName))
.collect(Collectors.toList());
return contacts;
});
}
The question is how do I change this piece of code to get a Flux<Object>
instead of a Mono<List<Object>>
?
Upvotes: 1
Views: 1434
Reputation: 11551
There are several methods to go from Mono
to Flux
which you will learn with experience. You will need to get better at Java streams
, better with Optional
and, of course, the Reactive
API. The Optional
part is important because you need to understand that using .map
means you still have an Optional
result so you should include a .orElse
as well.
You didn't specify whether you are using a reactive MonogoDb driver, so I assume you are.
One good way to go from a Mono<List<?>>
is to use Mono::flatMapMany
or Mono::flatMapIterable
;
public Flux<Contact> searchContacts(String customerId, String searchCriteria) {
return customerRepository.findMonoById(customerId)
.map(optionalCustomer -> optionalCustomer
.map(existingCustomer -> existingCustomer.getContacts().stream().filter(c -> c == c)
.sorted(Comparator.comparing(Contact::getName)).collect(Collectors.toList()))
.orElse(Collections.emptyList()))
.flatMapMany(contacts -> Flux.fromIterable(contacts));
}
or
public Flux<Contact> searchContacts(String customerId, String searchCriteria) {
return customerRepository.findMonoById(customerId)
.map(optionalCustomer -> optionalCustomer
.map(existingCustomer -> existingCustomer.getContacts().stream().filter(c -> c == c)
.sorted(Comparator.comparing(Contact::getName)).collect(Collectors.toList()))
.orElse(Collections.emptyList()))
.flatMapIterable(Function.identity());
}
In case you are not using a reactive driver then you can just make a Flux
from an iterable.
public Flux<Contact> searchContacts(String customerId, String searchCriteria) {
return Flux.fromIterable(customerRepository.findById(customerId)
.map(existingCustomer -> existingCustomer.getContacts().stream().filter(c -> c == c)
.sorted(Comparator.comparing(Contact::getName)).collect(Collectors.toList()))
.orElse(Collections.emptyList()));
}
Upvotes: 2