Recently, I crafted a sophisticated pipeline for my database:
let orders = await Order.aggregate(
{
$unwind: "$candidate",
},
{
$lookup: {
from: "groups",
localField: "candidate.groupId",
foreignField: "_id",
as: "groupData",
},
},
{
$lookup: {
from: "users",
let: {
id: "$candidate.groupId",
},
pipeline: [
{ $match: { groupId: { $ne: null } } },
{
$match: {
$expr: { $in: ["$$id", "$groupId"] },
},
},
{ $project: { name: 1, email: 1, _id: 1 } },
],
as: "members",
},
},
{ $match: { "members._id": new ObjectId(req.userId) } },
{
$lookup: {
from: "users",
let: { ids: "$candidate.autonomousId" },
pipeline: [
{
$match: {
$expr: { $in: ["$_id", "$$ids"] },
},
},
{ $project: { name: 1, email: 1, _id: 1 } },
],
as: "candidate",
},
},
{
$project: {
groupData: 1,
members: 1,
candidate: 1,
stillAvailable: 1,
_id: 0,
},
}
).toArray();
After executing the pipeline, I obtained the expected result...
{ candidate:
[ { _id: 601817dc2eeecd17db3a68f6,
name: 'Maria' },
{ _id: 601817ef2eeecd17db3a68f7,
name: 'Jose' } ],
groupData:
[ { _id: 606632403fffb851b8c41d12,
name: 'Giraia' } ],
members:
[ { _id: 601817dc2eeecd17db3a68f6,
name: 'Maria' },
{ _id: 601817ef2eeecd17db3a68f7,
name: 'Jose' },
{ _id: 60182cbb2b654330d2458f89,
name: 'Jonas'} ] }
However, in order to enhance the organization of my code, I aimed to merge the last step of manually comparing and filtering the members
array with the candidates
array into the pipeline itself. Despite numerous attempts, I couldn't achieve this using aggregation. As a workaround, I had to process the incomplete pipeline result in my backend. Here is the snippet of code I used:
orders.forEach(
(order) =>
(order.stillAvailable = order.members.filter(
(autonomous) =>
!order.candidate.some((el) => {
return el._id.toString() === autonomous._id.toString();
})
))
);
This adjustment led me to the desired outcome...
{ candidate:
[ { _id: 601817dc2eeecd17db3a68f6,
name: 'Maria' },
{ _id: 601817ef2eeecd17db3a68f7,
name: 'Jose' } ],
groupData:
[ { _id: 606632403fffb851b8c41d12,
name: 'Giraia' ],
members:
[ { _id: 601817dc2eeecd17db3a68f6,
name: 'Maria' },
{ _id: 601817ef2eeecd17db3a68f7,
name: 'Jose' },
{ _id: 60182cbb2b654330d2458f89,
name: 'Jonas' ],
stillAvailable:
[ { _id: 60182cbb2b654330d2458f89,
name: 'Jonas' ] }
The challenging part is finding a way to integrate the final step, currently handled by backend logic, directly into the aggregation pipeline. Any suggestions on how to accomplish this task?