Mongoose/Express population issue - node.js

Here are my schemas:
1.The Records schema:
const mongoose = require('mongoose')
const RecordsSchema = new mongoose.Schema({
Title: { type: String, required: true },
postedby: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
}],
Author: { type: String, required: true },
ISBN: { type: String, required: true },
Review: { type: String },
SelectedFile: { type: String },
Likes: { type: Number, default: 0 },
Date: { type: Date, default: Date.now() }
});
module.exports = Records = mongoose.model('record', RecordsSchema, 'record');
Here is the The user Schema:
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
username: { type: String },
email: { type: String, required: true, unique: true },
records: [{
type: [mongoose.Schema.Types.ObjectId],
ref: 'record'
}],
password: { type: String, required: true },
Date: { type: Date, default: Date.now(), immutable: true }
});
module.exports = User = mongoose.model('user', userSchema, 'user');
The express route for getting a record:
router.get('/postedby/', (req, res) => {
Records.findOne()
.populate('postedby')
.exec()
.then(post => {
if (!post) {
return res.status(400).json({ msg: 'Add Posts' });
}
else return res.json(post);
}).catch(err => console.error(err))
});
Result of the route:
{
"postedby": [],
"Likes": 0,
"_id": "5fed8c12a4fb2c1e98ef09f6",
"Title": "New Age",
"Author": "Situma Prisco",
"ISBN": "23422",
"SelectedFile": "",
"Review": "",
"Date": "2020-12-31T08:30:10.321Z",
"__v": 0
},
I'm getting a blank Array on the populated user field(posteddby) .
Please help, What am I doing wrong? And yes, i do have a User Logged in

I implemented your code and Schemas, It's work for me, if you stored data correctly in the database, every things will be ok...
note :
please use find({}) instead of findOne() if data is not displayed again for postedby key, Other issues need to be addressed like mongoose version and ..., because your code and schemas is correct
it's result for me with find({}):
[
{
"postedby": [
{
"records": [
"5ff6bc0bd9e7437184b83f76",
"5ff6bc23d9e7437184b83f78",
"5ff6bc85f1045a4f102bc0cd",
"5ff6bca1f1045a4f102bc0ce",
"5ff6bca5f1045a4f102bc0cf",
"5ff6bcb3f1045a4f102bc0d0",
"5ff6bcc7f1045a4f102bc0d1"
],
"_id": "5ff6b81df463322abc7406ec",
"Date": "2021-01-07T07:28:15.654Z",
"email": "a#test.com",
"password": "$2a$12$wJVDysQxbjuRve.hYn/lbO0rskhwj6y8lwDuEWpCwHeNT/V2mybs.",
"__v": 7
}
],
"Likes": 1,
"Date": "2021-01-07T07:47:11.610Z",
"_id": "5ff6bca1f1045a4f102bc0ce",
"Title": "farsi",
"Author": "javid1",
"ISBN": "1",
"Review": "1",
"SelectedFile": "1",
"__v": 0
},
{
"postedby": [
{
"records": [
"5ff6bc0bd9e7437184b83f76",
"5ff6bc23d9e7437184b83f78",
"5ff6bc85f1045a4f102bc0cd",
"5ff6bca1f1045a4f102bc0ce",
"5ff6bca5f1045a4f102bc0cf",
"5ff6bcb3f1045a4f102bc0d0",
"5ff6bcc7f1045a4f102bc0d1"
],
"_id": "5ff6b81df463322abc7406ec",
"Date": "2021-01-07T07:28:15.654Z",
"email": "a#test.com",
"password": "$2a$12$wJVDysQxbjuRve.hYn/lbO0rskhwj6y8lwDuEWpCwHeNT/V2mybs.",
"__v": 7
}
],
"Likes": 1,
"Date": "2021-01-07T07:47:11.610Z",
"_id": "5ff6bca5f1045a4f102bc0cf",
"Title": "farsi",
"Author": "javid1",
"ISBN": "1",
"Review": "1",
"SelectedFile": "1",
"__v": 0
},
{
"postedby": [
{
"records": [
"5ff6bc0bd9e7437184b83f76",
"5ff6bc23d9e7437184b83f78",
"5ff6bc85f1045a4f102bc0cd",
"5ff6bca1f1045a4f102bc0ce",
"5ff6bca5f1045a4f102bc0cf",
"5ff6bcb3f1045a4f102bc0d0",
"5ff6bcc7f1045a4f102bc0d1"
],
"_id": "5ff6b81df463322abc7406ec",
"Date": "2021-01-07T07:28:15.654Z",
"email": "a#test.com",
"password": "$2a$12$wJVDysQxbjuRve.hYn/lbO0rskhwj6y8lwDuEWpCwHeNT/V2mybs.",
"__v": 7
}
],
"Likes": 1,
"Date": "2021-01-07T07:47:11.610Z",
"_id": "5ff6bcb3f1045a4f102bc0d0",
"Title": "riyazi",
"Author": "javid1",
"ISBN": "1",
"Review": "1",
"SelectedFile": "1",
"__v": 0
},
{
"postedby": [
{
"records": [
"5ff6bc0bd9e7437184b83f76",
"5ff6bc23d9e7437184b83f78",
"5ff6bc85f1045a4f102bc0cd",
"5ff6bca1f1045a4f102bc0ce",
"5ff6bca5f1045a4f102bc0cf",
"5ff6bcb3f1045a4f102bc0d0",
"5ff6bcc7f1045a4f102bc0d1"
],
"_id": "5ff6b81df463322abc7406ec",
"Date": "2021-01-07T07:28:15.654Z",
"email": "a#test.com",
"password": "$2a$12$wJVDysQxbjuRve.hYn/lbO0rskhwj6y8lwDuEWpCwHeNT/V2mybs.",
"__v": 7
}
],
"Likes": 1,
"Date": "2021-01-07T07:47:11.610Z",
"_id": "5ff6bcc7f1045a4f102bc0d1",
"Title": "zaban",
"Author": "javid1",
"ISBN": "1",
"Review": "1",
"SelectedFile": "1",
"__v": 0
},
{
"postedby": [
{
"records": [
"5ff6c275964d062f045e93d3",
"5ff6c283964d062f045e93d5"
],
"_id": "5ff6c253964d062f045e93d2",
"Date": "2021-01-07T08:01:21.499Z",
"email": "b#test.com",
"password": "$2a$12$jmHUrTSPwjaVd0VEIpsGauExHNSukHRyWWiJt4UlEgeWLBo8GPDH.",
"__v": 2
}
],
"Likes": 1,
"Date": "2021-01-07T08:01:21.990Z",
"_id": "5ff6c275964d062f045e93d3",
"Title": "zaban",
"Author": "javid1",
"ISBN": "1",
"Review": "1",
"SelectedFile": "1",
"__v": 0
},
{
"postedby": [
{
"records": [
"5ff6c275964d062f045e93d3",
"5ff6c283964d062f045e93d5"
],
"_id": "5ff6c253964d062f045e93d2",
"Date": "2021-01-07T08:01:21.499Z",
"email": "b#test.com",
"password": "$2a$12$jmHUrTSPwjaVd0VEIpsGauExHNSukHRyWWiJt4UlEgeWLBo8GPDH.",
"__v": 2
}
],
"Likes": 1,
"Date": "2021-01-07T08:01:21.990Z",
"_id": "5ff6c283964d062f045e93d5",
"Title": "tttt",
"Author": "javid1",
"ISBN": "1",
"Review": "1",
"SelectedFile": "1",
"__v": 0
}
]

Related

MongoDB $lookup don't replace all of the other objects

I am trying to use the $lookup method to find users for this object. But when I use it, it replaces the other objects. The data that was outputed is this
"notifications": {
"author": [
{
"username": "UnusualAbsurd",
"status": "Michael Ohare",
"createdAt": "2022-03-08T14:02:53.728Z",
"id": "1",
"avatar": "https://avatars.dicebear.com/api/avataaars/UnusualAbsurd.png"
}
]
}
But what I expected was this
"notifications": [
"author": [
{
"username": "UnusualAbsurd",
"status": "Michael Ohare",
"createdAt": "2022-03-08T14:02:53.728Z",
"id": "1",
"avatar": "https://avatars.dicebear.com/api/avataaars/UnusualAbsurd.png"
}
],
"type": "REQUEST",
"value": "1"
]
How do I make it output the expected version?
This is my code right now
const data = await this.notificatioModel.aggregate([
{
$match: { author: id },
},
{
$project: { _id: 0, __v: 0 },
},
{
$lookup: {
from: 'users',
localField: 'notifications.author',
foreignField: 'id',
as: 'notifications.author',
pipeline: [
{
$project: { _id: 0, email: 0, password: 0 },
},
],
},
},
]);
This is my notification document
This is my user document

how to update embed document in mongoDB with mongoose

i have course model like
const courseSchema = new mongoose.Schema({
name:{
type: String,
required:[true,'course must have a name.'],
unique:true
},
duration :Number,
description :String,
imageCover :String,
images:Array,
price :Number,
curriculum:
[
{
week:Number,
description:String,
total:Number,
completed:Number,
progress:Number,
links:
[
{
name:String,
link:String,
img:String,
watched:{
type:Boolean,
default:false
}
}
]
}
],
tutors:[
{
type: mongoose.Schema.ObjectId,
ref:'user'
}
]
},
{
toJSON:{virtuals : true},
toObject:{virtuals : true}
});
i want to add new objects to links array in curriculum .client side will patch request with week object id , name and link ,inside update handler i am doing somthing like this.
const cour = await Course.findOneAndUpdate({"caricullum._id":req.params.w},
{$push:{name:req.body.name,link:req.body.link}},{
new : true,
});
w params contain curriculum week _id
{
"_id": {
"$oid": "6138abc106b3ad1d3477b3e2"
},
"images": [],
"tutors": [],
"name": "c/c++",
"duration": 8,
"price": 1299,
"imageCover": "cool_lion.jpg",
"description": "",
"curriculum": [
{
"_id": {
"$oid": "6138abc106b3ad1d3477b3e3"
},
"week": 1,
"description": "introduction to microcontroller and microprocesor",
"links": [
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e4"
},
"name": "introduction",
"link": "https://www.youtube.com/embed/d0e6ScoS3Sw"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e5"
},
"name": "difference between mc and mp",
"link": "https://www.youtube.com/embed/dcNk0urQsQM"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e6"
},
"name": "building with microcontroller vs boards(arduino uno)",
"link": "https://www.youtube.com/embed/IdEcm3GU7TM"
}
]
},
{
"_id": {
"$oid": "6138abc106b3ad1d3477b3e7"
},
"week": 2,
"description": "introduction to arduino uno",
"links": [
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e8"
},
"name": "introduction to arduino uno",
"link": "https://www.youtube.com/embed/BiCSW6QR6HA"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e9"
},
"name": "IO PINS",
"link": "https://www.youtube.com/embed/OZGMLOwHYf8"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3ea"
},
"name": "setting up arduno uno for programming",
"link": "https://www.youtube.com/embed/ELUF8m24sZo"
}
]
},
{
"_id": {
"$oid": "6138abc106b3ad1d3477b3eb"
},
"week": 3,
"description": "interfacing with different sensors",
"links": [
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3ec"
},
"name": "LED Blinking(OUTPUT)",
"link": "https://www.youtube.com/embed/dnPPoetX0uw"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3ed"
},
"name": "interfacing with button(INPUT)",
"link": "https://www.youtube.com/embed/58Ynhqmvzoc"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3ee"
},
"name": "16x2 LCD",
"link": "https://www.youtube.com/embed/Mr9FQKcrGpA"
}
]
}
],
"__v": 0
}
how to query for correct week document with req.params.w and push new document into links array
use arrayFilters
db.collection.update({},
{
$push: {
"curriculum.$[elem].links": {
link: "a",
name: "b",
whatched: "c"
}
}
},
{ new:true,
arrayFilters: [
{
"elem.week": 1
}
]
})
https://mongoplayground.net/p/nLV9UzbJlsc

How to change this response to simple array?

{
"success": true,
"message": "Result",
"data": [
{
"Here": [
{
"_id": "5ee97ee7f25d1c1482717bdf",
"email": "test1#test.io",
"profileImages": [],
"username": "test1",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location",
"firstName": "test1",
"lastName": "test1",
}
]
},
{
"Here": [
{
"_id": "5ee97ef2f25d1c1482717be1",
"email": "test2#test.io",
"profileImages": [],
"username": "test2",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location"
}
]
}
],
}
What I am expecting is this
{
"success": true,
"message": "Result",
data: [
{
"_id": "5ee97ee7f25d1c1482717bdf",
"email": "test1#test.io",
"profileImages": [],
"username": "test1",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location",
"firstName": "test1",
"lastName": "test1"},
{
"_id": "5ee97ef2f25d1c1482717be1",
"email": "test2#test.io",
"profileImages": [],
"username": "test2",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location"
}
]
}
Query I am using is for this response is below using aggregation in mongodb, lookup and project which is leading me to the some undesired response
db.collections.aggregate( [
{
$lookup: {
from: 'users',
as: 'Here',
let: {
whoDid: '$whoDid'
},
pipeline: [
{
"$match": { "$expr": { "$eq": ["$_id", "$$whoDid"] } }
},
{
$project: {
_id: 1,
email: 1,
profileImages: 1,
username: 1,
birthday: 1,
phoneNumber: 1,
firstName: 1,
lastName: 1,
fullName: 1,
// age: {$year: "$birthday"}
age: {
$divide: [{ $subtract: [new Date(), "$birthday"] },
(31558464000)]
}
}
}
],
}
},
{
$project:{
Here:1,
_id:0
}
} ,
])
who did table is one of the collection I have where I have stored the user Id and later I am populating the data using lookup
{
"_id" : ObjectId("5ee988eb1aac0022e15dbb7b"),
"whoDid" : ObjectId("5ee97ef2f25d1c1482717be1"),
"toWhomDid" : ObjectId("5ee97ec0f25d1c1482717bdd"),
"modified_at" : ISODate("2020-06-17T03:07:23.217Z"),
"created_at" : ISODate("2020-06-17T03:07:23.217Z"),
"__v" : 0
}
{
"_id" : ObjectId("5ee988eb1aac0022e15dbb7c"),
"whoDid" : ObjectId("5ee97ec0f25d1c1482717bdd"),
"toWhomDid" : ObjectId("5ee97ef2f25d1c1482717be1"),
"modified_at" : ISODate("2020-06-17T03:07:23.220Z"),
"created_at" : ISODate("2020-06-17T03:07:23.220Z"),
"__v" : 0
}
Can anyone suggest me any better option so that I can get a desired respose?
It is possible to use reduce method:
obj.data = obj.data.reduce((a, c) => {
a.push(...c.Here);
return a;
}, [])
An example:
let obj = {
"success": true,
"message": "Result",
"data": [ {
"Here": [ {
"_id": "5ee97ee7f25d1c1482717bdf", "email": "test1#test.io",
"profileImages": [], "username": "test1",
"birthday": "2020-06-11T10:11:32.000Z", "phoneNumber": "+910000000000", "location": "Test Location",
"firstName": "test1", "lastName": "test1",
}
]
},
{
"Here": [ {
"_id": "5ee97ef2f25d1c1482717be1",
"email": "test2#test.io",
"profileImages": [],
"username": "test2",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location"
}
]
}
]
};
obj.data = obj.data.reduce((a, c) => {
a.push(...c.Here);
return a;
}, [])
console.log(obj);
Add these extra steps into your aggregation pipeline:
{
$unwind: "$Here"
},
{
$replaceWith: "$Here"
}
MongoPlayground
Note: You can replace $project: { _id: 1, email: 1, ... to this:
{
$addFields:{
age: {
$divide: [{ $subtract: [new Date(), "$birthday"] },(31558464000)]
}
}
}

Populate data from another collection mongoose

I have 3 collections users, profiles and trustedcontacts. Profiles and trustedcontacts have ref to users
My db collections
I have collection users
{
"_id": {
"$oid": "5c5ecaf6134fc342d4b1a9d5"
},
"name": "User",
"email": "user#gmail.com",
"password": "$2a$10$BXxwpMTFK1a0aWclaqJYve4f3SZyi/emwHKv5rY2GNzrPSEsIJhzi",
},
{
"_id": {
"$oid": "5c64968cae53a8202c963223"
},
"name": "User1",
"email": "user1#gmail.com",
"password": "$2a$10$BXxwpMTFK1a0aWclaqJYve4f3SZyi/emwHKv5rY2GNzrPSEsIJhzi",
},
{
"_id": {
"$oid": "5c69968cae53a8202c963554"
},
"name": "User1",
"email": "user1#gmail.com",
"password": "$2a$10$BXxwpMTFK1a0aWclaqJYve4f3SZyi/emwHKv5rY2GNzrPSEsIJhzi",
}
collection profiles
{
"_id": {
"$oid": "5c5ecb17134fc342d4b1a9d6"
},
"user": {
"$oid": "5c5ecaf6134fc342d4b1a9d5"
},
"handle": "handle",
"company": "test"
},
{
"_id": {
"$oid": "5c6496ebae53a8202c963224"
},
"user": {
"$oid": "5c64968cae53a8202c963223"
},
"handle": "handle1",
"company": ""
},
{
"_id": {
"$oid": "5c6496ebae53a8202c963224"
},
"user": {
"$oid": "5c69968cae53a8202c963554"
},
"handle": "handle2",
"company": ""
}
collection trustedcontacts
{
"_id": {
"$oid": "5d76008e4b98e63e58cb34cc"
},
"approvedTrustedContacts": [
{
"_id": {
"$oid": "5d764e411b7476462cf6b540"
},
"user": {
"$oid": "5c5ecaf6134fc342d4b1a9d5"
}
},
{
"_id": {
"$oid": "5d764e411b7476462cf6b541"
},
"user": {
"$oid": "5c64968cae53a8202c963223"
}
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": {
"$oid": "5d76008e4b98e63e58cb34cb"
}
}
//My Schemas
const UserSchema = new mongoose.Schema({
name: {
type: String,
},
email: {
type: String,
}
});
export default mongoose.model('User', UserSchema);
const ProfileSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
handle: {
type: String,
},
company: {
type: String,
},
});
export default mongoose.model('Profile', ProfileSchema);
import mongoose from 'mongoose';
const TrustedContactsSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
approvedTrustedContacts: [
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
}
],
...
});
export default mongoose.model('TrustedContacts', TrustedContactsSchema);
I can populate trusted contact by user
const user = await TrustedContacts.findOne({ user: req.user.id }).populate('approvedTrustedContacts.user', ['name', 'email']);
and I got
"user": {
"date": "2019-09-09T07:32:20.174Z",
"_id": "5d76008e4b98e63e58cb34cc",
"approvedTrustedContacts": [
{
"_id": "5d764e411b7476462cf6b540",
"user": {
"_id": "5c5ecaf6134fc342d4b1a9d5",
"name": "User",
"email": "user#gmail.com",
}
},
{
"_id": "5d764e411b7476462cf6b541",
"user": {
"_id": "5c64968cae53a8202c963223",
"name": "User1",
"email": "user1#gmail.com",
}
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": "5d76008e4b98e63e58cb34cb",
}
Expected Output
It is possible to get list of approvedTrustedContacts with profile data
"approvedTrustedContacts": [
{
"_id": "5d764e411b7476462cf6b540",
"user": {
"_id": "5c5ecaf6134fc342d4b1a9d5",
"name": "User",
"email": "user#gmail.com",
},
"handle": "handle",
"company": "test"
},
{
"_id": "5d764e411b7476462cf6b541",
"user": {
"_id": "5c64968cae53a8202c963223",
"name": "User1",
"email": "user1#gmail.com",
},
"handle": "handle1",
"company": "test1"
}
],
Also I have joined 2 collections like this
let result1 = await TrustedContacts.aggregate([
{ $lookup: { from: "profiles", localField: "user", foreignField: "user", as: "approvedTrustedContacts" } },
]);
And I got
{
"_id": "5d76008e4b98e63e58cb34cc",
"approvedTrustedContacts": [
{
"_id": "5d764f551b7476462cf6b542",
"user": "5d76008e4b98e63e58cb34cb",
"handle": "handle",
"company": "test",
},
{
"_id": "5c5ecb17134fc342d4b1a9d6",
"user": "5c5ecaf6134fc342d4b1a9d5",
"handle": "handle1",
"company": "test1",
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": "5d76008e4b98e63e58cb34cb",
}
],
Now I don't know how to polute user to have an output like this:
{
"_id": "5d76008e4b98e63e58cb34cc",
"approvedTrustedContacts": [
{
"_id": "5d764f551b7476462cf6b542",
"user": {
"_id": "5c5ecaf6134fc342d4b1a9d5",
"name": "User",
"email": "user#gmail.com",
},
"handle": "handle"
"company": "test",
},
{
"_id": "5c5ecb17134fc342d4b1a9d6",
"user": {
"_id": "5c64968cae53a8202c963223",
"name": "User1",
"email": "user1#gmail.com",
},
"handle": "handle1",
"company": "test1",
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": "5d76008e4b98e63e58cb34cb",
}
],
My solution
let result = await TrustedContacts.aggregate([
{ $lookup: { from: "profiles", localField: "approvedTrustedContacts.user", foreignField: "user", as: "approvedTrustedContacts.profile" } },
{ $unwind: "$approvedTrustedContacts.profile" },
{ $lookup: { from: "users", localField: "approvedTrustedContacts.profile.user", foreignField: "_id", as: "approvedTrustedContacts.profile.user" } },
{ $unwind: "$approvedTrustedContacts.profile.user" },
{ $group :{
_id: "$_id",
"date": {"$first": "$date"},
"approvedTrustedContacts": {"$push": "$approvedTrustedContacts"},
}}
]);
As an output I have
{
"_id": "5d76008e4b98e63e58cb34cc",
"date": "2019-09-09T07:32:20.174Z",
"approvedTrustedContacts": [
{
"profile": {
"_id": "5c5ecb17134fc342d4b1a9d6",
"skills": [
"test"
],
"date": "2019-02-09T12:42:48.969Z",
"user": {
"_id": "5c5ecaf6134fc342d4b1a9d5",
"data": "2019-02-09T12:42:48.716Z",
"name": "User",
"email": "user#gmail.com",
},
"handle": "handle",
"company": "test",
}
},
{
"profile": {
"_id": "5c6496ebae53a8202c963224",
"skills": [
"qwqwqwqwqw"
],
"date": "2019-02-13T22:11:04.119Z",
"user": {
"_id": "5c64968cae53a8202c963223",
"data": "2019-02-13T22:11:03.807Z",
"name": "User1",
"email": "user1#gmail.com",
},
"handle": "handle1",
"company": "test1",
}
}
]
}
```

Get parent to child relation with mongodb aggregation

I have one collection called "location". in this collection all child and parent collection are stores. now I want to create a query who returns me parent to child comma separated string.
Collection
businessId: { type: mongoose.Schema.Types.ObjectId, ref: 'admin' },
parentId: { type: mongoose.Schema.Types.ObjectId, ref: 'location' },
name: { type: String },
image: { type: String },
imageManipulation: { type: String },
locationColor: [{ range: { type: String }, color: { type: String } }],
area: {},
settings: {},
status: { type: String, enum: [0, 1], default: 1 },
isChild: { type: String, enum: [0, 1] },
parentPosition: { type: String }
In the above collection, you can see parentId field. if the location is a child then it have parentId. if the location is a parent then parentId will null. parent location can N level child location.
Collection Data
[{
"_id": ObjectId("5ce4f84547e90a0b9c3c4763"),
"name": "Test",
"settings": {
"zoom": "3",
"positionX": "69",
"positionY": "69",
"width": "500",
"height": "334"
},
"parentId": null,
"image": "1558509637101.jpg",
"status": "0",
"businessId": ObjectId("5cbd61dc3b56b902284ea388"),
"locationColor": [],
"updatedAt": ISODate("2019-05-22T12:59:26.013Z"),
"createdAt": ISODate("2019-05-22T07:20:37.112Z"),
"__v": 0
},
{
"_id": ObjectId("5ce50caf09359e1b8ccf5c79"),
"name": "Test sub 1",
"settings": {
"zoom": "3",
"positionX": "48",
"positionY": "3",
"width": "500",
"height": "334"
},
"area": "",
"parentId": ObjectId("5ce4f84547e90a0b9c3c4763"),
"image": "1558514863396.jpg",
"status": "0",
"businessId": ObjectId("5cbd61dc3b56b902284ea388"),
"locationColor": [],
"updatedAt": ISODate("2019-05-22T12:59:21.883Z"),
"createdAt": ISODate("2019-05-22T08:47:43.421Z"),
"__v": 0
},
{
"_id": ObjectId("5ce53977e46da33e6cfdd9d1"),
"name": "Test Sub 2",
"settings": {
"zoom": "5",
"positionX": "0",
"positionY": "0",
"width": "500",
"height": "334"
},
"area": "",
"parentId": ObjectId("5ce50caf09359e1b8ccf5c79"),
"image": "1558526327126.jpg",
"businessId": ObjectId("5cbd61dc3b56b902284ea388"),
"locationColor": [],
"updatedAt": ISODate("2019-05-22T11:58:47.147Z"),
"createdAt": ISODate("2019-05-22T11:58:47.147Z"),
"__v": 0
}]
Expected Result
Test, Test sub 1, Test Sub 2
Expected result in JSON
[{
"_id": ObjectId("5ce4f84547e90a0b9c3c4763"),
"name": "Test",
},
{
"_id": ObjectId("5ce50caf09359e1b8ccf5c79"),
"name": "Test, Test sub 1",
},
{
"_id": ObjectId("5ce53977e46da33e6cfdd9d1"),
"name": "Test, Test sub 1, Test Sub 2",
}]
You basically need $graphLookup for recursive loop over the same collection.
db.location.aggregate([
{ "$graphLookup": {
"from": "location",
"startWith": "$parentId",
"connectFromField": "parentId",
"connectToField": "_id",
"as": "parent"
}},
{ "$project": {
"name": {
"$concat": [
"$name",
{ "$reduce": {
"input": "$parent",
"initialValue": "",
"in": { "$concat": [",", "$$this.name", "$$value"] }
}}
]
}
}}
])
Which will output
[
{
"_id": ObjectId("5ce4f84547e90a0b9c3c4763"),
"name": "Test"
},
{
"_id": ObjectId("5ce50caf09359e1b8ccf5c79"),
"name": "Test sub 1,Test"
},
{
"_id": ObjectId("5ce53977e46da33e6cfdd9d1"),
"name": "Test Sub 2,Test sub 1,Test"
}
]
MongoPlayground

Resources