Spring Data Reactive MongoDB — Aggregation Pipeline

Project Setup:

Sample Application:

{
"name": "sam",
"age": 40,
"skills": [ "js", "react", "python"]
}

{
"name": "jack",
"age": 38,
"skills": [ "js", "angular", "postgres"]
}

{
"name": "james",
"age": 30,
"skills": [ "java", "reactor", "mongo"]
}

{
"name": "smith",
"age": 32,
"skills": [ "qa", "selenium"]
}
{
"js":[
"sam",
"jack"
],
"java":[
"james"
],
"selenium":[
"smith"
]
...
...
}

MongoDB Setup:

version: "3"
services:
mongo:
image: mongo
ports:
- 27017:27017
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: password
mongo-express:
image: mongo-express
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: admin
ME_CONFIG_MONGODB_ADMINPASSWORD: password

Aggregation Pipeline:

  • unwind: Each freelancer has an array of skill sets. It is stored in the skills field. This stage reconstructs the document in a way that a person with 3 skills would be presented as 3 persons with 1 skill each.
{ 
"$unwind" : {
"path" : "$skills"
}
}
  • group: Once you have unwinded (!), now we could group by skills field. For each skill, extract the names and push it to an array!
{
"$group":{
"_id":"$skills",
"names":{
"$push":"$name"
}
}
}
  • project: Once we have grouped the records, then we need to look for the specific fields we are interested in. I exclude the _id and retrieve as skill, then I also need the names field.
{
"$project":{
"_id":0,
"skill":"$_id",
"names":1
}
}

Entity Class:

@Data
@Document
@ToString
public class Freelancer {

@Id
private String id;
private String name;
private int age;
private List<String> skills;

}

Projection Class:

@Data
@ToString
public class SkilledPeople {

private String skill;
private List<String> names;

}

Approach-1:

Mongo Reactive Repository:

Application Properties:

spring.data.mongodb.database=admin
spring.data.mongodb.username=admin
spring.data.mongodb.password=password

Demo:

SkilledPeople(skill=js, names=[sam, jack])
SkilledPeople(skill=angular, names=[jack])
SkilledPeople(skill=postgres, names=[jack])
SkilledPeople(skill=selenium, names=[smith])
SkilledPeople(skill=java, names=[james])
SkilledPeople(skill=mongo, names=[james])
SkilledPeople(skill=react, names=[sam])
SkilledPeople(skill=python, names=[sam])
SkilledPeople(skill=reactor, names=[james])
SkilledPeople(skill=qa, names=[smith])

Approach-2:

Reactive Mongo Template + Aggregation Operation:

Summary:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Vinoth Selvaraj

Vinoth Selvaraj

288 Followers

Principal Software Engineer — passionate about software architectural design, microservices.