I have three mongoDB collections and their respective documents namely; mosques, prayers and subscriptions as follows:
mosque document:
{
"_id": "64a48ce14ebcac9ec9a3b0b9",
"address": "pti road , effurun",
"city": "Warri",
"state": "Delta",
"country": "Nigeria",
"name": "PTI central mosque",
"image": "",
"imamName": "Malam malam",
"verified": false,
"active": true,
"__v": 0
}
prayer document:
{
"_id":"64a5f9c2f11d298e808170cb".
"title": "Subhi",
"adhaanTime": "05:10",
"iqaamaTime": "05:20",
"imamName": "Malam Suleiman",
"mosque":"64a48ce14ebcac9ec9a3b0b9",
"__v": 0
}
subscription document
{
"_id":"64aac5e5fd0db3668806e4ee",
"user":"649966a5cba88e510479da0a",
"service":"64a75b6e4c57834c539faea6"
"mosque":"64a48ce14ebcac9ec9a3b0b9",
"__v": 0
}
I want to be able to query a single mosque with its associated prayers and each prayer with its subscriptions using aggregation like so:
{
"_id": "64a48ce14ebcac9ec9a3b0b9",
"address": "pti road , effurun",
"city": "Warri",
"state": "Delta",
"country": "Nigeria",
"name": "PTI central mosque",
"image": "",
"imamName": "Malam malam",
"verified": false,
"active": true,
"prayers": [
{
"_id":"64a5f9c2f11d298e808170cb".
"title": "Subhi",
"adhaanTime": "05:10",
"iqaamaTime": "05:20",
"imamName": "Malam Suleiman",
"mosque":"64a48ce14ebcac9ec9a3b0b9",
"__v": 0,
"subscriptions": [
{
"_id":"64aac5e5fd0db3668806e4ee",
"user":"649966a5cba88e510479da0a",
"service":"64a75b6e4c57834c539faea6"
"mosque":"64a48ce14ebcac9ec9a3b0b9",
"__v": 0
},
{
"_id":"6546775e5fd0db3668806e45446",
"user":"649966a5cba88e510479da0a",
"service":"64a75b6e4c57834c539faea6"
"mosque":"64a48ce14ebcac9ec9a3b0b9",
"__v": 0
}
]
},
{
"_id":"64a5f9c2f11d298e808170cb".
"title": "Subhi",
"adhaanTime": "05:10",
"iqaamaTime": "05:20",
"imamName": "Malam Suleiman",
"mosque":"64a48ce14ebcac9ec9a3b0b9",
"__v": 0,
"subscriptions": [
{
"_id":"64aac5e5fd0db3668806e4ee",
"user":"649966a5cba88e510479da0a",
"service":"64a75b6e4c57834c539faea6"
"mosque":"64a48ce14ebcac9ec9a3b0b9",
"__v": 0
},
{
"_id":"6546775e5fd0db3668806e45446",
"user":"649966a5cba88e510479da0a",
"service":"64a75b6e4c57834c539faea6"
"mosque":"64a48ce14ebcac9ec9a3b0b9",
"__v": 0
}
]
},
]
}
How do I achieve that?
This is the aggregate I attempted to build:
const result = await Mosque.aggregate([
{
$match: {
_id: new mongoose.Types.ObjectId(mosqueId),
},
},
{
$lookup: {
from: "prayers",
localField: "_id",
foreignField: "mosque",
as: "prayers",
},
},
{
$set: {
"prayers.subscriptions": "subscriptions",
},
},
]);
And I got the following result:
{
"mosque": [
{
"_id": "64a48ce14ebcac9ec9a3b0b9",
"user": {
"_id": "649966a5cba88e510479da0a",
"firstName": "Bello",
"otherName": "sani",
"phoneNumber": "+6575455475",
"email": "",
"authProvider": "credentials",
"password": "$2a$10$Ednofrd3dxjWzgDC77rq1umrNhpzAKc.ypzksQ3rbOWTd7lKSFGC6",
"location": "my town",
"lga": "my town",
"state": "my town",
"country": "my town",
"verified": false,
"active": true,
"role": "user",
"createdAt": "2023-06-26T10:21:25.067Z",
"updatedAt": "2023-06-26T10:21:25.067Z",
"__v": 0
},
"address": "pti road , effurun",
"city": "Warri",
"state": "Delta",
"country": "Nigeria",
"name": "PTI central mosque",
"image": "",
"imamName": "Malam Malam",
"verified": false,
"active": true,
"createdAt": "2023-07-04T21:19:29.365Z",
"updatedAt": "2023-07-04T21:19:29.365Z",
"__v": 0,
"prayers": [
{
"_id": "64a5f9c2f11d298e808170cb",
"title": "Subhi",
"adhaanTime": "05:10",
"iqaamaTime": "05:20",
"imamName": "Malam malam",
"mosque": "64a48ce14ebcac9ec9a3b0b9",
"createdAt": "2023-07-05T23:16:18.641Z",
"updatedAt": "2023-07-05T23:16:18.641Z",
"__v": 0,
"subscriptions": "subscriptions"
},
{
"_id": "64a5fca4f11d298e8081b847",
"title": "Zuhr",
"adhaanTime": "01:42",
"iqaamaTime": "00:50",
"imamName": "Malam malam",
"mosque": "64a48ce14ebcac9ec9a3b0b9",
"createdAt": "2023-07-05T23:28:36.180Z",
"updatedAt": "2023-07-06T23:54:38.111Z",
"__v": 0,
"subscriptions": "subscriptions"
},
{
"_id": "64a5fecaf11d298e8081dd6e",
"title": "Asr",
"adhaanTime": "04:05",
"iqaamaTime": "04:15",
"imamName": "Malam malam",
"mosque": "64a48ce14ebcac9ec9a3b0b9",
"createdAt": "2023-07-05T23:37:46.418Z",
"updatedAt": "2023-07-06T23:55:21.588Z",
"__v": 0,
"subscriptions": "subscriptions"
},
{
"_id": "64a75b6e4c57834c539faea6",
"title": "Magrib",
"adhaanTime": "06:55",
"iqaamaTime": "07:05",
"imamName": "Malam malam",
"mosque": "64a48ce14ebcac9ec9a3b0b9",
"createdAt": "2023-07-07T00:25:18.282Z",
"updatedAt": "2023-07-07T10:37:26.153Z",
"__v": 0,
"subscriptions": "subscriptions"
}
]
}
]
}
I wish to replace "subscriptions" with matching list of subscription documents from the subscriptions collection
$lookup
$lookup
to pull the subscriptions. You could either do that as a separate top level stage and then reshape the document in the$set
as you're currently doing, or use thepipeline
functionality of$lookup
to embed the other one in the first (potentially preventing the need to do that final$set
at all).