Mongoose update subarray item - node.js

I'm trying to update sub-array item in my collection , i'm trying to use set but can't get it work with _id , it only work when I say array[0] ...
Here is my method :
exports.updateSubCategory = (req, res) => {
const category = req.category;
Category.findById(category._id, function (err, doc) {
if (err) {
return res.status(400).json({
error: "Can't Find parent category",
});
} else {
doc.subcategory.set(0, { name: req.body.name }); works
doc.subcategory.set(req.body.id, { name: req.body.name });//doesn't work
doc.subcategory.set({_id:req.body.id}, { name: req.body.name });//doesn't work
doc.save((err, updatedCategory) => {
if (err) {
return res.status(400).json({
error: "Can't update subcategory",
});
}
res.json(updatedCategory);
});
}
});
};
My schema :
const mongoose = require("mongoose");
const categorySchema = new mongoose.Schema(
{
name: {
type: String,
trim: true,
required: true,
maxlength: 32,
unique: true,
},
subcategory: [
{
name: {
type: String,
trim: true,
required: true,
maxlength: 32,
unique: true,
},
},
],
},
{ timestamps: true }
);
module.exports = mongoose.model("Category", categorySchema);

solution :
exports.updateSubCategory = (req, res) => {
const category = req.category;
Category.findById(category._id, function (err, doc) {
if (err) {
return res.status(400).json({
error: "Can't Find parent category",
});
} else {
let subdoc = doc.subcategory.id(req.body.id);
subdoc.name = req.body.name;
doc.save((err, updatedCategory) => {
if (err) {
return res.status(400).json({
error: "Can't update subcategory",
});
}
res.json(updatedCategory);
});
}
});
};

Related

Mongoose populate with pagination

Trying to implement pagination on my populated query. I'm successful populating with mongoose populate but limit or skip doesn't work. Also tried mongoose-paginate library, pagination work but population not.
As an output I need only array of missions by user id that is paginated. Thank you.
User schema:
var mongoosePaginate = require('mongoose-paginate');
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
unique: true,
required: true,
},
password: {
type: String,
required: true,
},
uavs: [uavSchema],
missions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Mission' }],
});
userSchema.plugin(mongoosePaginate);
This works but limit nor skip doesnt work
const getMissions = async (_id) => {
let missions = [];
try {
await User.findOne({ _id: _id })
.lean()
.populate('missions')
.then((usr) => {
console.log(usr);
Object.assign(missions, usr.missions);
});
return { success: true, missions };
} catch (err) {
return { success: false, err };
}
};
output when using mongoose populate
Then tried using mongoose-paginate
const getMissions = async (_id) => {
try {
var options = {
populate: 'missions',
page: 1,
limit: 4,
lean: true,
};
await User.paginate({ _id: _id }, options, function (err, result) {
console.log(result);
});
} catch (err) {
console.log(err);
}
};
output when using mongoose-paginate
Solution - searching missions colection
const getMissions = async (_id, page, limit) => {
try {
let missions = {};
var options = {
page,
limit,
lean: true,
};
await Mission.paginate({ _owner: _id }, options, function (err, result) {
Object.assign(missions, result);
});
return { success: true, missions };
} catch (err) {
return { success: false, err };
}
};

Routing in NodeJs

I am working on an eCommerce application, and I am trying to save users in my database but when I hit the API in the postmen then instead of :
res.json({
name: user.name,
email: user.email,
id: user._id
});
});
**instead of this code following code is running
user.save((err, user) => {
if (err) {
return res.status(400).json({
err: "NOT able to save user in DB"
});
}
//the complete code of my "auth.js" file is as following:
const User = require("../models/user");
exports.signup = (req, res) => {
const user = new User(req.body);
user.save((err, user) => {
if (err) {
return res.status(400).json({
err: "NOT able to save user in DB"
});
}
res.json({
name: user.name,
email: user.email,
id: user._id
});
});
};
exports.signout = (req, res) => {
res.json({
message: "User signout"
});
};
///and the complete code of my user model file is as following:
var mongoose = require("mongoose");
const crypto = require("crypto");
const uuidv1 = require("uuid/v1");
var userSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
maxlength: 32,
trim: true
},
lastname: {
type: String,
maxlength: 32,
trim: true
},
email: {
type: String,
trim: true,
required: true,
unique: true
},
userinfo: {
type: String,
trim: true
},
encry_password: {
type: String,
required: true
},
salt: String,
role: {
type: Number,
default: 0
},
purchases: {
type: Array,
default: []
}
},
{ timestamps: true }
);
userSchema
.virtual("password")
.set(function(password) {
this._password = password;
this.salt = uuidv1();
this.encry_password = this.securePassword(password);
})
.get(function() {
return this._password;
});
userSchema.methods = {
autheticate: function(plainpassword) {
return this.securePassword(plainpassword) === this.encry_password;
},
securePassword: function(plainpassword) {
if (!plainpassword) return "";
try {
return crypto
.createHmac("sha256", this.salt)
.update(plainpassword)
.digest("hex");
} catch (err) {
return "";
}
}
};
module.exports = mongoose.model("User", userSchema);
SO please anyone tell me how to solve this problem while hiting this code to api mongo shell is also opend and mean while i also keep ROBO3T connected.

How to display details in one to many relationship

In my case, one maincategory has many subcategories.
maincategory model defined:
const MainCategorySchema = mongoose.Schema({
mainCategoryName: {
type: String,
unique: true,
required: true,
},
});
subcategory model defined
const SubCategorySchema = mongoose.Schema({
subCategoryName: {
type: String,
unique: true,
required: true,
},
main_category: {
type: mongoose.Schema.Types.ObjectId,
ref: "MainCategory",
},
});
module.exports.getAllSubCategories = function (callback) {
SubCategory.find(callback);
};
route
router.get( "/subCategories",
passport.authenticate("jwt", { session: false }),
(req, res) => {
SubCategory.getAllSubCategories((err, subCategory) => {
if (err) {
let message = "No category";
return res.json({
success: false,
message,
});
} else {
return res.send(subCategory);
}
});
}
);
How can I display mainCategoryName along with subCategoryName?
You need to populate main_category like this:
router.get("/subCategories",
passport.authenticate("jwt", { session: false }), (req, res) => {
SubCategory.find()
.populate("main_category")
.exec((err, subCategory) => {
if (err) {
let message = "No category";
return res.json({
success: false,
message
});
} else {
return res.send(subCategory);
}
});
}
);

Axios.delete() not triggering as expected

So I've got a classes Model which contains an array of people who will attend the class, I am trying to remove people from the classes.
So this is the Model:
const mongoose = require('mongoose');
const classMembersSchema = mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user',
}
})
const classSchema = mongoose.Schema({
location: {
type: String,
required: true
},
type: {
type: String,
required: true
},
name: {
type: String,
required: true
},
time: {
type: String,
required: true
},
classMembers: [classMembersSchema]
});
module.exports = mongoose.model('createClass', classSchema);
The classMembers Array is the one I mentioned that I am trying to remove members from. classMembers: [classMembersSchema].
This is the axios.delete:
deleteClassHandler = () => {
axios.delete('/api/classes/' + this.props.id + '/user/' + this.props.userId)
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
This is the route:
router.delete('/:id/user/:userId', ClassesController.deleteUser);
This is the controller:
exports.deleteUser = (req, res) => {
GymClass.findById({
_id: req.params.id
}, 'classMembers', (err) => {
if (err) {
res.status(401).json({
message: "Error Occured!"
})
} else {
GymClass.findByIdAndDelete({
"classMembers.userId" : mongoose.Types.ObjectId(req.params.userId)
}, (err) => {
if(err) {
console.log('Keeps hitting here!');
res.status(401).json({
message: "Error Occured!"
})
} else {
res.status(200).json({
message: "Success!"
})
}
});
}
})
}
Everything works fine until it hits the console.log('Keeps hitting here!');
At the start of the function the req.params.id which is the class Id of which class we want to modify and the req.params.userId which is the user we want to remove from the Array inside the Model do have the right values but when it gets to that step it gives me the Error.
I'm thinking it could be that it is not finding this:
GymClass.findByIdAndDelete({
"classMembers.userId" : mongoose.Types.ObjectId(req.params.userId)
Since it's in an Array within the classMembers. Any idea or advice to get this to work? Many thanks.

Mongoose findOneAndUpdate: Is there a way to update object in subdocument?

I have a model like this:
// Document
var programSchema = new Schema({
name: {
type: String
},
session: [sessionSchema]
}, {
timestamps: true
});
// Subdocument
var sessionSchema = new Schema({
name: {
type: String
},
info: {
type: String
},
order: {
type: Number
}
}, {
timestamps: true
});
Is there a way to access the subdocuments object and edit if exists, else create new?
I figured something like this:
router.post('/createsession', function (req, res) {
var options = { upsert: true, new: true, setDefaultsOnInsert: true };
var SessionData = req.body.session;
if (!SessionData.id) {
SessionData.id = mongoose.Types.ObjectId();
}
Program.findOneAndUpdate({ _id: req.body.session.id }, { $push: { session: SessionData } }, options, function (err, session) {
if (err) {
return res.status(409).json({
success: false,
message: 'Error creating/updating session'
});
} else {
return res.status(200).json({
success: true,
session: session
});
}
});
});
This only creates a new document. Would I be able to edit existing with this same query?
Try like this
var options = { upsert: true};
Program.findOneAndUpdate({ _id: req.body.session.id }, { $set: {
//Set individually values
name: req.nnae,
} },
options, function (err, session) {
if (err) {
return res.status(409).json({
success: false,
message: 'Error creating/updating session'
});
} else {
return res.status(200).json({
success: true,
session: session
});
}
});
});

Resources