can findOneAndUpdate trigger schema post update/save? - mongodb

I am stuck with socket io with problem emit the changes. Just wondering is there a way to trigger scheme.post update or save. at the moment scheme.post save doesn't work with findOneAndUpdate, please help out been stuck for hrs... any help much appreciated.
project.schema.post('update', function (doc) {
onSave(socket, doc);
});
project.schema.post('save', function (doc) {
onSave(socket, doc);
});
where does the udate
project.findOneAndUpdate(
{
_id: req.body._id
},
{ $set:
{ 'watchers' : req.body.watchers }
},
function(err, data) {
return res.json(200, data)
}
);

That was an issue that is covered in some detail here. I'll let you read through for the why but the solution was the maintainers added a special post hook for it:
project.schema.post('findOneAndUpdate', function (doc) {
onSave(socket, doc);
});
NOTE: I am not sure if doc is provided though.

Related

Why does MongoDB not update unless I call ".then res.json(...)" after findOneAndUpdate?

understanding questions here. I am doing a MERN setup website, and I was updating a field in my database like this:
router.post("/updateLogApprovementStatus", (req, res) => {
User.findOneAndUpdate(
{ _id: req.body.userId },
{ $set: { log: req.body.newData } }
).then(user => res.json(user.log));
});
But after doing repeated calls to the api with correct data, my data field wasn't updating. However, when I do this:
router.post("/updateLogApprovementStatus", (req, res) => {
User.findOneAndUpdate(
{ _id: req.body.userId },
{ $set: { log: req.body.newData } }
).then(user => res.json(user.log));
});
My database updates perfectly fine. All I did was adding a res.json(), which occurs after the update since it is in the "then" statement, which makes me wonder why it wored.
I am pretty sure that all I did was adding the then res.json() statement. Any clarifications on why this made it work?
Reason being : "The query executes if callback is passed else a Query object is returned." (bellow the returns section)
.then() isn't really a promise, it's disguised by mongoose but acts as an execution.
You can see it execute queries here
.exec() from the documentation "Executes the query" and returns a Promise (true one)
Mongoose queries are not promises. They have a .then() function for co
and async/await as a convenience. If you need a fully-fledged promise,
use the .exec() function.
If I understand your issue correctly, you should go with something like this:
User.findOneAndUpdate(
{ _id: req.body.userId },
{ $set: { log: req.body.newData } }
).exec();
The exec function will run the query and this way you don't have to handle the promise result.

Updating a field within a document in MongoDB / Meteor

I am attempting to update a few different fields within a document in a collection, and seem to be having some trouble. I don't seem to be able to access any of the specific attributes I am looking to set (which are subject, standard, price). Would anyone be able to help? Here is my code so far, and the newAttributes don't seem to be making it there.
I have confirmed the doc._id is correctly populating.
Template.AppAdmin.events({
'click #editApp': function() {
let newAttributes = {};
let subject = $('#subject').val();
let standard = $('#standard').val();
let price = $('#price').val();
console.log(subject);
console.log(standard);
console.log(price);
newAttributes = { subject: subject, standard: standard, price: price };
var doc = Session.get('appId');
console.log(doc);
console.log(newAttributes);
Apps.update(doc._id, { $set: { newAttributes }});
console.log('app has been updated!');
}
});
Thank you.
UPDATE of course I figured it out, I wasn't correctly grabbing the document by ID...
This worked:
Apps.update({_id: doc}, { $set: newAttributes });
You need to remove the braces around newAttributes, because newAttributes is already an object. So your updated code will be like
Apps.update(doc._id, { $set: newAttributes });
Or
Apps.update({'_id':doc._id}, { $set: newAttributes });

WaterlineJs find() with no criteria and fields/select provided does not work

I am trying to fetch all the records but with selected fields, I have tried the following ways but none works:
Post.find(
{
where: {},
select: ['title']
}
);
Post.find(
{},
{
fields: {
title: 1
}
}
);
As this answer points out, the fields param "WILL work as long as you pass other params with it such as limit or order."
Alternatively, if you want this throughout your application, you could define a custom toJSON function for your model, under attributes. If not, you could still define it under some other (e.g. filter) and use map to return the custom objects instead of the default model. Remember to take care of the control flow while using map though. Use async/promises/raw logic to avoid returning before all objects are processed.
The issue has been resolved in sails-mongo latest version:
https://github.com/balderdashy/waterline/issues/1098
Thanks
I've played with trying to get above answer to use limit or order to kick in the projection to no avail.
I did see this in the docs located here:
http://sailsjs.org/documentation/reference/waterline-orm/models/native
With an out of the box solution for exactly what you're doing (pasted here for ease of use).
Pet.native(function(err, collection) {
if (err) return res.serverError(err);
collection.find({}, {
name: true
}).toArray(function (err, results) {
if (err) return res.serverError(err);
return res.ok(results);
});
});
Swap out the response base things and change Pet to Post and, this ought to work in the sails console:
Post.native(function(err, collection) {
if (err) throw new Error(err);
collection.find({}, {
title: true
}).toArray(function (err, results) {
if (err) throw new Error(err);
console.log(results);
});
});
You'll still get the _id field, and if you don't want that then hit the Mongo docs on not getting those hint(title: true, _id: false)hint
Hope this helps!

meteor how to manage async updates in a loop

I have this loop:
properties.forEach(function(property) {
console.log("property: " + property);
var upsertValues = {};
upsertValues["ID"] = property.ID;
Properties.upsert(upsertValues,
{$set: property},
function(err, nbr) {
if(err)
console.log(err);
else
console.log("upsert successful" + nbr);
});
});
setTimeout(function () {
Fiber(function() {
Meteor.call("removeOldProperties", modification_date);
}).run();
}, 30000)
})
Basically, it updates a bench of documents and at the end, it removes all the once who have not been updated.
I had to use a TimeOut because without that, I removes the documents before their update, as all the Meteor.upsert statements are async.
Is there a better way to do it (without having to use this timeout) ?
Thanks,
Couple thoughts:
upserts are fast, no need for a callback
Fiber is for the server
I don't understand how your upsertValues was a valid query. Is this referring to the document _id? If so, convention is to keep using the name _id, if not, I'd use a more descriptive name. Was this code functioning??
What remains:
var upsertsCompleted = 0;
properties.forEach(function(property) {
Meteor.call("upsertProperties", property, function() {
if (++upsertsCompleted === properties.length) {
Meteor.call("removeOldProperties", modification_date);
}
}
Meteor.methods({
upsertProperties: function (property) {
return Properties.upsert(property.ID, {$set: property});
}
});

Mongoose findByIdAndUpdate not working

I have a fairly straight forward method below to update a document based on its ObjectId. It does not return an error but it fails to make the required updates to the document. I think it is failing because, according to my research, findByIdAndUpdate() takes only plain Javascript whereas job._id is an ObjectId from the document that I want to update. Can someone tell me how to make this work correctly?
function handleEncoderResponse(xmlResponse, job) {
var r = et.parse(xmlResponse);
var mediaID = r.findtext('./MediaID');
var message = r.findtext('./message');
EncodingJob = mongoose.model('EncodingJob');
EncodingJob.findByIdAndUpdate( job._id, {
"MediaID": mediaID,
"Status": message
}, function(err, result) {
if (err) console.log(err);
console.log(result);
});
}
Edit: Per this question Mongoose update document Fail with findByIdAndUpdate
I also tried the following code to no avail.
job.MediaID = mediaID;
job.Status = message;
job.save(function(err, res) {
if(err) console.log(err);
});
This approach yields the issue. It does not update the document and it does not return an error.
As it turns out, my mistake was forgetting to define MediaID and Status in the Schema as follows:
var encodingJobSchema = new mongoose.Schema({
...
MediaID: String,
Status: String
});