This course has been updated! We now recommend you take the API Design in Node.js, v4 course.
Transcript from the "Querying Data with Mongoose" Lesson
>> Speaker 1: So, Mongo has this sophisticated query syntax. I'm going to go through this one, actually this one's kind of long. But I need to go to it. I'm gonna go through it relatively quicker than I normally do, so we can get started with the exercise. That way you guys can get out of here relatively earlier time and not be here all day.
[00:00:19] So I'm going to go through this, the notes, relatively quicker so we can hop right into the example, which is actually going to be kind of tough. So, Mongo has a sophisticated query syntax that is full of options. Actually, it has too many options for me to even list here.
[00:00:34] When I was writing this, I was worried about what to show you, what not to show you, cuz there's so many things and there's like five different ways to do the same thing. So I was just like I don't even know what's the best way. So there's just too many things to list so I just listed the one that I thought was the simplest and the one that I used the most and like the foundation of the rest.
[00:00:56] So using the mongoose model we have a few ways to ask mongo about what data we want. So we did this before, kind of, inside of the mongo shell, we were like db.the name of the collection.find. That was the native mongo implementation, this is the mongoose implementation that just calls that internally.
[00:01:16] So when I say model, I'm talking about the name of the model, so this is the model. This thing that's getting exported, that's the model. So in this case it would be post, or whatever you called it when you required it. So this is the model. So Model.find is a method that we can call.
[00:01:33] And what it does is, it can take a few things, but the most important thing is that the first object you pass in, it's just like an object describing the stuff that you want to find. So in the case of posts, if we said posts.find, actually I'll just do it down here so you can see what it looks like.
>> Speaker 1: So down here if I were like, post.find, the object I can pass in is the first argument is gonna describe the post that I'm looking for. So, I wanna find the post who's name is, or title, sorry.
>> Speaker 1: Who's title is whatever. So because our titles are unique this is only gonna return one.
[00:02:22] So then I can use a callback, which is a node style callback, which takes the error. A possible error is the first argument. And then a possible document is the second argument, so the document is returned from the database. So there I will have that stuff. Alternatively, most of these mango or mango query return promises.
[00:02:44] So like I say .then instead. There's also another way to execute this but we're gonna talk about that later cuz that one's a little more difficult. But that's the basics of the find method. So the find method is always gonna return an array. Even if it finds one.
[00:03:02] Even if it doesn't find anything, it'll be an array. But if it doesn't find anything it'll be empty. Nothing will be in the array. But find always returns an array or an error. So above is a basic example of how we can query Mongo for a specific model using the find method.
[00:03:19] We can pass a query object to specify what we're looking for. The object is empty. So I have an empty object here. So that means we want to get every single thing on that model. That means give me everything on that model. Everything. I think you can even just not use the object.
[00:03:32] You can just not put anything in there. The second argument is a node style callback. In this example it's a node style callback with either an error or the documents that gonna be retrieved. Most queries on mongoose return a promise. And you can look at the docs. It'll show you some more stuff.
>> Speaker 1: So, here's another utility method about it a Model.findById if it is give an object ID it will find that one thing or not. So, that you return an error will either return that document or it will just return nothing, no error but it also didn't find anything.
>> Speaker 1: So this one's very helpful for those PUT/DELETE/GET one routes, because they all use the ID property. So if you wanna put something, you need an ID so you gotta find that thing first If you wanna delete something you need an ID. So this method will come in handy for that, find by ID.
[00:04:26] Cuz we'll be given the ID on the URL. Yup.
>> Speaker 2: They're wondering why you're calling next if error's true.
>> Speaker 1: So the reason I'm doing this, so this is gonna be. This is a hint of, this query's wrapped inside of a route callback, so we have access to request, response, and next.
[00:04:47] So because of this function, is asynchronous, if we want node to know about this error, and we wanna be able to catch it, we actually need to pass it into next. Whereas this error before, but all synchronous, so they will always pass down through the chain. This is gonna be in a completely different call stack.
[00:05:03] So if you're familiar with angular, and they invented, how it works, this functioning is happening at a completely different call stack than this execution defined by id. So we have to call next to pass in order to to pass it down to our air handle or it will never get handled.
[00:05:18] It is a completely different call site. It will just stop and break the server. So this is why the next is awesome.
>> Speaker 2: Where is next coming from? The main parameter, or argument?
>> Speaker 1: Yeah, so all this is wrapped inside of one of these. I should have just written it.
[00:05:42] It's in one of these callback right here. So when you see these examples here, they're inside of one of these functions. That's why I'm able to call response and next. Sorry about that. Next is not coming Mongoose, it's coming from Express. That's the express is next in the middle here.
[00:06:05] So we'll be replacing all this stuff. With this stuff.
>> Speaker 1: So that's how you find an ID, that's how you find all of something. So those are two methods you will definitely be using. Here's a few ways to create a new document. There's probably more, but here's a few ways.
[00:06:24] So we could say var whatever equals a new model that we have. And then we pass in the object to create the new model. And all you have to do is call it dot save on that instance, which also takes a notes dot call back with either an error or the document that got saved.
[00:06:41] And if we save it, just send it back. Another way to do it is use the dot create shortcut on the actual model, which takes in the thing you want to create or many of those things. And then a node.callback as well, same thing. And then the third was to do it is if you can just say new model without passing in an object.
[00:07:03] And then add the properties using the dot notation. And then still call save. All three will do the same thing Is calling new dog internally, then it's calling save for you. It's just doing both, whereas we're doing it manually here. We're calling new dog, we're adding the properties then we're calling save.
>> Speaker 1: Those are three ways to create a method.
>> Speaker 3: You lost me.
>> Speaker 1: I lost you? Alright.
>> Speaker 3: Where did I get a function called save from?
>> Speaker 1: So new doc, when you make a new model. I'll just. Let's just do it in here.
>> Speaker 2: Is that schema.
>> Speaker 1: Yep. THat's a model.
>> Speaker 2: Export from the schema.
>> Speaker 1: Exactly, so this is like one of our categories or our posts or our user. So we call them new user and new post that's going to return an instance. In this case, it's the doc, And now we can say dog.save.
[00:07:53] So it's like if I were to come back into user, I guess, I deleted it didn't I, so I could just say user.save.
>> Speaker 1: The instance of a model is called a document. And all documents have a save method on them.
>> Speaker 1: It's an atomic operation. So if you call a .save on the document go right to the data base.Doesn"t matter where that document is inside of node it will right to it.
[00:08:21] It's atomic, so three ways to do the same thing you can pick your favor.
>> Speaker 1: So there's a way how to update something. So we can say model.findbyidandupdate. That's a real method you'll notice that Mongooses methods are actually pretty verbose, they say exactly what they mean. I'm going to findbyIdanupdate So if you give it an ID, and then you give it the objects with the new properties that you want to update too.
[00:09:01] What it'll do is, first it will go see if it can find a document on this model, with this ID. If it does find it, it will update these properties.
>> Speaker 1: And then an error callback. The thing to know about this though is this thing called upsert. So by default if you do this it will update the document to these properties, but it will also actually just update the document to just be this.
[00:09:26] It will just literally be this and all the other properties that were there before will be gone. So that's not what we want. So we want to use something else to get around that. I'm not going to show you how to do that. I want you guys to figure that out.
[00:09:40] Or unless you ask me when I walk around then I'll have to show you, but [LAUGH] I don't want to give you all the answers. It's just there's another method that allows you to do that or there's like two or three other ways to do it. If you literary looked it up, in like one second you would find out.
[00:09:57] And then of course, error style callback. Same thing.
>> Speaker 1: So like i said, most of the methods look very similar. Start off with something like find, you're passing some type of query object Maybe an optional update object and then there's a callback. Alright? So there are some advantages, uses, and features as well.
[00:10:19] Along with performing methods on the model. We can also use the actual document to do things like I was saying before. We were talking about the dot save method on the document. The document also ahs a dot remove method so it can remove itself. So if you had a instance of a document and you wanna delete it, you can just say document.remove, and it'll be like, okay, I'll go away.
[00:10:39] It'll either throw an error or the removed document. So this is a quick way to delete something. There's also a find by id and remove, or delete, to do those things, as well.
>> Speaker 1: So again, this is possible because the actual documents returned from mongo are not just objects but instances of a collection and have specific properties and methods that allow us to operate on it and for it to be able to write back to the database.
[00:11:07] The reason I emphasize this is because you're going to use this. You're going to have a document that's created somewhere else and you're going to pass it to another function. And then you're going to figure out how do I remove this thing? How do I delete this? How do I update this?
[00:11:22] And you're going to want to query the database again. Your going to want to say I will just do a model dot find and find the document again and do it here but you already have a document there so just know that you can do these methods on the document.
[00:11:34] You don't have to accrue the database again.