How join nested object with another collection in mongoose? [duplicate] - node.js

This question already has answers here:
$lookup on ObjectId's in an array
(7 answers)
MongoDb aggregation $lookup with foreign _ids in arrays
(1 answer)
Closed 5 years ago.
I am a starter with mean stack, i want to nested object with another collection in mongoose, my product collection look as follows, it contain multiple bidders(users)
{
"_id": "5a16b3774d74d10ce0131254",
"name": "my test product",
"desc": "looking good",
"bid_amount": 120,
"bidders": [
{
"amount": "145",
"bid_status": "participated",
"user_id": "5a1b9f8c356e9d246c0443ac"
},
{
"amount": "160",
"bid_status": "rejected",
"user_id": "5a1be6c7356e9d246c0443af"
}
]
}
my user collection as follows
[
{
"_id": "5a1b9f8c356e9d246c0443ac",
"name": "abcd",
"email": "abcd#gmail.com"
},
{
"_id": "5a1be6c7356e9d246c0443af",
"name": "xyz",
"email": "xyz#gmail.com"
},
]
I need each user details corresponds to its object, not a separate object array, I am looking a result like this using mongoose
[
{
"_id": "5a16b3774d74d10ce0131254",
"name": "my test product",
"desc": "looking good",
"bid_amount": 120,
"bidders": [
{
"amount": "145",
"bid_status": "participated",
"user_id": "5a1b9f8c356e9d246c0443ac",
"user_details" : {
"_id": "5a1b9f8c356e9d246c0443ac",
"name": "abcd",
"email": "abcd#gmail.com"
}
},
{
"amount": "160",
"bid_status": "rejected",
"user_id": "5a1be6c7356e9d246c0443af",
"user_details": {
"_id": "5a1be6c7356e9d246c0443af",
"name": "xyz",
"email": "xyz#gmail.com"
}
}
}
]

Related

mongoose find multiple fileds then add array of object

I have the following mongoose collection
{
"_id": "5f494ca2d84e5d2ae800d5a4",
"email": "test#gmail.com",
"customer": [
{
"entries": [],
"payment": [],
"_id": "5f4950e7f4e0162c2c8af05f",
"name": "demo",
"mobile": 8877887788
},
{
"entries": [],
"payment": [],
"_id": "5f49514230dc8e3f0063f5e1",
"name": "demo2",
"mobile": 8877887788
},
{
"entries": [],
"payment": [],
"_id": "5f4956d92d83c03e68905fbb",
"name": "demo3",
"mobile": 8877887788
}
],
"createdAt": "2020-08-28T18:27:46.090Z",
"updatedAt": "2020-08-28T19:27:25.882Z",
"__v": 5
}
We have multiple users Above this is only 1 user schema
User have multiple Customers
Goal :-
Verify User -> Select particular Customer -> push entries Values in particular Customer
Find user by Email ID
then We have multiple Customers in this User so I want to find particular 1 Customer and target entries array .. and push value in entries Array
eg:- What i Want
{
"_id": "5f494ca2d84e5d2ae800d5a4",
"email": "test#gmail.com",
"customer": [
{
"entries": [
{ "amount" : 40 ,
"date" : "2020-08-28T19:27:25.882Z"
}
],
"payment": [],
"_id": "5f4950e7f4e0162c2c8af05f",
"name": "demo",
"mobile": 8877887788
},
{
"entries": [],
"payment": [],
"_id": "5f49514230dc8e3f0063f5e1",
"name": "demo2",
"mobile": 8877887788
},
{
"entries": [],
"payment": [],
"_id": "5f4956d92d83c03e68905fbb",
"name": "demo3",
"mobile": 8877887788
}
],
"createdAt": "2020-08-28T18:27:46.090Z",
"updatedAt": "2020-08-28T19:27:25.882Z",
"__v": 5
}
So I would use mongoose find by id to find the user then for each through the customer array, then save your changes.
db.<collectionName>.findById(id).then((collection) => {
collection.customer.forEach((customer, index) => {
if (customer._id === custId) {
collection.customer[index] = { ...collection.customer[index], quantity: newQuantity }
};
});
db.<collectionName>.findByIdAndUpdate(id, collection);
});
Something like that.

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

Populating all items from ref model [duplicate]

This question already has answers here:
$lookup multiple levels without $unwind?
(1 answer)
Mongoose: deep population (populate a populated field)
(10 answers)
Closed 3 years ago.
I have a database structured like this:
I want to get all listItems, of all lists from a user with a x ID. What's the correct way of doing that?
I'm using node with mongoose, and I tried the following:
await User.findById(user._id).populate('list');
But realized that I can't populate all ListItem's from that. Meaning, I can't do this:
await User.findById(user._id).populate('list').populate('listItem');
How can I get all listItems, of all lists from a user with a x ID?
Assuming User, List, and ListItem are Collections, you should be able to accomplish this using $lookup..
Here is a live demo of the following query..
Query:
db.users.aggregate([
{
$match: {
uniqueId: 1
}
},
{
$lookup: {
from: "lists",
localField: "uniqueId",
foreignField: "userId",
as: "lists"
}
},
{
$lookup: {
from: "listItems",
localField: "uniqueId",
foreignField: "userId",
as: "listItems"
}
}
])
Dataset:
db={ // Simulates a DB ********
"users": [ // Simulates a Collection ********
{
"firstname": "John",
"lastname": "Smith",
"email": "jsmith#gmail.com",
"password": "password123",
"uniqueId": 1
},
{
"firstname": "Jane",
"lastname": "Doe",
"email": "doe#yahoo.com",
"password": "123password",
"uniqueId": 2
}
],
"lists": [ // Simulates a Collection ********
{
"userId": 1,
"name": "Johns List 1",
"items": [
11,
12,
13
]
},
{
"userId": 2,
"name": "Groceries",
"items": [
21,
22,
23
]
}
],
"listItems": [ // Simulates a Collection ********
{
"userId": 2,
"itemId": 21,
"title": "Apple",
"notes": []
},
{
"userId": 2,
"itemId": 22,
"title": "Banana",
"notes": []
},
{
"userId": 2,
"itemId": 23,
"title": "Strawberry",
"notes": []
},
{
"userId": 1,
"itemId": 11,
"title": "Oil Change",
"notes": []
},
{
"userId": 1,
"itemId": 12,
"title": "Pick Up Grandma",
"notes": []
},
{
"userId": 1,
"itemId": 13,
"title": "Go For Run",
"notes": []
}
]
}
Result:
[
{
"_id": ObjectId("5a934e000102030405000008"),
"email": "jsmith#gmail.com",
"firstname": "John",
"lastname": "Smith",
"listItems": [
{
"_id": ObjectId("5a934e000102030405000003"),
"itemId": 11,
"notes": [],
"title": "Oil Change",
"userId": 1
},
{
"_id": ObjectId("5a934e000102030405000004"),
"itemId": 12,
"notes": [],
"title": "Pick Up Grandma",
"userId": 1
},
{
"_id": ObjectId("5a934e000102030405000005"),
"itemId": 13,
"notes": [],
"title": "Go For Run",
"userId": 1
}
],
"lists": [
{
"_id": ObjectId("5a934e000102030405000006"),
"items": [
11,
12,
13
],
"name": "Johns List 1",
"userId": 1
}
],
"password": "password123",
"uniqueId": 1
}
]

Mongoose - Multi-level navigation

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.

Mongoose find anywhere inside document

i need to find record matching userId. the userId can be in any level of document.
It can be in parent level or it can be inside friends array.
[{
"_id": "543357620c9af6066e689713",
"createdDate": "2014-10-06 08:00 pm",
"cancle": false,
"eventDate": "2014/12/12",
"eventstatus": true,
"location": "chennai",
"userId": "54334def7e85de48638d1069",
"createdBy": "four",
"eventName": "jamba",
"__v": 0,
"friends": []
},
{
"_id": "543356fe0c9af6066e68970c",
"createdDate": "2014-10-06 07:59 pm",
"cancle": false,
"eventDate": "2014/12/12",
"eventstatus": true,
"location": "chennai",
"userId": "54310801e2659ecc3650100b",
"createdBy": "one",
"eventName": "tea ",
"__v": 0,
"friends": [
{
"userId": "54310814e2659ecc3650100c",
"userName": "two",
"phoneNumber": "22222222"
},
{
"userId": "54310945e2659ecc3650100d",
"userName": "three",
"phoneNumber": "33333333"
},
{
"userId": "54334def7e85de48638d1069",
"userName": "four",
"phoneNumber": "44444444"
}
]
}]
i am trying for long time. Any help is highly appreciated.
You need the $or operator. Also, you don't need to iterate to query for elements within an array. Assuming your collection is named Events:
Events.find({
$or: [
{ _id: req.params.userId },
{ 'friends.userId': req.params.userId }
]
}).exec();

Resources