Mongoose - Multi-level navigation - node.js

i'm new to MongoDB & Mongoose
I have data like this:
{
"_id": "5787009e494495e56d327417",
"title": "Hahaha",
"parent": null,
"depth": 0
},
{
"_id": "5787009e494495e56d327416",
"title": "Hihihi",
"parent": null,
"depth": 0
},
{
"_id": "5787009e494495e56d327415",
"title": "Huhuhu",
"parent": "5787009e494495e56d327417",
"depth": 1
}
How can I convert the data into this:
{
"_id": "5787009e494495e56d327417",
"title": "Hahaha",
"children": [
"_id": "5787009e494495e56d327415",
"title": "Huhuhu",
"children": []
]
},
{
"_id": "5787009e494495e56d327416",
"title": "Hihihi",
"children": []
}
Please help me, and sorry for my bad english !

There is no other way you have to traverse the result and create new Data in memory.
//for each item in the result {
if(item.parent !=null){
insert_item_in_tree(item);
}
//}
then build a data structure function to insert the one item appropriately as per parent id.

Related

Remove nested categories in mongo

I want when a category is deleted. All its child categories and its own categories will be deleted.
For example, I want if the web development category is deleted. All its child categories (delete Django and Django Channel)
{
"statusCode": 200,
"data": {
"categories": [
{
"_id": "62fdfb567bb46dcf93b3717f",
"title": "Web development",
"parent": null,
"position": "important",
"slug": "-eb-development",
"createdAt": "2022-08-18T08:41:58.826Z",
"updatedAt": "2022-08-18T08:41:58.826Z",
"children": [
{
"_id": "62fdfb677bb46dcf93b3718d",
"title": "Django",
"parent": "62fdfb567bb46dcf93b3717f",
"position": "unimportant",
"slug": "-jango",
"createdAt": "2022-08-18T08:42:15.557Z",
"updatedAt": "2022-08-18T08:42:15.557Z",
"children": [
{
"_id": "62fdfb857bb46dcf93b371a1",
"title": "Django chennels",
"parent": "62fdfb677bb46dcf93b3718d",
"position": "unimportant",
"slug": "-jango-chennels",
"createdAt": "2022-08-18T08:42:45.665Z",
"updatedAt": "2022-08-18T08:42:45.665Z",
"children": [],
"id": "62fdfb857bb46dcf93b371a1"
}
],
"id": "62fdfb677bb46dcf93b3718d"
}
],
"id": "62fdfb567bb46dcf93b3717f"
}
]
}
}
I wrote a code for this which does not work properly and removes only one child from the desired category.
const category = await this.checkExistCategory(id);
const deleteResult = await Category.deleteMany({
$or: [{ _id: category._id }, { parent: category._id }],
});
Thank you very much for helping me!!

How to get mongoose schema result properly with missing field in JSON

I am new to Node.js and mongoose. I have tried a lot of things but not able to get the result I want.
Can someone help who knows how, who has faced this problem before or knows the solution of that problem?
Below is my database screen where 3 records are insured like below.
I have written this code and it returns the result shown below:
router.get("/categoryFields", async (request, response) => {
const categories = await categoryModel.find({}).select("parentId title slug");
try {
response.send(categories);
} catch (error) {
response.status(500).send(error);
}
});
JSON result =>
[
{
"_id": "61779e5c1e4ed11e96301ccd",
"title": "Clothing",
"slug": "hello"
},
{
"_id": "61779e8d1e4ed11e96301ccf",
"parentId": "61779e5c1e4ed11e96301ccd",
"title": "Shoe",
"slug": ""
},
{
"_id": "6177c1cd6d3e170ae58c89c3",
"title": "Electric",
"slug": ""
}
]
But I need to get a result like this - I want parentID in every object:
[
{
"_id": "61779e5c1e4ed11e96301ccd",
"parentId": "",
"title": "Clothing",
"slug": "hello"
},
{
"_id": "61779e8d1e4ed11e96301ccf",
"parentId": "61779e5c1e4ed11e96301ccd",
"title": "Shoe",
"slug": ""
},
{
"_id": "6177c1cd6d3e170ae58c89c3",
"parentId": "",
"title": "Electric",
"slug": ""
}
]
Please can anyone help me how to do this in mongoose?
db.collection.find({},
{
"parentId": {
$cond: {
if: "$parentId",
then: "$parentId",
else: ""
}
},
"title": 1,
"slug": 1
})
Test Here

How to query nested object in mongodb

I'm new to mongodb and I've been trying to query this doc for awhile now.
Im trying to query all the rooms that have a room name of 100.
json
{
"count": 3,
"reviews": [
{
"_id": "5f9d42a0a8e71e004643f584",
"user": {
"_id": "5f7308cde0a4a7a66bc3d184",
"name": "Guest"
},
"room": {
"_id": "5f98f9321fd5bb0045b3d886",
"name": "100",
},
"rating": 4,
},
{
"_id": "5f9d431ea8e71e004643f585",
"user": {
"_id": "5f7308cde0a4a7a66bc3d184",
"name": "Guest",
},
"room": {
"_id": "5f98f9321fd5bb0045b3d886",
"name": "100",
},
"rating": 5,
},
{
"_id": "5f9e74fea6c06a0046d3cae2",
"user": {
"_id": "5f7308cde0a4a7a66bc3d184",
"name": "Guest",
},
"room": {
"_id": "5f98fa8b1fd5bb0045b3d88a",
"name": "300",
},
"rating": 5,
}
]}
what I've tried
1. find({},{"reviews.room.name": {$eq: "100"}}) // getting a projection error
2. find({"reviews.room.name": "100"}) // getting null
Any help to the right direction would be greatly appreciated.
Check out the docs about how to use find:
https://docs.mongodb.com/manual/reference/method/db.collection.find/
and try this
db.reviews.find({
"room.name": "100"
})
Here is the playground with your example: https://mongoplayground.net/p/dPfH5fSOePq
did u try this ? const response = await Room.find({name: "100"})

Flter mongodb database using mongoose nodejs

I need to filter some users according to some fixed criteria. I have a user collection and a talent collection. The talent collection holds the reference to a master category collection.
What I need is to filter these users according to the category in the talent collection and some keys from the user collection.
For example I need to search for a user whose gender is 'male' and education 'BTech' and will have talents as a programmer and tester
my user collection is like,
{
"_id": "5f1939239bd35429ac9cd78f",
"isOtpVerified": "false",
"role": "user",
"adminApproved": 1,
"status": 0,
"languages": "Malayalam, Tamil, Telugu, Kannada",
"name": "Test user",
"email": "test#email.com",
"phone": "1234567890",
"otp": "480623",
"uid": 100015,
"bio": "Short description from user",
"dob": "1951-09-07T00:00:00.000Z",
"gender": "Male",
"education": "Btech",
"bodyType": "",
"complexion": "",
"height": "",
"weight": "",
"requests": [],
"location": {
"place": "place",
"state": "state",
"country": "country"
},
"image": {
"avatar": "5f1939239bd35429ac9cd78f_avatar.jpeg",
"fullsize": "5f1939239bd35429ac9cd78f_fullsize.png",
"head_shot": "5f1939239bd35429ac9cd78f_head_shot.jpeg",
"left_profile": "5f1939239bd35429ac9cd78f_left_profile.png",
"right_profile": "5f1939239bd35429ac9cd78f_right_profile.png"
},
"__v": 42,
"createdAt": "2020-07-23T07:15:47.387Z",
"updatedAt": "2020-08-18T18:54:22.272Z",
}
Talent collection
[
{
"_id": "5f38efef179aca47a0089667",
"userId": "5f1939239bd35429ac9cd78f",
"level": "5",
"chars": {
"type": "Fresher",
},
"category": "5f19357b50bcf9158c6be572",
"media": [],
"createdAt": "2020-08-16T08:35:59.692Z",
"updatedAt": "2020-08-16T08:35:59.692Z",
"__v": 0
},
{
"_id": "5f3b7e6f7e322948ace30a2c",
"userId": "5f1939239bd35429ac9cd78f",
"level": "3",
"chars": {
"type": "Fresher",
},
"category": "5f19359250bcf9158c6be573",
"media": [
{
"adminApproved": 0,
"status": 0,
"_id": "5f3c22573065f84a48e04a14",
"file": "id=5f1939239bd35429ac9cd78f&dir=test&img=5f1939239bd35429ac9cd78f_image_undefined.jpeg",
"description": "test",
"fileType": "image",
"caption": "test file"
},
{
"adminApproved": 0,
"status": 0,
"_id": "5f3c2d7a8c7f8336b0bfced2",
"file": "id=5f1939239bd35429ac9cd78f&dir=test&img=5f1939239bd35429ac9cd78f_image_1.jpeg",
"description": "this is a demo poster for testing",
"fileType": "image",
"caption": "A Test Poster"
}
],
"createdAt": "2020-08-18T07:08:31.532Z",
"updatedAt": "2020-08-18T19:35:22.899Z",
"__v": 2
}
]
And the category in the above document is a separate one populated to this. the category collection as,
[
{
"_id": "5f19359250bcf9158c6be573",
"status": true,
"title": "Testing",
"description": "Application tester",
"code": "test",
"characteristics": [],
"createdAt": "2020-07-23T07:00:34.221Z",
"updatedAt": "2020-07-23T07:00:34.221Z",
"__v": 0
},
{
"status": true,
"_id": "5f29829a705b4e648c28bc88",
"title": "Designer",
"description": "UI UX Designer",
"code": "uiux",
"createdAt": "2020-08-04T15:45:30.125Z",
"updatedAt": "2020-08-04T15:45:30.125Z",
"__v": 0
},
{
"_id": "5f19357b50bcf9158c6be572",
"status": true,
"title": "programming",
"description": "Java programmer",
"code": "program",
"createdAt": "2020-07-23T07:00:11.137Z",
"updatedAt": "2020-07-23T07:00:11.137Z",
"__v": 0
}
]
So my filter terms will be;
{
categories: ["5f19359250bcf9158c6be573", "5f19357b50bcf9158c6be572"],
minAge: 18,
maxAge: 25,
minHeight: 5,
maxHeight: 6,
minWeight: 50,
maxWeight: 80,
complexion: "white",
gender: "male",
}
And the expected result will be a user have both the above talents and followed conditions,
{
users: { ..User details.. },
medias: { ...medias from the matching talents.. }
}
If there are two collections you need to join them either by primary key or _id with foriegn fields and you can use $lookup with $match to filter down.
Documentation
You need to use $lookup with pipeline,
$match you condition for category match
$lookup to join users collection
$match conditions for users collections fields
$match exclude documents that don't found matching users of criteria passed in conditions
db.talents.aggregate([
{
$match: {
category: { $in: ["5f19359250bcf9158c6be573", "5f19357b50bcf9158c6be572"] }
}
},
{
$lookup: {
from: "users",
as: "users",
let: { userId: "$userId" },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ["$$userId", "$_id"] },
{ $eq: ["$gender", "Male"] },
{ $eq: ["$education", "Btech"] }
// ... add you other match criteria here
]
}
}
}
]
}
},
{ $match: { users: { $ne: [] } } }
])
Playground

MongoDB create product summary collection

Say I have a product collection like this:
{
"_id": "5a74784a8145fa1368905373",
"name": "This is my first product",
"description": "This is the description of my first product",
"category": "34/73/80",
"condition": "New",
"images": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstproduct_image1.jpg"
},
...
],
"attributes": [
{
"name": "Material",
"value": "Synthetic"
},
...
],
"variation": {
"attributes": [
{
"name": "Color",
"values": ["Black", "White"]
},
{
"name": "Size",
"values": ["S", "M", "L"]
}
]
}
}
and a variation collection like this:
{
"_id": "5a748766f5eef50e10bc98a8",
"name": "color:black,size:s",
"productID": "5a74784a8145fa1368905373",
"condition": "New",
"price": 1000,
"sale": null,
"image": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstvariation_image1.jpg"
}
],
"attributes": [
{
"name": "Color",
"value": "Black"
},
{
"name": "Size",
"value": "S"
}
]
}
I want to keep the documents separate and for the purpose of easy browsing, searching and faceted search implementation, I want to fetch all the data in a single query but I don't want to do join in my application code.
I know it's achievable using a third collection called summary that might look like this:
{
"_id": "5a74875fa1368905373",
"name": "This is my first product",
"category": "34/73/80",
"condition": "New",
"price": 1000,
"sale": null,
"description": "This is the description of my first product",
"images": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstproduct_image1.jpg"
},
...
],
"attributes": [
{
"name": "Material",
"value": "Synthetic"
},
...
],
"variations": [
{
"condition": "New",
"price": 1000,
"sale": null,
"image": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstvariation_image.jpg"
}
],
"attributes": [
"color=black",
"size=s"
]
},
...
]
}
problem is, I don't know how to keep the summary collection in sync with the product and variation collection. I know it can be done using mongo-connector but i'm not sure how to implement it.
please help me, I'm still a beginner programmer.
you don't actually need to maintain a summary collection, its redundant to store product and variation summary in another collection
instead of you can use an aggregate pipeline $lookup to outer join product and variation using productID
aggregate pipeline
db.products.aggregate(
[
{
$lookup : {
from : "variation",
localField : "_id",
foreignField : "productID",
as : "variations"
}
}
]
).pretty()

Resources