I'm learning Mongoose and I can't find in the documentation, nor in other questions on this site, why updateMany()
needs to have a .then()
in the end to be executed.
As an example, here is the code I'm trying to run, aiming to change the rating of the movies made in 1992 and 2019.
Movie.updateMany({year: {$in: [1992,2019]}}, {rating: 'M'}).then(data => console.log(data));
These are the movies in question:
{ "_id" : ObjectId("6282e0d37a9a5a4851d465b1"), "title" : "Elton Pan", "year" : 2013, "score" : 10, "rating" : "M", "__v" : 0 }
{ "_id" : ObjectId("6282e0d37a9a5a4851d465b2"), "title" : "Pon Porom", "year" : 2019, "score" : 0, "rating" : "M", "__v" : 0 }
{ "_id" : ObjectId("6282e0d37a9a5a4851d465b3"), "title" : "The Night", "year" : 1992, "score" : 10, "rating" : "R", "__v" : 0 }
If I attempt to run the code without .then
in the end, nothing changes.
I have also seen people use this method without .then
in the end, which makes me wonder if I can't use it this way because of the version of Mongoose I'm using.
Just to clarify, I'm checking the results via the Mongo shell, and not attempting to retreive the results within the code.
Thanks in advance, and sorry for the noob question :)
CodePudding user response:
updateMany
does not work without .then
because it returns a Promise. Actually, it updates the data, but for you to have the updated data, you need to wait for it, as a Promise is a task that starts and ends later. .then
lets you say, I wanna know when the task I asked for is done.
To understand Promise in JavaScript you could watch this Youtube Video, or use the above link to read about it on MDN. It's a key concept in JavaScript. Mongoose's documentation does not talk about why they are using .then
because they assume at this point you have a clue about it.
CodePudding user response:
It doesn't need a .then()
to be executed. It executes just fine when you do this:
Movie.updateMany({year: {$in: [1992,2019]}}, {rating: 'M'})
You just don't have access to the results yet because it's an asynchronous operation. The function returns a promise. The .then()
waits for the promise to resolve, then gives you the result as the .then()
callback's first parameter.
I'd recommend using async...await
syntax. Having a bunch of .then()
promise chaining crap is no good, especially nowadays.
// wrapped it in an automatically invoked async function
(async () => {
const data = await Movie.updateMany({year: {$in: [1992,2019]}}, {rating: 'M'})
console.log(data)
})()
CodePudding user response:
I think I may have found an explanation to the .then
question. Quoting Zarko, a teacher in the (Udemy) course I'm doing:
The mongoose query shouldn't return a real promise by default, but a query object that is thenable. Basically, mongoose is providing support for callbacks, promises and the async/await syntax when working with asynchronous queries. The mongoose query itself will return a mongoose 'query' object which has its own .then (so it's like a mongoose custom wrapper over regular promises), and when we add .then to it we trigger the execution of that query. You can check the mongoose docs here: https://mongoosejs.com/docs/promises.html#queries-are-not-promises
You can check this article: https://masteringjs.io/tutorials/mongoose/promise
So, as mentioned in the documentation, we can also chain the .exec() method call after the query to get the fully-fledge promise - Mongoose - What does the exec function do?
So, basically, the .then
or .exec
is necessary to trigger the execution of that query (when not using async...await
). At least that is what I understand from the teacher's answer.
This is my first post, and I'm not sure if I should have posted this as an answer or edited my own question to include this explanation, feedback would be appreciated. Thanks.