Mongoose to update MongoDB collection of array of number ids - node.js

I have the following user Schema
const UserSchema = new mongoose.Schema({
name: String,
username: String,
email: String,
picture: String,
id: { type: String, unique: true },
accessCount: Number,
appliedIds: [Number],
general: {
citizenship_code: String,
gender: String,
currentLocation: String,
phone: String,
}
});
And I wanna update the appliedIds field. The appliedIds field is an array of numbers that will have an indeterminate number of indexes.
My function is as follow:
router.route('/myCustomRoute/:id/apply')
.post(async (req, res) => {
const { nModified } = await Job.findOne({ id: req.params.id }).updateOne({
$addToSet: { applicants: req.body.applicantId },
});
const test = await User.findOneAndUpdate({ id: req.body.applicantId}, { appliedIds: req.params.id })
Obviously, the applicantId is getting replaced entirely here, how can I just add a new item in this array instead of replacing it entirely?

You'll want to push to the appliedIds fields in your findOneAndUpdate call.
const test = await User.findOneAndUpdate(
{ id: req.body.applicantId},
{ $push: { appliedIds: req.params.id } }
)
MongoDB $push

Related

Mongoose pre hook findOneAndUpdate to modify document before saving

I am using the mongoose pre hook for findOneAndUpdate. I went through the documentation to understand better it's usage. I would like to update the password field before it saves to DB. However, I am not getting the disired result - nothing gets changed. What would be the right approach for using the findOneAndUpdate pre hook to modify a certain field in the doc?
Actual Document
{
_id: new ObjectId("622457f5555562da89b7a1dd"),
id: '5982ca552aeb2b12344eb6cd',
name: 'Test User',
configuration: [
{
email: 'test2#gmail.com',
password: 'p#ssw0rd',
_id: new ObjectId("9473l58f2ad34efb816963dd"),
},
{
email: 'test3#gmail.com',
password: 'trUstN0oNe',
_id: new ObjectId("8674884cec1877c59c8838e0")
}
],
__v: 0
}
Desired Document
{
_id: new ObjectId("622457f5555562da89b7a1dd"),
id: '5982ca552aeb2b12344eb6cd',
name: 'Test User',
configuration: [
{
email: 'test2#gmail.com',
password: '0f359740bd1cda994f8b55330c86d845',
_id: new ObjectId("9473l58f2ad34efb816963dd"),
},
{
email: 'test3#gmail.com',
password: '3dba7872281dfe3900672545356943ce',
_id: new ObjectId("8674884cec1877c59c8838e0")
}
],
__v: 0
}
Code:
const UserSchema = new Schema({
id: {
type: String,
required: [true, "'id' value is required"]
},
name: {
type: String,
required: [true, "'name' value is required"]
},
configuration: [ConfigModel.schema]
});
const ConfigSchema = new Schema({
email: {
type: String,
required: [true, "Email is required"]
},
password: {
type: String,
required: [true, "Password is required"]
}
});
UserSchema.pre('findOneAndUpdate', async function(next) {
const docToUpdate = await this.model.findOne(this.getQuery());
docToUpdate.configuration.forEach((item,i) => {
docToUpdate.configuration[i].password = md5(item.password);
});
return next();
});
You are missing the .save() document command after changing the information inside the document, because you are only using findOne
const docToUpdate = await this.model.findOne(this.getQuery());
docToUpdate.botconfiguration.forEach((item,i) => {
docToUpdate.configuration[i].password = md5(item.password);
});
await docToUpdate.save() // <---- this line
You dont need the updateMany() here because the ConfigSchema is nested inside the user collection
in userModel you read configuration from ConfigModel so you have to modify the config model not user model it just read and populate the data from config model.

My mongoose populate() function isnt working, I dont know why

I'm trying to populate the content key of my posts model with the contents of my content collection but it isnt working. The content collection is getting populated but the data isnt getting passed to posts collection's content key.
Schemas:
const postsSchema = new mongoose.Schema({
_id: {
type: String,
required: true
},
title: {
type: String,
required: true
},
content: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Content' }]
})
const contentSchema = new mongoose.Schema({
_id: {
type: String,
required: true
},
subHeading: String,
subHeadingContent: String,
image: {
data: Buffer,
contentTyle: String
}
})
const content = mongoose.model("Content", contentSchema)
const posts = mongoose.model("Posts", postsSchema)
Post request to populate the collections:
// Write a new post
app.post("/create", function (req, res) {
let Posts = {
title: req.body.newTitle,
subheading: req.body.newSubHeading,
subheadingcontent: req.body.newSubHeadingContent
}
postsArray = [];
postsArray.push(Posts)
console.log(postsArray);
postsArray.forEach((post) => {
content.create({
_id: uuidv4(),
subHeading: post.subheading,
subHeadingContent: post.subheadingcontent
})
posts.create({
_id: uuidv4(),
title: post.title,
})
posts.find().populate('content').exec((err, posts) => console.log("populated: ", posts))
})
res.redirect("/overview");
})
You do not need to have a postsArray & a for loop since your only trying to create a post from a single object.
Anyways, the reason it's not showing up is because you need to push the content object to your posts array.
First, you give a variable to the content.create,
then you push the variable to the array when you're creating the post
app.post("/create", function (req, res) {
let post = {
title: req.body.newTitle,
subheading: req.body.newSubHeading,
subheadingcontent: req.body.newSubHeadingContent
}
const postContent = content.create({
_id: uuidv4(),
subHeading: post.subheading,
subHeadingContent: post.subheadingcontent
})
posts.create({
_id: uuidv4(),
title: post.title,
{ $push: { content: postContent } }
})
posts.find().populate('content').exec((err, posts) => console.log("populated: ", posts))
res.redirect("/overview");
})

Can I push an element into a model's array during creation in mongoDB?

When doing this, I just get an empty array for list_employee in the database. So, is it possible to push an element when creating the house database?
If it is not possible, would it be best to use findOneandUpdate after creating it?
Here is my code:
module.exports.addHouse = async (req, resp) => {
const {
landLord,
email,
landLordPhone,
address1,
address2,
city,
numEmployees,
state,
zip,
numBeds,
numMattress,
numTables,
preferredName,
firstName,
tenantsPhone,
} = req.body;
console.log(req.body);
try {
const createTenants = await Tenants.create({ preferredName, firstName, tenantsPhone });
const createFacility = await Facility.create({ numBeds, numMattress, numTables });
const createHouse = await House.create({ landLord, email, landLordPhone, address1, address2, city, numEmployees, state, zip, $push: { list_employee: createTenants._id}, facilityInfo: createFacility._id })
resp.status(200).json({house: createHouse});
}catch(e){
console.log(e);
resp.status(200).send('error')
}
}
Here is the model:
const houseSchema = new Schema({
landLord: String,
email: String,
landLordPhone: String,
address1: String,
address2: String,
city: String,
numEmployees: String,
state: {
type: String,
},
zip: String,
list_employee: [{
type: mongoose.Schema.ObjectId,
ref: Tenants
}],
facilityInfo: {
type: mongoose.Schema.ObjectId,
ref: Facility
},
// numReports: [{
// type: mongoose.Schema.ObjectId,
// ref: FacilityReports,
// }]
});
const tenantSchema = new Schema({
preferredName: String,
firstName: String,
tenantsPhone: String,
});
Hi there from my understanding things like $push is for updating, not insertion. Since you are using push on a newly created row in the database you wouldn't need to use push as it's empty in the first place.
Looking at the MongoDB Driver API $push is an array update operator
https://docs.mongodb.com/manual/reference/operator/update/push/

How to populate data from nested object in mongoose

I am having schema like below:
const commentSchema = new Schema({
name: String,
surname: String,
email: String,
positions: [
{ detail: [{
type: Schema.Types.ObjectId,
ref: 'Position'
}],
progress: { type: String }, // keep track of the status
comment: { type: String } // keep track of internal notes
}],
});
Field detail contains array of mongo ids.
I am trying with below code but not getting the populated data:
const requirementsData = await Requirement.find({})
.populate({
path: "positions.detail",
model: Position,
})
.exec(function(err, docs) {
if(err){
console.log("err====", err)
}else{
res.render('candidates/show', {candidate: docs})
}
});
if I understand your problem you can do this
.populate({
path:'position',
populate:{path:'details'}
})

MongoDB - Mongoose , Adding new document data in nested query

I couldn't push the data in the nested query
I couldn't understand what I missed in my code (I am new in mongodb just experimenting )
My target is adding 'post' in posts
const Schema = mongoose.Schema;
const UserDetail = new Schema({
username: String,
password: String,
firstname: String,
lastname: String,
email: String,
posts: {
post:{
title: String,
article: String,
comments: {}
}
}
});
const User = mongoose.model('userInfo', UserDetail, 'userInfo');
module.exports = User;
Here my updating code
User.findOneAndUpdate({_id: req.user._id},{ $push: {"posts": { "post" : { "article": req.body.description }} } });
Thank you in advance
$push is used to append a specified value to an array. If the field is absent in the document to update, it adds the array field with the value as its element but if the field is not an array, the operation will fail. In your case posts is an embedded document, not an array.
You can either update your schema to make posts an array as:
const Schema = mongoose.Schema;
const UserDetail = new Schema({
username: String,
password: String,
firstname: String,
lastname: String,
email: String,
posts: [
{
title: String,
article: String,
comments: []
}
]
})
then do a push
User.findByIdAndUpdate(req.user,
{ "$push": {
"posts": {
"article": req.body.description
}
} }
);
or use $set with the dot notation if using the existing schema. The operation with $set follows this example:
User.findByIdAndUpdate(req.user,
{ "set": { "posts.post.article": req.body.description } }
);

Resources