Using ref in express js to make a relationship in mongodb - node.js

I have tried to make the relationship between two models in node js express app. I used the world ref to retrieve the user's names who created the courses however, when I create the course from the user after login or register, it does not show anything about the user who created that course. Instead, it shows an empty [] array. I want to show the user full name who created that course.
User's ref in the course model:
},
creator: [
{
ref: "Users",
type: mongoose.Schema.Types.ObjectId,
},
],
Here I am trying to get the user who created the course:
//Get all courses
exports.getAllCourses = async (req, res) => {
await Courses.find()
.sort("-created")
.populate("creator", "firstName lastName fullName")
.exec((err, courses) => {
if (err) {
res.status(500).send({ message: error.message });
} else {
res.status(200).send({
message: "All courses fetched successfully",
result: courses,
});
}
});
};
The result I am getting in postman:
{
"message": " All courses fetched successfully",
"result": [
{
"creator": [], <----- Here I am getting the user as an empty array
"_id": "606d0f4d6051bb308089b5d2",
"courseCode": "Math202",
"courseName": "Math linear algebra",
"section": "001",
"semester": 1,
"__v": 0
}

.populate({ path: 'creator', model: 'Users', select: 'firstName lastName fullName' });

Related

Id not getting removed from nested array

Hello I am trying to remove nested array object id from document but it is not getting removed. Although I am getting message "Deleted"
I have a response where the structure is :-
{
"admins": {
"users": [
"5d0364048db4957100f33fea" //<===want to delete this relational id
],
"email": "1cf1eede89#himail.online",
"password": "$2a$10$vHyGxX9P.t0/ybKcmIzkc.ZCX18oHaVnvTgJIWA2gTNzJ3TCdXS4a",
"_id": "5d0339d5b4b28b6ddff06802",
"companyName": "GH",
"__v": 0
}
I want to delete users _id from the array.
I tried this but it is not getting removed.
router.delete('/userDelete/:uId', checkAuth , (req, res, next) =>{
if(req.userData.role2 === 'admin') {
Admin.findOneAndUpdate({ _id: req.params.userId },{ $pull: { 'admins.users': req.params.uId}})
.exec()
.then(result => {
res.status(200).send(["Deleted"]);
})
.catch(err =>{
if (err.code == 500)
res.status(500).send(["Didn't get deleted"]);
else
return next(err);
});
Controller is like this :-
var admin = new Admin();
admin.companyName = req.body.companyName;
admin.admins = {
email : req.body.email,
password: req.body.password,
users : []
};
I am stuck here , what changes I must do in my route ?
EDIT:- DB is like this
The problem is here Admin.findOneAndUpdate({ _id: req.params.userId }
req.params.userId is undefined, because it does not exist in your path. req.params object holds only one property, uId.
So your query does not find any data.
req.params.userId would have value if your method route had a form like this router.delete('/userDelete/:userId/:uId).
So you could add userId in the url of your delete request and access it through req.params object. The new url should be like this
/userDelete/userId/uId
(e.g.)
userDelete/5d0339d5b4b28b6ddff06802/5d0364048db4957100f33fea
try to hard code your id here
Admin.findOneAndUpdate({ _id: req.params.userId },{ $pull: { 'admins.users': "5d0364048db4957100f33fea"}})
If it is working then do
req.params.uId.toString()
Try marking the '_id' as false in the schema itself for the array. For eg, in your schema, mark '_id' as false like below:
admin: {
type: Object,
users: [{
_id: false
}]
}
.
.
//rest of the schema

Find by a value in an object array

I can't make a query to all profiles that are included in a specific department.
I'm using nodejs with mongo and mongoose. An example of a Profile schema is the next:
Profile: {
"level": 1,
"departments": [
{
"_id": "5c5f3bb4338fde6c60a684d4",
"department": "5c106a324acd0571241323f2",
"name": "Calidad"
},
{
"_id": "5c5f3794eca3f14cd49e395e",
"department": "5c106bad99142733446a44f0",
"name": "Mantenimiento"
}
]
This below is the query I tried:
Profile.find({ departments: [{ department: req.params.id }] })
.then(profiles => res.json(profiles))
.catch(err =>
res.status(404).json({ nodepartmentfound: "No departments found" })
);
I expect to return tan array with all profiles with the specified department.
Try the following code:
Profile.find({ "departments.department": req.params.id })
.then(profiles => res.json(profiles))
.catch(err =>
res.status(404).json({ nodepartmentfound: "No departments found" })
);
Basically, what you want to do is query an array of embedded documents. Using the dot notation is enough to solve your problem. Relevant documentation can be found here.

mongoDb database form-data empty response

I am sending Rest POST Request(form-data) using postman to mongoDb. Even after providing all the key-value pairs in the Model, only the product _id gets stored into the database not other array of objects. Here's my model schema:
const mongoose = require('mongoose');
const productSchema = mongoose.Schema({
name: String,
price: Number,
editor1: String,
year: String,
quantity: Number,
subject: String,
newProduct: String,
relatedProduct: String,
//coverImage: { type: String, required: false }
});
module.exports = mongoose.model('Product', productSchema);
And here's my POST request for the products:
exports.products_create_product = (req, res, next) => {
const product = new Product(req.body);
product
.save()
.then(result => {
console.log(result);
res.status(201).json({
message: "Created product successfully",
createdProduct: {
name: result.name,
price: result.price,
_id: result._id,
request: {
type: "GET",
url: "http://localhost:3000/products/" + result._id
}
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
};
And this is my result output:
{
"message": "Created product successfully",
"createdProduct": {
"_id": "5b2df3420e8b7d1150f6f7f6",
"request": {
"type": "GET",
"url": "http://localhost:3000/products/5b2df3420e8b7d1150f6f7f6"
}
}
}
Tried every possible way to solve this but in vain.
try the callback
product.save((err,result) =>{
if(err){
res.status(500).json({
error: err
});
return false
}
res.status(201).json({
message: "Created product successfully",
createdProduct: {
name: result.name,
price: result.price,
_id: result._id,
request: {
type: "GET",
url: "http://localhost:3000/products/" + result._id
}
}
})
First let's try to understand why this happens ? ,
When you use .json() method inside this method it uses JSON.stringify() function what this function does is that take any JavaScript value and convert it to JSON string for example
let product = {
name : 'p1' ,
price : 200
}
console.log(JSON.stringify(product)); // {"name":"p1","price":200}
that's good , but you should know that if this function during the conversion see any undefined values it will be omitted ,
for example
let product = {
id:"23213214214214"
} // product doesn't have name property and its undefind
console.log(JSON.stringify({
id:product.id ,
name : product.name
})); // {"id":"23213214214214"}
if you look at the example above you'll see that because the value of name is **undefined ** you get a JSON output but only with the id value , and any value that is undefined will not be in the result .
that's the main reason why you get the result with only the product._id because other values like price and name are undefined .
so what to do to solve this problem ?
log the req.body and make sure that it has properties like name and price and I think this is the main reason of the problem because when you create the product variable it will only has the _id prop because other props are not exist .
after you create the product log it to the console and make sure that it has other properties like name and price
#mostafa yes I did tried.
{
"count": 3,
"products": [
{
"_id": "5b2e2d0cb70f5f0020e72cb6",
"request": {
"type": "GET",
"url": "https://aa-backend.herokuapp.com/products/5b2e2d0cb70f5f0020e72cb6"
}
},
{
"_id": "5b2e2d37b70f5f0020e72cb7",
"request": {
"type": "GET",
"url": "https://aa-backend.herokuapp.com/products/5b2e2d37b70f5f0020e72cb7"
}
},
{
this is the only output I am getting.

Cascade delete from array using Mongoose middleware remove hook

I am building a Node.js express RESTfull API using Mongodb and mongoose.
This is my schema:
var UserSchema = new mongo.Schema({
username: { type: String },
password: { type: String, min: 8 },
display_name: { type: String, min: 1 },
friends: { type: [String] }
});
UserSchema.post('remove', function(next){
console.log({ friends: this._id }); // to test if this gets reached (it does)
UserSchema.remove({ friends: this._id });
});
And this is the function that removes a User:
.delete(function(req, res) {
User.findById(req.params.user_id, function(err, user) {
if (err) {
res.status(500);
res.send(err);
} else {
if (user != null) {
user.remove();
res.json({ message: 'User successfully deleted' });
} else {
res.status(403);
res.json({ message: 'Could not find user.' });
res.send();
}
}
});
});
What I need to do is when a user is removed, his or her _id (String) should also be removed from all the other users' friends array. Hence the remove hook in the schema.
Right now the user gets deleted and the hook gets triggered, but the user _id is not removed from the friends array (tested with Postman):
[
{
"_id": "563155447e982194d02a4890",
"username": "admin",
"__v": 25,
"password": "adminpass",
"display_name": "admin",
"friends": [
"5633d1c02a8cd82f5c7c55d4"
]
},
{
"_id": "5633d1c02a8cd82f5c7c55d4",
"display_name": "Johnybruh",
"password": "donttouchjohnsstuff",
"username": "John stuff n things",
"__v": 0,
"friends": []
}
]
To this:
[
{
"_id": "563155447e982194d02a4890",
"username": "admin",
"__v": 25,
"password": "adminpass",
"display_name": "admin",
"friends": [
"5633d1c02a8cd82f5c7c55d4"
]
}
]
To try and figure it out I have looked at the Mongoosejs Documentation, but the mongoose doc example doesn't cover the remove hook. Also this stackoverflow qestion but this question seems to be about removing from other schemas.
I think i'm doing the remove in the hook wrong, but I can't seem to find the problem.
Thanks in advance!
EDIT:
I could not get the first suggestion by cmlndz to work, so I ended up fetching all the documents with arrays that contained the to-be-deleted users' id and pulling it from them one-by-one:
The delete function now contains this bit of code that does the magic:
// retrieve all documents that have this users' id in their friends lists
User.find({ friends: user._id }, function(err, friends) {
if (err) {
res.json({ warning: 'References not removed' });
} else {
// pull each reference to the deleted user one-by-one
friends.forEach(function(friend){
friend.friends.pull(user._id);
friend.save(function(err) {
if (err) {
res.json({ warning: 'Not all references removed' });
}
});
});
}
});
You could use $pull to find all documents that contain the "ID" in the "friends" array -or- find any matching document and popping the "ID" out of the array one by one.

Populating nested properties with Mongoose

In the API I'm trying to write with Node and Mongoose, the following query:
User.findOne({username: req.params.username}, "-_id -__v")
.populate({path: "songs", select: "-_id -__v"})
.populate({path: "following", select: "-_id username email"})
.exec(function(err, user) {
res.send(user);
});
returns the following JSON:
{
"email": "alice#alice.org",
"username": "alice",
"following": [
{
"username": "john",
"email": "john#john.org"
}
],
"songs": [
{
"slug": "dvorak-cello-concerto",
"artist": "5403e825cc9c45e9c55c4e7d",
"title": "Cello Concerto"
}
]
}
In the songs schema, I've setup artist as the following:
artist: {type: Schema.Types.ObjectId, ref: 'User'}
What is the best way to also populate the 'artist' property in every song that's populated in the initial query, rather than just its _id which references the user that song belongs to?
I figured out a way to do this, but please correct me if there's a better/cleaner way of doing it.
User.findOne({username: req.params.username}, "-_id -__v")
.populate({path: "songs", select: "-_id -__v"})
.exec(function(err, user) {
Songs.populate(user, {
path: 'songs.artist',
select: '-_id username',
model: 'User'
}, function (err, user) {
res.send(user);
});
});
Also, I'm only returning the 'username' value for the user which is all I need, but 'artist' still ends up being an object with that one property. If anybody knows how to return that value just as a string.
I'd love to know how.

Resources