Date field in mongodb not get update when sending a null value - node.js

I have developed a mean stack application. I am trying to update a record with a null value for the Date field. This is working fine on my localhost but not on my server (Aws Ec2). It contains the previous value before the update.
I have also tried 'undefined' but still same issue.
Visit mongodb set null in update
router.put('/editAssign/:id',(req,res)=>{
if(!ObjectId.isValid(req.params.id))
return res.status(400).send('No record with given id : $(req.params.id)');
var assignment = {
name: req.body.name,
code: req.body.code,
appointmentTime: req.body.appointmentTime,
scheduledTime:req.body.scheduledTime,
countEndTime: null
};
Assignment.findOneAndUpdate(req.params.id,{$set:assignment},{new:true},(err,doc)=>{
if(!err)
res.send(doc);
else
console.log('Error in Assignment Update: '+JSON.stringify(err,undefined,2));
});
});
I expect it to work on my server too.

I have done a similar thing with updating the last login date of a user when they log in using Mongoose.
const authUser: any = await new Promise((res, rej) => {
User.findOneAndUpdate({ _id: user[0]._id }, { last_login: date }, {new: true}, (err: any, user:any) => {
if (err) rej(err);
res(user);
});
});
As you can see I wrapped it in a promise so i can wait for the response for sending back.
From looking at yours I would it looks like you are not telling it to look for using findByIdAndUpdate and not findOneAndUpdate because you are only passing in the ID. So the updated should look like this.
Assignment.findByIdAndUpdate(req.params.id, assignment, {new:true}, (err,doc)=>{
if(err) console.log('Error in Assignment Update: '+JSON.stringify(err,undefined,2));
return res.send(doc);
});
So in the one above, we are passing over the ID for findByIdAnyUpdate and we are just passing in the assignment. which if it includes all the same fields as the schema it will just update with the latest fields.
EDIT:
One other method you could try is:
Assignment.findByIdAndUpdate(req.params.id, assignment, {new: true}, (err: any, result: any) => {
if(err) console.log('Error in Assignment Update: '+JSON.stringify(err,undefined,2));
// Reasign with new assignment and save
result = assignment;
result.save();
return res.send(result);
});

Related

NOT WORKING: Mongoose findByIdAndUpdate() does not work

I am trying to create a (MERN stack) management system that keeps track of vacant rooms in a hotel.
I am trying to change the roomTypeAOccupiedTotal from 2 to 3.
From the client side, it sends an axios.put()request as follows:
axios
.put(`http://localhost:8082/api/myHotel/${branchStatus.id}`, data)
this is the server-side code:
router.put('/:_id', (req, res) => {
/*
req.params looks like this:
{ _id: '63b4d533fabbf31cdb519896' }
req.body looks like this:
roomOccupied5F: 3,
roomOccupied6F: 5,
roomTypeAOccupiedTotal: 2,
roomTypeBOccupiedTotal: 8,
*/
let filter = { _id: mongoose.Types.ObjectId(req.params._id) }
let update = { $set: req.body }
MyHotel.findByIdAndUpdate(filter, update, {new: true})
.then(data => res.json({ msg: 'updated successfully' }))
.catch(err =>
res.status(400).json({ error: 'Unable to update the Database' })
);
Below are the GET request and PUT request sent using POSTMAN.
after the message "updated successfully", I sent another GET request to check, but there are no changes to the variable(roomTypeAOccupiedTotal).
Could someone help me with solving this problem? the findByIdAndUpdate() method is working, as its not throwing any errors, but its not updating.
I believe your problem is the filter object. Looking at the docs for findByIdAndUpdate, it expects to receive the id param, not a filter object.
https://mongoosejs.com/docs/api/model.html#model_Model-findByIdAndUpdate
Parameters:
id «Object|Number|String» value of _id to query by
Additionally, when you create an objectId out of the request param, you aren't creating a new instance of it, so whatever was passed in would have failed to match anything. My IDE highlights this for me:
Your fix is likely something like this:
const id = new mongoose.Types.ObjectId(req.params._id)
MyHotel.findByIdAndUpdate(id, update, {new: true})
No need to convert id, and no need to use the update operator(i.e. $set).
try this:
MyHotel.findByIdAndUpdate(req.params._id, req.body, { new: true }, (err, hotel) => {
if (err) {
console.log(err);
} else {
console.log(hotel);
}
});

MongoDB CRUD routes returning null or wrong values

I've recently started using the MEAN stack and stumbled upon some errors while trying to work with my MongoDB database. I connected to the database successfully, implemented my CRUD routes, and I get wrong values for anything besides the find() method (which returns all the documents in my collection without any problem). The findOne() looks like this for example:
router.route(server.get("/company/:id", (request, response) => {
const companyId = request.params.id;
console.log("Showing company with id: " + companyId)
dbCollection.findOne({ _id: mongodb.ObjectId(companyId) }, (error, result) => {
if (error) throw error;
// return company
response.json(result);
});
}));
The result after making a get request via Postman is null
The insertOne() looks like this:
router.route(server.post("/company/add", (request, response) => {
const company = request.body;
dbCollection.insertOne(company, (error, result) => {
if (error) throw error;
// return updated list
dbCollection.find().toArray((_error, _result) => {
if (_error) throw _error;
response.json(_result);
});
});
}));
It adds one document to the database with the ID that it creates for itself, but for some reason it doesn't take in the body data (2 string elements { "name": "xy", "type": "company" })
And last but not least, the deleteOne():
router.route(server.delete("/company/delete/:id", (req, res) => {
const companyId = req.param.id;
console.log("Delete company with id: ", companyId);
dbCollection.deleteOne({ _id: mongodb.ObjectId(companyId) }, function(err, result) {
if (err) throw err;
// send back entire updated list after successful request (optional)
dbCollection.find().toArray(function(_err, _result) {
if (_err) throw _err;
res.json(_result);
});
});
}));
For some reason it deletes the very first document in the collection, but not the one that is entered with the corresponding ID.
If anyone could help me out with this it would be awesome. Thank you in advance!
Edit 1:
Adding a new document to the collection via Postman
Collection after the add
Edit 2:
Get request via ID and response (returns null)
Console output:
Showing company with id: 5e63db861dd0ce2418ce423d
Edit 3:
Corrected the code for the findOne() and deleteOne() methods.
When you try with _id you need to convert the string(request.params.id) to ObjectId().
Convert string to ObjectID in MongoDB - whoami

How can I retrieve documents' properties from a pre hook?

I posted this question yesterday because I didn't know how to solve my problem.
Change variable value in document after some time passes?
I was told I need to use a pre hook. I tried to do it, but "this" would refer to the query, not to the document. So I couldn't retrieve the documents to check if the 4 weeks passed. (check the question, you will get it)
Because I don't know how to make this .pre('find') to use variables from each of my document (so it checks if the 4 weeks passed) I was thinking about looping through all of them and checking if 4 weeks passed.
router.get('/judet/:id([0-9]{2})', middleware.access2, function(req, res)
{
var title = "Dashboard";
Somer.find({}, function(err, someri)
{
if(err)
{
console.log(err);
}
else
{
res.render("dashboard", {title: title, id:req.params.id, someri:someri});
}
});
}); ///get route
var someriSchema = new mongoose.Schema({
nume: {type: String, required: true},
dateOfIntroduction: {type:Date, default: Date.now, get: formatareData},
});
someriSchema.pre('find', function(next) {
console.log(this.dateOfIntroduction); <- this will return undefined, because this refers to the query, actually
next();
});///schema and the pre hook. I thought I could use it like this, and inside the body of the pre hook I can check for the date
Here's what I am talking about:
router.get('/judet/:id([0-9]{2})', middleware.access2, function(req, res)
{
var title = "Dashboard | Best DAVNIC73";
Somer.find({}, function(err, someri)
{
if(err)
{
console.log(err);
}
else
{
someri.forEach(function(somer)
{
///check if 4 weeks passed and then update the deactivate variable
})
res.render("dashboard", {title: title, id:req.params.id, someri:someri});
}
});
});
but I think this will be very bad performance-wise if I will get many entries in my DBs and I don't think this is the best way to do this.
So, if I was told correctly and I should use a pre hook for obtaining what I've said, how can I make it refer to the document?
Ok, I think I understood your requirements. this is what you could do:
/*
this will always set a documents `statusFlag` to false, if the
`dateOfIntroduction` was before Date.now()
*/
const mongoose = require('mongoose')
someriSchema.pre('find', function(next) {
mongoose.models.Somer.update(
{ datofIntroduction: { $lte: new Date() }},
{ statusFlag : false})
.exec()
.then((err, result) => {
// handle err and result
next();
});
});
The only problem I see, is that you are firing this request on every find.
in query middleware, mongoose doesn't necessarily have a reference to
the document being updated, so this refers to the query object rather
than the document being updated.
Taken straight from the documentation of mongoose
I pointed you yesterday to their documentation; but here is a more concrete answer.
someriSchema.post('find', function(res) {
// res will have all documents that were found
if (res.length > 0) {
res.forEach(function(someri){
// Do your logic of checking if 4 weeks have passed then do the following
someri.deactivated = true
someri.save()
})
}
})
What this basically do is for every found schema you would update their properties accordingly, your res can have only 1 object if you only queried 1 object. your second solution would be to do the cron
EDIT: This is what you would do to solve the async issue
const async = require('async')
someriSchema.post('find', function(res) {
async.forEach(res, function(someri, callback) {
// Do your logic of checking if 4 weeks have passed
// then do the following - or even better check if Date.now()
// is equal to expiryDate if created in the model as suggested
// by `BenSow`
// Then ONLY if the expiry is true do the following
someri.deactivated = true
someri.save(function (err) {
err ? callback(err) : callback(null)
})
}, function(err){
err ? console.log(err) : console.log('Loop Completed')
})
})

How to update some data based on array value in Mongoose?

I'd like to update some data in Mongoose by using array value that I've find before.
Company.findById(id_company,function(err, company) {
if(err){
console.log(err);
return res.status(500).send({message: "Error, check the console. (Update Company)"});
}
const Students = company.students;
User.find({'_id':{"$in" : Students}},function(err, users) {
console.log(Students);
// WANTED QUERY : Update company = null from Users where _id = Students[];
});
});
Students returns users._id in array with object inside, and I use that to find users object, and then I want to set null a field inside users object, that field named as "company". How I can do that? Thank you.
From what you posted (I took the liberty to use Promises but you can roughly achieve the same thing with callbacks), you can do something like:
User.find({'_id':{"$in" : Students}})
.then( users =>{
return Promise.all( users.map( user => {
user.company = null;
return user.save()
}) );
})
.then( () => {
console.log("yay");
})
.catch( e => {
console.log("failed");
});
Basically, what I'm doing here is making sure .all() user models returned by the .find() call are saved properly, by checking the Promised value returned for .save()ing each of them.
If one of these fails for some reasons, Promise.all() return a rejection you can catch afterhand.
However, in this case, each item will be mapped to a query to your database which is not good. A better strategy would be to use Model.update(), which will achieve the same, in, intrinsically, less database queries.
User.update({
'_id': {"$in": Students}
}, {
'company': <Whatever you want>
})
.then()
use .update but make sure you pass option {multi: true} something like:
User.update = function (query, {company: null}, {multi: true}, function(err, result ) { ... });

Update data in MongoDB with Mongojs using findAndModify()

Yet another first-timer problem here. This gets data from a database and displays it in some text fields (that part is not shown in the code below) and after the user edits it the data should be updated in the database via the findAndModify() method and I think this is where the issue lies. There are no errors, it just doesn't do anything. EDIT The following error is received: MongoError: Either an update or remove=true must be specified
server.js
MongoClient.connect("mongodb://user:secretPassword#aws-us-east-1-portal.7.dblayer.com:10712,aws-us-east-1-portal.10.dblayer.com:10316/database", function(err, db) {
if (err) throw err;
var contactList = db.collection("contactList");
app.put('/contactList/:id', function(req, res) {
var id = req.params.id;
console.log("edited: " + req.body.name); //works up until here
contactList.findAndModify({
query: {_id: mongojs.ObjectId(id)},
update: {$set: {name: req.body.name, email: req.body.email, number: req.body.number}},
new: true
}, function (err, doc) {
res.json(doc);
})
});
controller.js
$scope.update = function() {
$http.put('/contactList/' + $scope.contact._id, $scope.contact).success(function(response) {
refresh();
})
};
If this were me I would first do a couple of things:
Before your call to findAndModify just do a simple find using your query. Make sure you can actually find the object using your query. If that works you know that the 'find' part of the findAndModify is probably ok.
Do some console logging inside the callback handler of the findAndModify call. As it stands you do not do anything if an err is returned from the findAndModify call. It is possible your call is returning an error that you are just ignoring and it may provide some additional insight into your problem.
I would try these two first and see if it helps.
Update:
Example using native:
collection.findAndModify(
{ field: 'some value' },
[],
{ $set: { field2: 'some new value' } },
{ new:true },
function(err, doc) {
//handle err and doc
});

Resources