I have below collection:
[{
"_id": "60035d0a1599912a5c814e58",
"idUsuario": "600365521599912a5c814e5e",
"parentNode": "",
"piernaPadre": "",
"estado": "1"
},
{
"_id": "6003827b06b4423c9ca7e6aa",
"idUsuario": "60036e53dda7df34749ebf3a",
"parentNode": "60035d0a1599912a5c814e58",
"piernaPadre": "d",
"estado": 1
},
{
"_id": "60038c92ea7d593fe029cc0f",
"idUsuario": "600382a506b4423c9ca7e6ab",
"parentNode": "6003827b06b4423c9ca7e6aa",
"piernaPadre": "d",
"estado": 1
}]
I need to get the descendants of a node, I'm trying with $graphLookup,
$graphLookup: {
from: "nodoModel",
startWith: "$_id",
connectFromField: "_id",
connectToField: "parentNode",
as: "arrayDes"
}
but does not work, the return is void. Is there a mistake?
Thanks.
EDIT 1
Now I can get a result when try to get de ancestors of a node:
$graphLookup: {
from: "nodos",
startWith: "$_id",
connectFromField: "_id",
connectToField: "nodoPadre",
as: "padre"
}
Whit below result:
[
{
_id: 60035d0a1599912a5c814e58,
idUsuario: '600365521599912a5c814e5e',
parentNode: '',
piernaPadre: '',
estado: '1',
padre: [ [Object] ]
},
{
_id: 6004589436a40941f48121f8,
idUsuario: '600365e9ccf1e51b2cab341f',
parentNode: '60035d0a1599912a5c814e58',
piernaPadre: 'd',
estado: 1,
createdAt: 2021-01-17T15:32:36.986Z,
updatedAt: 2021-01-17T15:32:36.986Z,
__v: 0,
padre: [ [Object] ]
},
{
_id: 6004592936a40941f48121fa,
idUsuario: '6004591536a40941f48121f9',
parentNode: '6004589436a40941f48121f8',
piernaPadre: 'd',
estado: 1,
createdAt: 2021-01-17T15:35:05.626Z,
updatedAt: 2021-01-17T15:35:05.626Z,
__v: 0,
padre: [ [Object] ]
}
]
But I need to get the descendants not the ancestors
EDIT 2
(in the original model parentNode is named nodoPadre)
It is a screenshot of my code:
and that is the console.log:
arrayDes is a void array. I'm using mongoose, maybe it is related with the problem?
EDIT 3
I'm trying to change type of nodoPadre to objectId
Try query to get descendants,
$match put condition
$grouphLookup same as yours
{ $match: { nodoPadre: "" } },
{
$graphLookup: {
from: "collection",
startWith: "$_id",
connectFromField: "_id",
connectToField: "nodoPadre",
as: "arrayDes"
}
}
Playground
For your Second Edit:
Update nodoPadre type to object id type in all documents, and change type in schema to type: mongoose.Types.ObjectId
nodoPadre: {
type: mongoose.Types.ObjectId,
required: [false, '2'],
index: true
}
I had the same issue and finally I resolved it by chnaging the collection name to small letters and it should be plural based on mongodb . Here is my details
Mongoose schema:
const fileFolderSchema = new Schema({
name: String,
parentFolder: {type: Mongoose.Types.ObjectId, ref: "FileFolder"},
path: String,
metadata: {
type: metaDataSchema
}
}, { id: false }).set('toJSON', {
virtuals: true
});
export const FileFolder = Mongoose.model('FileFolder', fileFolderSchema);
Nodejs Method:
folder_tree_structure: async(ctx:any) => {
try {
let treeStructure = await FileFolder.aggregate([
{
$match: {
parentFolder: {
$exists: true
}
}
},
{
$graphLookup: {
from: 'filefolders', // here your collection name is always small letters and plural
startWith: '$_id',
connectFromField: 'parentFolder',
connectToField: 'parentFolder',
maxDepth: 1,
depthField: 'depth',
as: 'TreeResult'
}
}
]);
console.log('tree structure',treeStructure )
ctx.status = 200;
ctx.body = treeStructure;
} catch (err) {
ctx.status = 400;
ctx.body = 'Not found'
}
}
My Nodejs response:
[
{
"_id": "636cd1d2692344da47f3e2f0",
"name": "Folder2",
"path": "files/Folder2",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T10:26:26.828Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd213692344da47f3e2f5",
"TreeResult": [
{
"_id": "636cd238692344da47f3e301",
"name": "Folder3",
"path": "files/Folder3",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T10:28:08.655Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd1d2692344da47f3e2f0",
"depth": 0
},
{
"_id": "636d075874867ade3d3c3224",
"name": "images",
"path": "files/images",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T14:14:48.871Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd1d2692344da47f3e2f0",
"depth": 0
}
]
},
{
"_id": "636cd213692344da47f3e2f5",
"name": "Folder1",
"path": "files/Folder1",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T10:27:31.600Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd213692344da47f3e2f5",
"TreeResult": [
{
"_id": "636cd213692344da47f3e2f5",
"name": "Folder1",
"path": "files/Folder1",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T10:27:31.600Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd213692344da47f3e2f5",
"depth": 0
},
{
"_id": "636cd1d2692344da47f3e2f0",
"name": "Folder2",
"path": "files/Folder2",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T10:26:26.828Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd213692344da47f3e2f5",
"depth": 0
},
{
"_id": "636ce2452e97522606b14b23",
"name": "images",
"path": "files/images",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T11:36:37.691Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd213692344da47f3e2f5",
"depth": 0
}
]
},
{
"_id": "636cd238692344da47f3e301",
"name": "Folder3",
"path": "files/Folder3",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T10:28:08.655Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd1d2692344da47f3e2f0",
"TreeResult": []
},
{
"_id": "636ce2452e97522606b14b23",
"name": "images",
"path": "files/images",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T11:36:37.691Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd213692344da47f3e2f5",
"TreeResult": []
},
{
"_id": "636d075874867ade3d3c3224",
"name": "images",
"path": "files/images",
"metadata": {
"version": 1,
"created_by": "user-1",
"created_on": "2022-11-10T14:14:48.871Z",
"timeout": -1
},
"__v": 0,
"parentFolder": "636cd1d2692344da47f3e2f0",
"TreeResult": []
}
]
Here is mongo play ground link:
https://mongoplayground.net/p/M4pEB34Ozib
Related
I have an product option schema where I have chield material and add-on type
Product_options
const productOptionsSchema = new mongoose.Schema({
category: [{
value: { type: String },
display: { type: Number },
display_order: { type: String },
categoryImage: { type: String },
parent_id: { type: mongoose.Schema.Types.ObjectId },
parent_name: { type: String }
}],
material: [{
value: { type: String },
display: { type: Number },
display_order: { type: String },
price: { type: String }
}],
addon_type: [{
// addon_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'AddOnDetails'
// }
}],
design: [{
// design_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'DesignDetails'
// }
}]
}, {
timestamps: true
})
const Product_options = mongoose.model('Product_options', productOptionsSchema)
i want to add one more key 'isChildExist' if have any chield of category have parent_id == parent_id . my node js code is
const cat = await Product_options.aggregate( [
{
$unwind: {
path: "$category",
preserveNullAndEmptyArrays: true
}
},
{
$lookup: {
from: 'Product_options.category',
localField: '_id',
foreignField: 'parent_id',
as: 'category.isChildExist'
}
},
{
"$project": {
"_id": 0,
"category": 1,
}
}
] );
res.json({
msg: 'Success!',
cat
})
my current response is whenre isChildExist is blank :
{
"msg": "Success!",
"cat": [
{
"category": {
"value": "Rudraksha",
"display": 1,
"display_order": "",
"categoryImage": "",
"parent_id": null,
"parent_name": null,
"_id": "63aeac69f969cf78856b7db9",
"isChildExist": []
}
},
{
"category": {
"value": "Bead Bracelet",
"display": 1,
"display_order": "",
"categoryImage": "",
"parent_id": null,
"parent_name": null,
"_id": "63aeae05f969cf78856b80b2",
"isChildExist": []
}
},
{
"category": {
"value": "Gemstones",
"display": 1,
"display_order": "1",
"categoryImage": "",
"parent_id": null,
"parent_name": null,
"_id": "63aeb968f969cf78856b8cd9",
"isChildExist": []
}
},
{
"category": {
"value": "Natural Yellow Sapphire - Pukhraj ",
"display": 1,
"display_order": "1",
"categoryImage": "",
"parent_id": "63aeb968f969cf78856b8cd9",
"parent_name": "Gemstones",
"_id": "63aec39bf969cf78856bb9c3",
"isChildExist": []
}
},
{
"category": {
"value": "Natural Blue Sapphire - Neelam",
"display": 1,
"display_order": "1",
"categoryImage": "",
"parent_id": "63aeb968f969cf78856b8cd9",
"parent_name": "Gemstones",
"_id": "63aebe42f969cf78856b9fae",
"isChildExist": []
}
},
{
"category": {
"value": "Natural Ruby - Manik ",
"display": 1,
"display_order": "",
"categoryImage": "",
"parent_id": "63aeb968f969cf78856b8cd9",
"parent_name": "Gemstones",
"_id": "63aebe54f969cf78856b9fd9",
"isChildExist": []
}
},
{
"category": {
"value": "Natural Hessonite - Gomed",
"display": 1,
"display_order": "",
"categoryImage": "",
"parent_id": "63aeb968f969cf78856b8cd9",
"parent_name": "Gemstones",
"_id": "63aebe83f969cf78856ba076",
"isChildExist": []
}
},
{
"category": {
"value": "Natural Coral - Moonga ",
"display": 1,
"display_order": "",
"categoryImage": "",
"parent_id": "63aeb968f969cf78856b8cd9",
"parent_name": "Gemstones",
"_id": "63aebe9ff969cf78856ba0a8",
"isChildExist": []
}
},
{
"category": {
"value": "Natural Emerald - Panna ",
"display": 1,
"display_order": "",
"categoryImage": "",
"parent_id": "63aeb968f969cf78856b8cd9",
"parent_name": "Gemstones",
"_id": "63aebeb5f969cf78856ba0de",
"isChildExist": []
}
}
]
}
i expect isChildExist have data in gemstone but current is blank array
{
"category": {
"value": "Gemstones",
"display": 1,
"display_order": "1",
"categoryImage": "",
"parent_id": null,
"parent_name": null,
"_id": "63aeb968f969cf78856b8cd9",
"isChildExist": [
{
"value": "Natural Yellow Sapphire - Pukhraj ",
"display": 1,
"display_order": "1",
"categoryImage": "",
"parent_id": "63aeb968f969cf78856b8cd9",
"parent_name": "Gemstones",
"_id": "63aec39bf969cf78856bb9c3",
"child": []
},{
"value": "Natural Blue Sapphire - Neelam",
"display": 1,
"display_order": "1",
"categoryImage": "",
"parent_id": "63aeb968f969cf78856b8cd9",
"parent_name": "Gemstones",
"_id": "63aebe42f969cf78856b9fae",
"child": []
}
]
}
},
Problem is in $lookup
Try this code:
const cat = await Product_options.aggregate([{
$unwind: {
path: "$category",
preserveNullAndEmptyArrays: true
}
},
{
$lookup: {
from: 'Product_options',
let: {
category_id: "$category._id"
},
pipeline: [{
$match: {
$expr: {
$and: [{
$eq: ["$category.parent_id", "$$category_id"]
}, ]
}
}
},
{
$project: {
_id: 0,
category: 1,
}
}
],
as: "category.isChildExist"
}
},
{
$project: {
_id: 0,
category: 1
}
}
]);
I'm new to mongoose, I'm confuse while create the query. Can you help me?
I have a movie document like this :
"movies": [
{
"id": "635611395a71beb6c5bf0b4d",
"title": "Mission: Impossible - Fallout",
"createdAt": "2022-10-24T04:14:54.445Z",
"cast": [
{
"actor": "635350c581d5b60383f0c4be",
"roleAs": "Ethan Hunt",
"leadActor": true,
"_id": "635658c18b9e50facd7f1fd1"
},
{
"actor": "63560bf55a71beb6c5bf0b1f",
"roleAs": "Ilsa Faust",
"leadActor": false,
"_id": "635658c18b9e50facd7f1fd2"
}
],
"poster": {
"url": "https://res.cloudinary.com/debfn35m1/image/upload/v1666603204/vczxb7lgbonjn8ydsyep.jpg",
"public_id": "vczxb7lgbonjn8ydsyep",
"responsive": [
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_640/v1666603204/vczxb7lgbonjn8ydsyep.jpg",
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_50/v1666603204/vczxb7lgbonjn8ydsyep.jpg"
]
},
"reviews": {
"ratingAvg": "5.0",
"reviewCount": 2
}
},
{
"id": "635614855a71beb6c5bf0bdc",
"title": "Spider-Man: No Way Home",
"createdAt": "2022-10-24T04:28:58.286Z",
"cast": [
{
"actor": "635350a881d5b60383f0c4b8",
"roleAs": "Peter Parker",
"leadActor": true,
"_id": "636a2d6520cf4cf14a11ef95"
},
{
"actor": "635611eb5a71beb6c5bf0b99",
"roleAs": "MJ",
"leadActor": false,
"_id": "636a2d6520cf4cf14a11ef96"
}
],
"poster": {
"url": "https://res.cloudinary.com/debfn35m1/image/upload/v1667902823/tajzr9hpulvzqoytgpxu.jpg",
"public_id": "tajzr9hpulvzqoytgpxu",
"responsive": [
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_640/v1667902823/tajzr9hpulvzqoytgpxu.jpg",
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_470/v1667902823/tajzr9hpulvzqoytgpxu.jpg",
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_50/v1667902823/tajzr9hpulvzqoytgpxu.jpg"
]
},
"reviews": {
"ratingAvg": "8.0",
"reviewCount": 2
}
},
This is my desired result:
{
"id": "635611395a71beb6c5bf0b4d",
"title": "Mission: Impossible - Fallout",
"createdAt": "2022-10-24T04:14:54.445Z",
"cast": [
{
"actor": "635350c581d5b60383f0c4be",
"roleAs": "Ethan Hunt",
"leadActor": true,
"_id": "635658c18b9e50facd7f1fd1"
},
{
"actor": "63560bf55a71beb6c5bf0b1f",
"roleAs": "Ilsa Faust",
"leadActor": false,
"_id": "635658c18b9e50facd7f1fd2"
}
],
"poster": {
"url": "https://res.cloudinary.com/debfn35m1/image/upload/v1666603204/vczxb7lgbonjn8ydsyep.jpg",
"public_id": "vczxb7lgbonjn8ydsyep",
"responsive": [
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_640/v1666603204/vczxb7lgbonjn8ydsyep.jpg",
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_50/v1666603204/vczxb7lgbonjn8ydsyep.jpg"
]
},
"reviews": {
"ratingAvg": "5.0",
"reviewCount": 2
}
},
Im trying to write a filter function to get all movie that has Tom Cruise with actorId as a parameter but cannot get the result.
Can someone please help me with this ?
Since your actor id is inside a cast array with key actor you must specify your key while match, check the updated code below
exports.actorAggregation = (actorId) => {
return [
{
$lookup: {
from: "Movie",
localField: "cast",
foreignField: "_id",
as: "actorFilter",
},
},
{ $unwind: "$cast" },
{
$match: {
"cast.actor._id": { $in: [actorId] }, // or "cast.actor": { $in: [actorId] },
status: { $eq: "public" },
},
},
{
$project: {
title: 1,
poster: "$poster.url",
responsivePosters: "$poster.responsive",
createdAt: "$createdAt",
},
},
];
};
I have a list of records and want to group by categories and after this count buy isArchived status.
I'm just starting to learn MongoDB and I can't do the query described below, I would appreciate your tips.
This is peace of data.
[
{
"_id": "63356af2d77a56d764f362e4",
"noteName": "string",
"category": "IDEA",
"content": "string",
"isArchived": true,
"createdAt": "2022-09-29T09:52:50.477Z",
"updatedAt": "2022-09-29T09:52:50.477Z",
"__v": 0
},
{
"_id": "63356afad77a56d764f362ea",
"noteName": "string",
"category": "IDEA",
"content": "string",
"isArchived": false,
"createdAt": "2022-09-29T09:52:58.765Z",
"updatedAt": "2022-09-29T09:52:58.765Z",
"__v": 0
},
{
"_id": "63356afbd77a56d764f362ee",
"noteName": "string",
"category": "IDEA",
"content": "string",
"isArchived": false,
"createdAt": "2022-09-29T09:52:59.180Z",
"updatedAt": "2022-09-29T09:52:59.180Z",
"__v": 0
},
{
"_id": "63356b04d77a56d764f362f4",
"noteName": "string",
"category": "TASK",
"content": "string",
"isArchived": false,
"createdAt": "2022-09-29T09:53:08.261Z",
"updatedAt": "2022-09-29T09:53:08.261Z",
"__v": 0
},
{
"_id": "63356b09d77a56d764f362fc",
"noteName": "string",
"category": "TASK",
"content": "string",
"isArchived": true,
"createdAt": "2022-09-29T09:53:13.980Z",
"updatedAt": "2022-09-29T09:53:13.980Z",
"__v": 0
},
{
"_id": "63356b0ad77a56d764f362fe",
"noteName": "string",
"category": "TASK",
"content": "string",
"isArchived": true,
"createdAt": "2022-09-29T09:53:14.445Z",
"updatedAt": "2022-09-29T09:53:14.445Z",
"__v": 0
}]
This is request
getStats() {
const stats = this.noteModel
.aggregate([
{
$group: {
_id: {
category: '$category',
isArchived: '$isArchived',
},
count: {
$sum: 1,
},
},
},
{ $sort: { _id: 1 } },
])
.project({
_id: 0,
category: '$_id.category',
isArchived: '$_id.isArchived',
average: 1,
count: '$count',
});
return stats;
}
Now I receive like this
[
{
"category": "IDEA",
"isArchived": false,
"count": 5
},
{
"category": "IDEA",
"isArchived": true,
"count": 3
},
{
"category": "QUOTE",
"isArchived": false,
"count": 4
},
{
"category": "QUOTE",
"isArchived": true,
"count": 3
},
{
"category": "RANDOM THOUGHT",
"isArchived": false,
"count": 2
},
{
"category": "RANDOM THOUGHT",
"isArchived": true,
"count": 3
}....
]
But I want to receive it like this
[
{
"category": "IDEA",
"archived": 5,
"unArchived": 3
},
{
"category": "QUOTE",
"archived": 5,
"unArchived": 3
},
{
"category": "RANDOM THOUGHT",
"archived": 2,
"unArchived": 3
},
{
"category": "TASK",
"archived": 3,
"unArchived": 3
},
]
What should be changed in the query to get the required view?
Group by category only and calculate the archived and unArchived counts by checking the condition,
archived condition is if isArchived is true then return 1 otherwise 0
unArchived condition is if isArchived is true then return 0 otherwise 1
const stats = this.noteModel.aggregate([
{
$group: {
_id: "$category",
archived: {
$sum: { $cond: ["$isArchived", 1, 0] }
},
unArchived: {
$sum: { $cond: ["$isArchived", 0, 1] }
}
}
},
{ $sort: { _id: 1 } }
])
Playground
I want data from places where userid is equal to the body.user._id
PLACE DATA
{
"_id": "5e8ddd0f7f5b174290bbefc8",
"type": 0,
"location": [
24.8757396,
67.3464698
],
"title": "E 22, Steel Town Karachi, Karachi City, Sindh, Pakistan",
"googlePlaceId": "ChIJlbvA8BIzsz4Rlh7w_fKfwus",
"createdDate": "2020-04-08T14:17:51.869Z",
"__v": 0,
},
{
"_id": "5e8de4204396310017564a2b",
"type": 0,
"location": [
24.910688,
67.0310973
],
"title": "Nazimabad, Karachi, Pakistan",
"googlePlaceId": "ChIJzZudRr0_sz4R81KZ48Ylk3Q",
"createdDate": "2020-04-08T14:48:00.557Z",
"__v": 0,
},
{
"_id": "5e8de4364396310017564a2d",
"type": 0,
"location": [
24.9180271,
67.0970916
],
"title": "Gulshan-e-Iqbal, Karachi, Pakistan",
"googlePlaceId": "ChIJsda_CLg4sz4RIghXwgIae5k",
"createdDate": "2020-04-08T14:48:22.979Z",
"__v": 0,
},
{
"_id": "5e8dea79894854524cc554e0",
"type": 0,
"location": [
24.9343322,
67.177173
],
"title": "Malir Cantt Check Post No 6, Malir Link to Super Highway, Karachi, Pakistan",
"googlePlaceId": "ChIJJ7BbsyQ4sz4RvpkV9Ig_aU4",
"createdDate": "2020-04-08T15:15:05.360Z",
"__v": 0,
}**
Visited Places DATA
{
"_id":"5e90998f8bc84d0017a6d2f3",
"visitingNo":"0",
"_userId":"5e8f3ef5434f5800170c7169"
"_placeId":"5e908fdb8bc84d0017a6d2e8"
"createdDate":"2020-04-10T16:06:39.231+00:00"
"__v":"0"
},
{
"_id":"5e90998f8bc84d0017a6d2f3",
"visitingNo":"0",
"_userId":"5e8f3ef5434f5800170c7169"
"_placeId":"5e908fdb8bc84d0017a6d2e8"
"createdDate":"2020-04-10T16:06:39.231+00:00"
"__v":"0"
},
{
"_id":"5e90998f8bc84d0017a6d2f3",
"visitingNo":"0",
"_userId":"5e8f3ef5434f5800170c7169"
"_placeId":"5e908fdb8bc84d0017a6d2e8"
"createdDate":"2020-04-10T16:06:39.231+00:00"
"__v":"0"
},
MY CODE
const palace = placeData.aggregate([
{
$lookup:{
from: `${visitplaceData}`,
// localField: "_id",
// foreignField: "_placeId",
let : {
"placeId" : "$_id"
},
pipeline : [
{ $sort: { visitingNo : -1 } },
{
$match : {
$expr : {
$and : [
{$eq: [ "$_placeId", "$$placeId" ]},
{"_userId": body.user._id}
]
}
}
},
],
as: "places"
}
}
])
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