Check out a free preview of the full Introduction to MongoDB course
The "Virtuals, Hooks & Indexes 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 the previous exercise.
Transcript from the "Virtuals, Hooks & Indexes Solution" Lesson
[00:00:00]
>> Scott Moss: Welcome back. I hope everyone had enough time to complete those exercises on the indexes, the middleware, and the virtuals. So, like always, I'm just going to go ahead and walk through the solutions, so let's start with a project. So for the project we had a couple of things, let's see here.
[00:00:27]
We needed to add a compound index of the project schema, so that the project names are unique for all. So I'll pull up the test and then will do that. So, project here.
>> Scott Moss: And then project.spec, cool. All right, so it says right here project names are unique per org.
[00:00:51]
So it's expecting an error to happen if I insert a project with the same name that has the same org. So we'll just go ahead and write a index for that. So what we'll do is we'll say projectschema.index. And then first one we will index on is the org.
[00:01:08]
And then underneath that, we want it to shadow the name. So that means we're gonna make a compound index with the org and then a combination of name and we want that to be a unique index.
>> Scott Moss: So think about there's different types of indexes, right? I didn't talk about the different types but you said compound indexes, but this compound index is a unique index.
[00:01:33]
There's also text indexes and,
>> Scott Moss: Sparse indexes and different types of indexes, but we've just been talking about unique. For the most of time is gonna be regular indexes it looks like maybe unique or something like that. Text may be but is probably something else. So we've got that and now is gonna run test.
[00:01:55]
And I'll do watch, I think watch break here with indexes we'll see. Okay, so we've got one passing. And yup, project names are unique per org. So that one's good. The next one we have to do was budget left. So a virtual should calculate the budget left, so to do that, what we'll do is we'll say projectSchema.virtual('budgetsLeft').
[00:02:26]
And I'm gonna define a getter, and for that I'm just gonna say return this.budget- this.spent. So it'll tell me how much is left from the budget and how much we spent so far. So I'm gonna add that virtual, and it looks like 2 passed, so we'll verify that.
[00:02:52]
And budgetleft virtual should calculate budget left. That passed, all that's good. So the last test that we have here is Org model, removes projects when org is remove. So I saw a couple issues with this and I haven't quite figured out what exactly the issue was, it seems like some silent issues.
[00:03:10]
But I think it's an issue where if you have an older version of Mongo as in less than 4.0, but using the latest version of Mongoose as in, anything above 5.0, these middleware might not work for you. They don't actually fail, they just don't work. So I think it's a combination of that.
[00:03:27]
I haven't verified it. But if you're in that boat, whereas you had Mongo before coming in today, and it's an older version, but you installed the NPM packages, which are the latest Mongoose. There might be some inconsistencies there and they might not be working, I think that's the issue.
[00:03:41]
So, if you're just like, my hooks aren't even running. I really don't know why they aren't running, that might be you. But to get going with this exercise I'm gonna look into the orgspec. There we go. And so the mongoose project org should be removed. So I'm gonna head over to org.js and I'm gonna go ahead and add a hook for that.
[00:04:10]
So I'll say orgSchema.post('remove', function(doc, next). What I want to do here is I'm going to use the project model to remove all the projects. I want this to be async, cuz I like async. So what I'll do is I'll just await Project., and there's so many different operations you can do here.
[00:04:49]
You can do delete many, you can do find and delete, you can just do .remove, which might be deprecated but still works. There's so many ways to delete a lot of things out of the database. I'm just gonna do a findAnd,
>> Scott Moss: Actually, I'm gonna do a deleteMany, let's do deleteMany.
[00:05:09]
So we'll say a deleteMany, and then the conditions are pretty much any project that has the ID of the org that was removed. So we know a project, if you go look at it, it has an org property whose value is a org ID. And we know this document has an ID on it, so if I say org and then document._ID, I should be able to delete all of those.
[00:05:33]
I'm gonna save that and I'm gonna go back to my test and that passes.
>> Scott Moss: Again, if org was removed, then delete all of the projects that are associated with that org as well. In production, you can probably do like a soft delete, just in case your customers come back.
[00:05:53]
Getting their data back. Any questions on this? Other than the issue that I brought up earlier?
>> Scott Moss: Anybody do anything differently than this and if you did, I would love to know about it. Cuz there's a lot of different ways you can do this. Yeah what's up?
>> Student: So doc I just did this, not sure if it worked not sure if that's better or worse.
[00:06:18]
>> Scott Moss: Yeah, yeah this works. Yeah, that totally works.
>> Student: And it used the async or await, maybe that's bad?
>> Scott Moss: No, it's not bad. The reason I did this is I forced this function to just wait, right? Technically, I should come here and do next right underneath it.
[00:06:33]
But the reason next is not that important here is because I don't have any middleware after it. If I did then I would absoluely have to put next. But the reason I put await is so that there's no race condition in my test, right? Because if I don't await this, then while I'm awaiting this org to be removed, this might be happening in the background.
[00:06:56]
And then when my assertion happens, this still might be happening. So you have an erase condition where it may pass sometimes and it may fail sometimes because there's erase condition. So you just wanna put everything synchronous, so I just awaited it. That was it. But I also think in these posts depending on where the version of mongoose you are using, like mongoose 5 you can actually just return a promise here.
[00:07:16]
So if you just put a return statement infront of it, it probably would have worked as well too, as far as waiting
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops