Mongoose Validation | Creating a REST API with Node.js

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to another video in this building a restful service with no js' serious the last video we added Mongoose and we connected therefore our MongoDB database and we worked a lot on the products related routes in this video I want to find you an hour setup there a bit add validation so that only valid data makes it into our database and also come back to these restful constraints I showed you earlier this serious because right now our responses we give back from our endpoints here are not really dead great so let's work on both in this video let's start by adding validation now for that most interesting class is the post route here where we create new products and there we store an ID which we automatically generate so nothing to validate here this will be unique and so on but we also store a name and a price and what happens if a user passes let's say a string as a price well let's find out let's go back to postman create a new post request to products let's work on the body and the body now needs to change again should be a normal JSON object here ray set the name to something something awesome and then I set the price to hello which doesn't look like a correct price if I sent this and restart my server which I adjusted so if I sent this I do get back an error cast number failed for a value hello so that's great what important lecture we can already take away we can't store strings as numbers and so on this is already something mongoose checks for us and it correctly throws an error if we try to do so however what happens if we don't pass a price but just pass a name then we still get back a valid response and if I now get all my products you see we created a product without a price that is not how it should work so I'll go back to my product model and there where I set the values to string a number we can also pass an object which does not mean the type as an object but now we can provide a more detailed configuration we can set up a type property here where we can still set this to number so now we had the same as before but we can also pass more configuration like for example we could set required to true here and this does just what it sounds like it makes sure that this field is required if I now save this and I try to send that same post request from before again I now get an error that path price is required and this of course makes sense because well it is required I don't want to allow this right excess and the same can be done for the name of course here I'll now also set is to type string and require this and if I now send this here sorry without setting a name so let's just set some names property which doesn't exist now this also fails because price is required and name is required if I do set a name to something awesome and if I then do set a price to something awesome then it succeeds if I now add a third argument here like sales price which I set to 999 and I said this it also succeeds and if we get all products we see that here know where the sales price was safe though and that makes a lot of sense because if you have a look at our back end just sending the sales price as an argument to our route doesn't do anything because here we're configuring the product we plan on storing and there we never extract the sales price we never assign it to a property in our object which is going to get stored so we can send which every day that we want we're just making sure that the day that we do expect is valid and this is now the case with the set up we well set up here now let me quickly clean up that data here by sending a couple of delete requests so I'll delete this product which doesn't have a valid price and thereafter let me quickly again grab all products whoops without that ID which correctly failed because we just deleted it and let me also delete one of these something awesome products here or if you want of course both so let's delete that two now that also Rachelle's us some other issue i want to work on in this video the response now this is not a good response in at cert doesn't fulfill the constrains I mentioned earlier in this video series where the responses should be all kind of self-destructive so what we want to do is provide better responses let's start in products file here which is the only file where we really do something with the data and there let's take a closer look I do have my get request where I get all my Doc's and we can't improve that because if we send such a get request we clearly whoops without the idea again we clearly get back a response that is interesting to us it gives us all the IDS and we know that we can take the ID and appended at the end of the URL to get data for this object at but this is not necessarily something you know when you're a newcomer to this API so it would be nice if we could also provide a link here which you could then programmatically fetch to send another request to it and maybe we also want to send some metadata like the amount of items we fetched so overall I don't just want to return the docs here as the response I want to return more I'll get rid of the console log which I don't really need anymore and now I will create my response object here you can name this whatever you want and in this object I want if account for example and I will simply set is equal to Doc's length so that I give some meta information about the amount of elements we fetched thereafter I'll add a products property which now will be an array of all the products now there I'm not interested in this strange underscore underscore V thing which seems to be some internal thing so that is something I don't want to pass along I can make sure that I don't fetch it by adding some other method prior to exit the Select method where I can define which fields I want to select and you can pass a string here and there you can pass name price and underscore ID and this means I will fetch these fields and no other field and this is a great way of controlling which data you actually want to fetch so now if I attach Docs here it will be an array of talks without that strange underscore D thing and we can see this if we just save that and send again a get request to fetch all products now these are a new structure now we don't see the count field because I'm not using my new response constant here I should return that instead of the docs so now if I do that again you see now we got an object with count two products and then the products and then as I said would be interesting to also have more information on the individual product like the URL that leads us to the detail information for that product so for that I'll actually change my Doc's array here I can use the normal map method for that to basically map it into a new array there I'll get my individual document I fetched and I will return a new version of it now that new version will use all the old data and for that we could use the object spread operator if it is supported by the node.js version you're using but you can also map it manually to say name is doc name and price is dark price and then underscore ID is doc underscore ID but then also pass something like URL which could be a JavaScript object where we or maybe request which could be type where we say okay you can send a get request and this is just meta information you can write this in whichever way you want pass whichever information you want now I want to pass information about which kind of requests do you have to send to which URL to get more information about this object so here it would be a get request which you send to given URL that would be and now it's the URL of our service here so in my case is HTTP a localhost but of course you can also dynamically fetch this to get the ID off the service you are running on or you can of course also hard-code the domain in here which you're going to use in the end so I'm going to fetch my address here localhost 3000 to be precise but then you would have to connect to products slash and then dark underscore ID whoops should be dot ID now if I save this and I send a get request we get back dead extra information with the URL I can send a get request you and I can indeed do this by simply clicking on it where I get detailed information for dead given object so this is now how we should style this and how we should structure this this is a better response for getting all the documents and of course you can find you just totally to your needs now let's have a look at the AMA routes if we created a new object right now I simply return a message which is okay but maybe not this message so we could say created object or created product successfully though that is kind of a redundant message because we do have status code 200 one but still let's keep it then create a product make sense but I don't just want to paste in the result here instead because let's maybe first have a look because if I do send such a post request here with the body I have here without the sales price maybe if I sent this what I get back as a response is also again with this strange V thing and so on so what I could do is I could also simply return a new object here where may be manually mapped name to result name price to result price and ID to result ID but where I then also and my request object I used before where I set the type equal to get and the URL to the same URL as above to gift user an idea about where to say a subsequent request to get detailed information about that new object the one difference is of course that here I'm not accessing doc ID but result ID so this would now be a better response for creating products if we have a look this looks good now we get this type of response and feel free to continue on your own of course to practice this we can do the same for the other routes too like here when we get data about one single object if I do send such a get request here we also get back that we thing the rest actually might be fine though you could also pass some meta information about where to send a request to get a list of all objects maybe so that is something you can change on that get route for a single object so on this route here for one I can add select here to say I only want to name the price and the ID and then as I just mentioned you can adjust the response here to not just give back the product which is your document but also that request metadata where you say yeah you could also send a get request to a URL and that URL which be HDPE localhost / products to get a list of all products and of course you could pass also some description property where you say get all products so that it's clearer what you're doing here or use some identifiers like get all products that could be more machine readable I'll remove that but you can style this and set this up in whichever way you need it where you want it for your API it is something you should always keep in mind though you create descriptive api's if you plan on using them publicly if it's only for you you might not need that but if you want to create an API that's used by other people you should be clear about how to use it and you do that by using it like this and for that let's also do the same for patching here we obviously also update and we then return the result of that operation which isn't that meaningful it's just is the strange set of now so there I could also just pass nothing that's also valid or simply pass something like an object where we have a message product updated and then again our request object to know that you can send a get request queue a URL to get the details about the new product and that would be localhost / products / and then the ID which we fetch from our URL here so that would be a meaningful response for patching so let's try this out - if I want to send a patch request to this URL and there I do instead indeed set a meaningful body well let's do that on the first tab where I already configured this a bit better so let's grab some ID here which I want to patch let's turn this to a patch request and then remember here the body is array where we got a couple of objects describing the operations we want to do like here we would set the prop name property - let's say name we want to change the name of a product and then the value will be something more useful if I now send this I get back this updated response and I can send a get request to dis of course and fail oh because I of course should encode the port into that URL queue so that is something I also need to do up here where I return the data for a single Product ID so this should be the full domain of course so with that fixed let's try this again let's again patch this object here and then simply send a get request and now we get that data for this changed object and with that for deleting we also might do something comparable here we try to delete this object and if we succeed I can either send an empty object or again something with a message where I say product deleted and here I don't need to send in a link to the product because it was deleted but we could add our request object here maybe to show hey you could also send a post request to some other URL so here would be HTTP localhost 3,000 products to create a new product there you will need to send data and that data then would simply be in the form of having a name which is a string and price which is a number and with that we would give instructions what the request body should look like maybe we name this body therefore so now if we save this and we delete our object here we get back this language cells hey you can send a post request to this URL and if you pass that payload then you will create a new product so these are more meaningful responses and you can as I said fine-tune them to your needs you might need different responses obviously I think we spent enough time on that now one thing because just as I said I want to work on it's just application warning which you also might have seen and which you may be also asked about already now this is not a problem you could ignore it but we also can fix it by going back to the app.js file and there when we set up mangu is right when we connect it there I can also say Mongoose promise equals global promise to use the default nodejs promise implementation instead of the Mongoose one and with that if you restart the server you shouldn't get this anymore so now if you again start sending your requests and so on it should still work as before but you shouldn't get this deprecation warning now feel free to find you this more to adjust it to your needs and requirements I'm happy with the current state and I'd say in the next video we take a closer look at further evolving our data structures and also adding some orders and making sure that we save these in the database too
Info
Channel: Academind
Views: 114,030
Rating: undefined out of 5
Keywords: node, nodejs, rest api, restful, mongodb, mongoose, mongoose validation, tutorial
Id: CMDsTMV2AgI
Channel Id: undefined
Length: 18min 32sec (1112 seconds)
Published: Fri Dec 15 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.