Check out a free preview of the full Introduction to MongoDB course:
The "CRUD Solution" Lesson is part of the full, Introduction to MongoDB course featured in this preview video. Here's what you'd learn in this lesson:

Scott live codes the solution to CRUD portion of the exercise, and explains why it's important to use .exec() at the end of queries.

Get Unlimited Access Now

Transcript from the "CRUD Solution" Lesson

[00:00:00]
>> Scott Moss: So the CRUD stuff was the work, right? That was the one where I was like I don't know what's going on here. Okay, so we hop over here to the CRUD one, we'll do CRUD here. Okay, so we'll go through this line by line. So the first one says get user by ID.

[00:00:19] And it says get user by object ID. Yeah, that's basically what it needs, an object ID, not like an object with an ID property, but object ID as in a Mongo object ID. So you're already given an ID here so given this ID that it's asking for, you should return a user by that ID.

[00:00:39] So what we want to do is, we want to return User.findById, pass the id. And that should satisfy it because, again, we're given an ID, we're just gonna use findById. This always returns a promise, so pretty much every query you do on the model is gonna return a promise, almost every single one of them.

[00:01:03] So this should satisfy it. And if we can go look, you can see get user by object id is good. So quick pro tip, yes, these queries do return a promise, but technically, they're not really promises. What Mongoose is, doing is they're actually returning a query object. That's really advanced, we're probably not going to get to query objects today because that's like an advanced thing.

[00:01:27] But you could think of it as, like, SQL like query on a query. And on that query object there's a dot then property. So anything consumed in this query thinks it's a promise because there's a dot then property on it. But in reality, it's not a real promise.

[00:01:42] So to avoid that, what you normally do is you use .exec at the end of a query like this to say, I'm done. There's no more querying coming after this. Because on a query, I can do things like .limit, .sort, .greaterthan, .lessthan. But when I'm done with all that I can say cool, I'm done, execute the query.

[00:02:03] So .exec is short of execute. So this is saying, I'm done, there's no more querying coming out of this, so just return a real promise and that's what this does. So this will help you avoid any bugs that you might have that might be consuming this function and expecting a real promise, this will help avoid that.

[00:02:20] So always use .exec at the end of your queries. This won't work at the end of things like create cuz a creation is not a query. So only for queries, get all users. We'll just say return User.find wild card exact. There's no arguments here, so it's just a wild card, so all the users.

[00:02:45] All right, let me go check the test, that one passes, get all users. For our create user we're just going to return user.create, it's in the name create. And we'll just pass the user details, so whatever details that the test decides to pass us. It's up to the test to make sure those details are correct, we're just going to save it.

[00:03:08] And we can check to see if that worked, and that works so create a user succeeded. The next one we have is remove user by ID, so given an ID remove users. So if we say return user.findByIDAndRemove, I know it's so verbose, .exec cuz that's a query. We know it's a query because it has find in it.

[00:03:36] That should pass and now we get removeUserByID that's successful.
>> Scott Moss: There's another way you can do this. You could just user.findById, grab the user and, I didn't teach you how to do this. But you could use the .remove method on the document instance itself. Remember, I told you that documents that you get back from Mongoose aren't JavaScript documents.

[00:03:58] So like Mongoose documents, well, they have properties on the methods, one of them is .remove. You can do .remove on the document itself at the instance, it will remove itself. So you can do that way but obviously this way is just way cleaner, and is just on one operation.

[00:04:12] And then the last one is update user by Id. So we have an Id and then we have some properties to update. So I'm just gonna say return User.findByIdAndUpdate. So id is the one that's passed in here. And then the update is the update. Now if you ran this, you probably expected it to work and [SOUND]

[00:04:41]
>> Scott Moss: Now it's just hanging. So, yeah, if you ran this, you'd probably expect this to work, right? But if you got to this point, you might have realized that this one might not work all the way, because there's something else that you have to do. So we'll let this run, and you can see right here, my test is failing.

[00:04:56] So it's expecting beta user to be true but instead it's getting false. And it's not because it's not updating the database it is. It is updating the database. The problem is find by ID and update isn't returning the newly updated user. By default it's just not going to do that, even though it updated in the database.

[00:05:16] What it's returning is the user before it got updated. So [LAUGH] how helpful is that? It's not that helpful, so what you have to do is you have to add this third option here. So findByIdAndUpdate and you have to put new:true, and that means return the new thing that got updated, the new instance.

[00:05:35] It doesn't mean create a new one, that option is called upsert. As in, if this doesn't exist, create a new one, that's what that does. New means return the updated object. After the update operation is done, return that object. And that's the one that we want, that's what the test is expecting.

[00:05:51] I saved that one for last to let you explore a little bit.
>> Student: Does that need an exec at the end?
>> Scott Moss: And it does need an exec cuz it has a find on it. That's exactly right, cool.
>> Student2: If you do separately the update or .remove then it's not executable, right?

[00:06:11]
>> Scott Moss: Right, the exec is only for model queries.
>> Student2: I mean, you can do it find? Update at the end, it said.
>> Scott Moss: Yeah, then you're fine, yeah.
>> Scott Moss: So now if you run the test, all those tests should pass. So what we're gonna do now is we're gonna hop into more advanced things in Mongo, things like more advanced queries so using some type of filtering type of options.

[00:06:39] We are going to talk about relations, how does that work with Mongo? And like many to one and one to many, those different types of things. So that's what we are going to do next. So I'm just going to hop back into my test.js file. And I'm just gonna continue to do my work in here.