Coding

Nest.js with MongoDB – Complete Example

  • 00:00:01 hi and welcome to this video in my first
  • 00:00:04 video about nest reyes link below the
  • 00:00:07 video of course I introduced you to nest
  • 00:00:09 Ches I explained what it is and we built
  • 00:00:11 our first little application a first
  • 00:00:14 little API with nest Ches now in this
  • 00:00:17 video we'll build up on the project we
  • 00:00:19 built there but the code is provided
  • 00:00:20 below the video in case you didn't
  • 00:00:22 follow along and we'll now connect this
  • 00:00:25 application to a real database we'll
  • 00:00:27 connect it to MongoDB and you will learn
  • 00:00:28 how it works and how you of course may
  • 00:00:30 use it in your own apps thereafter so
  • 00:00:32 let's dive in
  • 00:00:39 so in this video we're going to connect
  • 00:00:42 our little nest chase application which
  • 00:00:44 we worked on in the previous video which
  • 00:00:46 you should definitely check out link
  • 00:00:48 below the video of course we'll connect
  • 00:00:50 this application to a database to
  • 00:00:52 MongoDB now for that in case you don't
  • 00:00:56 know what MongoDB is I do have a link in
  • 00:00:58 the video or two links actually where I
  • 00:01:00 explain what Longwood EB is and also
  • 00:01:02 where I compare MongoDB which uses as no
  • 00:01:05 sequel solution to sequel databases so
  • 00:01:08 that might be helpful so for the rest of
  • 00:01:09 this video I'll just assume that you
  • 00:01:11 know what one would be B is and for this
  • 00:01:14 video I will use their cloud solution
  • 00:01:16 MongoDB Atlas that simply means that I
  • 00:01:18 get a fully managed database in the
  • 00:01:20 cloud you don't need to pay anything for
  • 00:01:23 that for the basic version of it at
  • 00:01:25 least of course there are paid versions
  • 00:01:26 but for the basic version which will
  • 00:01:28 suffice for this video you don't have to
  • 00:01:30 pay anything and long DB Atlas simply is
  • 00:01:32 very convenient to use make sure that we
  • 00:01:34 don't have to install anything locally
  • 00:01:35 and so on now here I'm already locked in
  • 00:01:39 with my account which I created up here
  • 00:01:41 with sign-in and there you can create a
  • 00:01:44 new cluster and you can basically leave
  • 00:01:46 all the defaults or choose the free care
  • 00:01:48 settings wherever you're prompted so
  • 00:01:50 that you get a cluster which you can run
  • 00:01:52 for free again for the things we're
  • 00:01:55 going to do here now cluster simply is
  • 00:01:58 like your cloud database for actually a
  • 00:02:00 collection of databases to to be
  • 00:02:02 concrete and we can connect to this
  • 00:02:04 cluster from inside our nest jeaious
  • 00:02:06 application now now for connecting a
  • 00:02:09 node application to MongoDB be that a
  • 00:02:12 local MongoDB instance or wherever
  • 00:02:14 MongoDB Atlas as it's here you got two
  • 00:02:17 main options version one is that you use
  • 00:02:19 the official driver you can find that
  • 00:02:21 driver by simply googling for MongoDB
  • 00:02:24 nodejs and what you'll find there in the
  • 00:02:26 end is this MongoDB package which is the
  • 00:02:29 official Longwood EP driver and you can
  • 00:02:31 use that in any node app and therefore
  • 00:02:33 also in an SAS application and that
  • 00:02:35 would allow you to manually connect to
  • 00:02:37 database and then run queries against
  • 00:02:39 the database definitely something you
  • 00:02:41 can do not bad but of course means you
  • 00:02:43 have to write all queries manually if
  • 00:02:46 you want to insert something you have to
  • 00:02:47 write the full query manually if you
  • 00:02:50 want to fetch data and so on there is a
  • 00:02:52 more convenient
  • 00:02:53 way of doing that and that's the way I
  • 00:02:55 will use here we'll use a package called
  • 00:02:57 Mongoose and you can find your official
  • 00:03:00 docs on Mongoose Jess calm Mongoose is a
  • 00:03:03 nodejs
  • 00:03:04 package which wraps the native driver so
  • 00:03:08 which wraps the one would he be packet
  • 00:03:10 we just had a look at but gives you more
  • 00:03:12 convenience functions to be precise it's
  • 00:03:14 a model focused packet where you work
  • 00:03:17 with models which in the end are
  • 00:03:19 JavaScript objects and then you can save
  • 00:03:21 something to the database through these
  • 00:03:23 objects or get some data from the
  • 00:03:25 database with the help of these objects
  • 00:03:27 you can check out the official Docs to
  • 00:03:29 learn all about this package and this is
  • 00:03:32 the package will now use as well now for
  • 00:03:35 that we first of all need to install it
  • 00:03:37 so here in the command prompt or a
  • 00:03:38 terminal in your project folder you can
  • 00:03:42 simply run npm install – – safe and then
  • 00:03:45 I will install Mongoose but there is an
  • 00:03:48 error package which I'll install there
  • 00:03:50 is a nest J's wrapper so we'll all
  • 00:03:52 install at nest Jaya slash Mongoose now
  • 00:03:55 this simply helps us use Mongoose in
  • 00:03:57 this app we wouldn't need it we could
  • 00:03:59 technically use Nair Mongoose without
  • 00:04:01 this nest J's package but with the nest
  • 00:04:04 as package we get improved typescript
  • 00:04:06 support we can inject things to make our
  • 00:04:10 lives easier so I would definitely
  • 00:04:11 recommend using both now with that
  • 00:04:15 installed let's set everything up and
  • 00:04:17 for that we first of all could connect
  • 00:04:20 to the database that seems like a
  • 00:04:21 logical first step I'll do this in the
  • 00:04:24 app module because you connect to the
  • 00:04:27 database by importing something from
  • 00:04:30 this Aetna's chase mongoose package and
  • 00:04:33 that's something which you do import
  • 00:04:36 there is the mongoose module the
  • 00:04:39 mongoose module can be used to set up a
  • 00:04:41 database connection and it makes sense
  • 00:04:43 to set this connection up in the app
  • 00:04:45 module which is our first module to run
  • 00:04:47 and to be loaded because I want to
  • 00:04:49 connect to the database as soon as
  • 00:04:51 possible when the server starts so here
  • 00:04:54 I'll now import mongoose module and
  • 00:04:58 there you call for root which is a
  • 00:05:00 method provided by this module your
  • 00:05:03 esthetic method to which you now pass
  • 00:05:05 your
  • 00:05:06 action string and that connection string
  • 00:05:09 if you're using MongoDB Atlas you can be
  • 00:05:13 found here under connect connect your
  • 00:05:15 application then it's this string here
  • 00:05:17 so I'll copy that string close that and
  • 00:05:20 then enter this here as a string now a
  • 00:05:23 couple of important things about that
  • 00:05:25 string this string includes the user
  • 00:05:27 name for which you want to connect and a
  • 00:05:29 password for this user name and both
  • 00:05:31 needs to be managed by you you can do
  • 00:05:33 that here in MongoDB Atlas under
  • 00:05:34 database access if you click on that you
  • 00:05:37 see your users there I actually want to
  • 00:05:39 use this Maximilian user so I'll change
  • 00:05:41 the user name easier to Maximilian but
  • 00:05:42 of course you could use any net user you
  • 00:05:44 want you just should make sure that it
  • 00:05:46 has at least read and write database
  • 00:05:48 access and I'll also set a password
  • 00:05:50 which I'll change after recording this
  • 00:05:53 so no need and copying it and I'll enter
  • 00:05:56 this password here you could use
  • 00:05:58 environment variables if you prefer that
  • 00:05:59 for our purposes here this hard-coded
  • 00:06:02 connection string will do at the end of
  • 00:06:04 this string you also to find the
  • 00:06:06 database you want to connect to because
  • 00:06:08 as I mentioned the cluster holds a
  • 00:06:10 combination or multiple databases and
  • 00:06:12 I'll use nest Jas demo as a database
  • 00:06:15 name the name is totally up to you if it
  • 00:06:17 doesn't exist yet it will be
  • 00:06:19 automatically created so instead we got
  • 00:06:22 the connection string setup and when we
  • 00:06:23 now start this application nest share
  • 00:06:26 should actually try to connect to our
  • 00:06:28 MongoDB server here now that's a nice
  • 00:06:31 first step but of course we can't do
  • 00:06:33 anything with that alone instead we now
  • 00:06:36 need to add code that allows us to add
  • 00:06:38 data to the database or to fetch data
  • 00:06:40 from there and since we're using the
  • 00:06:42 moongoose package we'll use the moon
  • 00:06:44 whose package for that because as I
  • 00:06:45 mentioned this mongoose package allows
  • 00:06:47 us to work with javascript object and it
  • 00:06:50 runs the database queries and sets them
  • 00:06:52 up behind the scenes so we don't have to
  • 00:06:54 write all these trees manually instead
  • 00:06:56 that's done for us so to say now for
  • 00:07:00 that you need to understand how mongoose
  • 00:07:01 works and of course you can check out
  • 00:07:03 the original docs to learn all about
  • 00:07:04 mongoose mongoose works with so-called
  • 00:07:07 models which are nhien blueprints for
  • 00:07:10 the javascript objects you then create
  • 00:07:11 which are these enriched JavaScript
  • 00:07:15 objects which represent your data for
  • 00:07:17 example a product object which is not
  • 00:07:19 just a product
  • 00:07:20 object based on a class like this which
  • 00:07:22 is just a bunch of properties but
  • 00:07:24 instead since Mongoose will help us
  • 00:07:26 create this object it will be an object
  • 00:07:28 with a lot of behind-the-scenes magic
  • 00:07:31 that will run queries automatically and
  • 00:07:33 so on
  • 00:07:33 now all these objects are based on these
  • 00:07:36 mongoose models and these models on the
  • 00:07:39 other hand are based on Mongoose schemas
  • 00:07:41 and a schema simply defines how a model
  • 00:07:44 should look like regarding the
  • 00:07:45 properties it has so therefore in this
  • 00:07:48 product model file
  • 00:07:50 I'll now actually add a new thing and
  • 00:07:55 we'll add such a scheme and verdad well
  • 00:07:57 first of all import everything as
  • 00:07:59 Mongoose from the Mongoose package
  • 00:08:04 and there we will now use Mongoose dot
  • 00:08:10 schema now I want to store an export
  • 00:08:13 this schema and I'll name it product
  • 00:08:16 schema and this will be the blueprint
  • 00:08:18 for the model which then is the
  • 00:08:20 blueprint for the concrete objects but
  • 00:08:21 that's just how Mongoose works there we
  • 00:08:24 create a new mangu schema so that's a
  • 00:08:25 constructor and now here we pass a
  • 00:08:28 JavaScript object where we define how a
  • 00:08:30 product object should look like and
  • 00:08:33 we're setting this up for Mongoose
  • 00:08:35 so to say now of course we'll have the
  • 00:08:38 same properties as down there except for
  • 00:08:40 the ID because we actually don't need
  • 00:08:43 the ID we'll have a ID which will be
  • 00:08:45 automatically generated by Mongoose and
  • 00:08:47 MongoDB so we'll only focus on the free
  • 00:08:50 other properties we'll have a title now
  • 00:08:52 without public because this is now a
  • 00:08:55 JavaScript object literal here this is
  • 00:08:58 not a class were defining with the help
  • 00:09:00 of typescript so we can't add public
  • 00:09:02 here instead this is a title and now for
  • 00:09:04 Mongoose there's something special you
  • 00:09:06 also have to define the type of data
  • 00:09:08 this is but you don't do this with these
  • 00:09:10 typescript types because Mongoose
  • 00:09:12 doesn't use typescript instead you do
  • 00:09:14 that with the default JavaScript types
  • 00:09:15 therefore of course it supports
  • 00:09:17 different types than typescript does and
  • 00:09:19 they're also sometimes written a bit
  • 00:09:20 differently for example they're written
  • 00:09:23 uppercase so if that's a string we have
  • 00:09:25 to define it with string like this and
  • 00:09:28 not string like this this is the
  • 00:09:29 typescript type this is a JavaScript
  • 00:09:31 type now besides the title we'll have
  • 00:09:35 the description which of course is a
  • 00:09:37 string and then the price and the price
  • 00:09:40 is a number but with a capital n now for
  • 00:09:44 Mongoose you can also be a bit more
  • 00:09:45 detailed than that you could pass an
  • 00:09:47 object instead of just a type name and
  • 00:09:49 there add a type property which
  • 00:09:51 describes the type and then in addition
  • 00:09:53 for example you could set require to
  • 00:09:55 true to indicate that this is a required
  • 00:09:58 field which always has to be provided
  • 00:10:00 and I will actually do that for all
  • 00:10:02 three fields here now we have our
  • 00:10:06 product schema and that's important step
  • 00:10:08 because now we can create a product
  • 00:10:10 model based on that schema now we do
  • 00:10:13 have a product model on there but this
  • 00:10:15 is not the model we'll continue to use
  • 00:10:17 and
  • 00:10:18 I'll come back to that in a second
  • 00:10:20 instead now we go to our products module
  • 00:10:23 and there we can now add a imports array
  • 00:10:27 because you set up a mongoose model with
  • 00:10:29 the help of mongoose module so again we
  • 00:10:32 import mongoose module from Aetna's
  • 00:10:37 chess mongoose like that and then here
  • 00:10:40 in the import now of the products model
  • 00:10:42 not of the app model I will setup
  • 00:10:45 mongoose module dot for feature and then
  • 00:10:49 has some data here now the idea here is
  • 00:10:53 that this will automatically allow us to
  • 00:10:55 then inject this model a to any file
  • 00:10:57 that needs it so you can share this
  • 00:10:59 model which you're creating with the
  • 00:11:01 help of dependency injection that is
  • 00:11:03 what mongoose module does for you it
  • 00:11:05 creates that model and makes it
  • 00:11:06 injectable it takes an array because you
  • 00:11:09 could define multiple models which are
  • 00:11:11 available for injection in this module
  • 00:11:14 so in this products module but here I
  • 00:11:16 only have one each model then is defined
  • 00:11:18 with a JavaScript object where you give
  • 00:11:21 that model and name name is up to you
  • 00:11:23 but of course it should make sense for
  • 00:11:25 the data you're managing so here I'll
  • 00:11:26 name it product and that has to be a
  • 00:11:29 string and then you have to point at the
  • 00:11:31 schema that defines how the data should
  • 00:11:33 look like for this model and that of
  • 00:11:36 course is our product schema here and
  • 00:11:39 for that you need to import product
  • 00:11:41 schema from the product model file
  • 00:11:45 so with that setup were defining this
  • 00:11:48 model we're making it injectable with
  • 00:11:49 the help of Mongoose now we can inject
  • 00:11:52 it into files where we want to work with
  • 00:11:54 it and that would be the product service
  • 00:11:56 of course because here we are for
  • 00:11:58 example creating a new product and right
  • 00:12:00 now we're doing this with our own model
  • 00:12:02 this will now change and we'll use the
  • 00:12:04 Mongoose model because that will allow
  • 00:12:06 us to create JavaScript objects but
  • 00:12:08 magical JavaScript object so to say
  • 00:12:10 where we can then also call a simple
  • 00:12:12 method to write it to the database and
  • 00:12:15 have Mongoose do the heavy lifting for
  • 00:12:16 us so all we have to do here is add a
  • 00:12:19 constructor because as I just said we
  • 00:12:21 can inject these models these mongoose
  • 00:12:23 models and q inject this model we now
  • 00:12:26 need to again import something from Ness
  • 00:12:31 j/s mongoose
  • 00:12:32 so from Aetna's J's mongoose we're
  • 00:12:35 importing and there we're importing the
  • 00:12:38 inject model decorator in the end which
  • 00:12:42 is you can use this in a constructor at
  • 00:12:44 inject model this simply tells nest
  • 00:12:48 chess that you want to inject a mongoose
  • 00:12:51 model q inject model you pass a string
  • 00:12:54 and that is the name of the model you
  • 00:12:56 want to inject here that's of course
  • 00:12:57 product here because I defined that
  • 00:13:00 product should be the name of my
  • 00:13:01 mongoose model here in the products
  • 00:13:04 module we have the product model setup
  • 00:13:06 here we can inject it here now you can
  • 00:13:09 store this in any argument you want like
  • 00:13:11 product model but I also want to use two
  • 00:13:16 types of shortcut off automatically
  • 00:13:18 storing this a property by adding an
  • 00:13:20 accessor in front of it
  • 00:13:21 and we can also add to read-only
  • 00:13:22 modifier here to make it really clear
  • 00:13:24 that we will never overwrite the value
  • 00:13:26 which is stored in the product model
  • 00:13:28 property here now this also has a type
  • 00:13:31 and this type is of type model which you
  • 00:13:35 have to import and you import that
  • 00:13:37 directly from Mongoose so not from nest
  • 00:13:40 Reyes mongoose but from just Mongoose
  • 00:13:42 you import model and model actually is a
  • 00:13:45 generic type because model is that base
  • 00:13:49 class Mongoose uses which holds all the
  • 00:13:51 magic for running the queries the
  • 00:13:53 concrete model then also needs to take
  • 00:13:55 your schema into account so what you
  • 00:13:57 pass here
  • 00:13:58 is now a description of how your model
  • 00:14:01 looks like that's something we're
  • 00:14:02 missing we're defining our schema here
  • 00:14:05 but that's not really a typescript thing
  • 00:14:08 here that's as I said just set up for
  • 00:14:11 mangu is using Java Script types and so
  • 00:14:13 on
  • 00:14:13 but we do have our own model here now we
  • 00:14:17 could turn this into an interface
  • 00:14:18 instead of a class the difference is
  • 00:14:20 that we now can't if a constructor we
  • 00:14:22 can't instantiate interfaces an
  • 00:14:24 interface is simply a type description
  • 00:14:26 if you will and therefore here we would
  • 00:14:28 now just have our properties like this
  • 00:14:32 so we can add all of the adds get rid of
  • 00:14:38 public here and now define an interface
  • 00:14:41 like this and ID will be auto-generated
  • 00:14:44 in the end and whilst this technically
  • 00:14:46 will be stored in an underscore ID
  • 00:14:48 property there will be an ID gather
  • 00:14:51 later which allows us to get the ID with
  • 00:14:54 just the ID Cillian that will return a
  • 00:14:56 string so that gather so we should have
  • 00:14:58 this as a product object which Mongoose
  • 00:15:02 creates for us and now in the product
  • 00:15:04 service here in the generic type for mod
  • 00:15:06 we can therefore refer to product and
  • 00:15:09 simply import product from product model
  • 00:15:11 as we're doing it before now we're
  • 00:15:13 injecting this product model which is
  • 00:15:17 created by Mongoose and now we can start
  • 00:15:20 using it and let's start using it for
  • 00:15:22 creating a new product now here we're
  • 00:15:25 creating a new product by calling new
  • 00:15:26 product now this should now be new this
  • 00:15:29 product model looks a bit strange but
  • 00:15:32 product model is a property hence we
  • 00:15:34 have to use this and then we can use it
  • 00:15:37 as a constructor again it's created by
  • 00:15:39 Mongoose and what Mongoose in the end
  • 00:15:41 creates here is a constructor function
  • 00:15:43 and that's basically the same as a class
  • 00:15:47 or follows the same idea and therefore
  • 00:15:51 we can call this or use this with the
  • 00:15:53 new keyword to create a new object based
  • 00:15:55 on this blueprint created by Mongoose
  • 00:15:57 behind the scenes now to product model
  • 00:16:00 we don't pass four different arguments
  • 00:16:04 though instead we pass a JavaScript
  • 00:16:06 object which should provide the fields
  • 00:16:09 we define in our schema so a title
  • 00:16:11 description and
  • 00:16:12 not an ID because that will be generated
  • 00:16:14 automatically so we don't need to create
  • 00:16:16 our own ID here instead we provide title
  • 00:16:19 here and title will of course hold the
  • 00:16:22 title value which we're getting we do
  • 00:16:24 the same for description which gets the
  • 00:16:27 desk value and price which gets the
  • 00:16:29 price value if you want you can shorten
  • 00:16:32 these assignments here where the key
  • 00:16:34 name and the value name is the same you
  • 00:16:37 can then use a types code shortcut here
  • 00:16:38 and in the end we'll MIT this value
  • 00:16:41 assignment behind-the-scenes this will
  • 00:16:43 be expanded to this syntax but it's a
  • 00:16:46 bit shorter for you to write so with dad
  • 00:16:48 here I'm setting up title description
  • 00:16:50 price on this mall I'm creating a new
  • 00:16:52 object based on this model which is
  • 00:16:54 stored a new product now we're no longer
  • 00:16:57 going to push this to some local array
  • 00:17:00 here instead we can now use new product
  • 00:17:03 and to save it to the database all you
  • 00:17:05 have to do is call save this save method
  • 00:17:09 was never defined by us it is provided
  • 00:17:11 by Mongoose instead and that's what I
  • 00:17:14 meant it's this magic behind the scenes
  • 00:17:15 since Mongoose creates this model it
  • 00:17:18 does not just wrap our schema but add
  • 00:17:20 these extra magic methods to it and
  • 00:17:23 these extra magic methods like save will
  • 00:17:25 create a full Mongo DB query behind the
  • 00:17:28 scenes which saves our data to the
  • 00:17:30 database now of course here we want to
  • 00:17:33 return the product ID though for that
  • 00:17:35 it's important to note that safe in the
  • 00:17:37 end will return a promise so here we can
  • 00:17:40 use then or use a single wait which is
  • 00:17:43 what I'll do simply at the async keyword
  • 00:17:46 and set in front of insert product now
  • 00:17:48 we can await this case you don't know
  • 00:17:50 that syntax it's an alternative to using
  • 00:17:52 then here in the end it makes the code
  • 00:17:55 more look more like a normal synchronous
  • 00:17:58 code it's still using promises in their
  • 00:18:00 product now we'll also implicitly return
  • 00:18:02 a promise we can add async in front of
  • 00:18:05 here and therefore use the await keyword
  • 00:18:07 to wait for this promise to complete
  • 00:18:09 before the next line executes behind the
  • 00:18:11 scenes the code after this line simply
  • 00:18:14 gets wrapped into an invisible then
  • 00:18:16 block here so here I await the result
  • 00:18:20 and then I get my well result here and
  • 00:18:23 for the moment I'll not return any
  • 00:18:26 thing here but instead I'll simply
  • 00:18:29 console.log results so that we can see
  • 00:18:32 what's in there actually it will return
  • 00:18:34 something but I'll return a hard-coded
  • 00:18:35 string for now which is of course not
  • 00:18:38 the ID we're getting back with all of
  • 00:18:41 that let's give it a try and we can run
  • 00:18:43 this with NPM run start : death to bring
  • 00:18:46 up that development server let's see
  • 00:18:48 whether that works the way it should
  • 00:18:51 work
  • 00:18:53 so it's trying to connect and it's
  • 00:18:56 having issues here connecting reason for
  • 00:18:58 that is on MongoDB Atlas setting up the
  • 00:19:02 user is one thing you always need to
  • 00:19:04 make sure that you whitelist your local
  • 00:19:07 IP you have to whitelist your local IP
  • 00:19:10 if you're not doing that then MongoDB
  • 00:19:13 Atlas will block access from your IP
  • 00:19:15 that's a security mechanism so make sure
  • 00:19:17 the under network access you add your
  • 00:19:19 local IP now wait for these changes to
  • 00:19:22 be active before you try again in the
  • 00:19:26 meantime I'll already bring up postman
  • 00:19:29 here because will of course need postman
  • 00:19:32 to send post requests to create a new
  • 00:19:34 product for example here I already got
  • 00:19:36 it prepared it's the same post request I
  • 00:19:38 sent in the last video so I got it
  • 00:19:41 prepared there's now also finished now
  • 00:19:43 let's try running this again now it
  • 00:19:45 should be able to connect to MongoDB
  • 00:19:46 Atlas and yeah that's looking way better
  • 00:19:50 this is up and running now let me send
  • 00:19:53 that post request I sent this I get back
  • 00:19:57 no ID which kind of makes sense when I
  • 00:20:01 do get here in the console looks
  • 00:20:02 promising though I get this object being
  • 00:20:04 printed and there we see our data and we
  • 00:20:07 see underscore ID which I mentioned
  • 00:20:09 before is this auto-generated ID stored
  • 00:20:12 in the underscore ID field and if we now
  • 00:20:14 have a look into our database here in
  • 00:20:17 MongoDB Atlas under clusters collections
  • 00:20:21 you can also download MongoDB comp s and
  • 00:20:23 connect that to your cluster if you
  • 00:20:25 can't access the collections like this
  • 00:20:27 but there I can look into my databases
  • 00:20:29 and into the data store there and there
  • 00:20:32 if I go to the nest chess demo there's
  • 00:20:34 the products collection it has one
  • 00:20:36 document so that looks good because we
  • 00:20:38 we entered one document and there indeed
  • 00:20:40 I see the document I just added so
  • 00:20:42 saving works and as you see we had some
  • 00:20:44 initial setup but now it's really simple
  • 00:20:47 it's just this call of the save method
  • 00:20:49 now we also know we're getting back a
  • 00:20:51 result there we have the ID and
  • 00:20:53 underscore ID but as I mentioned the
  • 00:20:55 result will actually also have an ID
  • 00:20:58 getter so what we can return here is
  • 00:21:00 result dot ID in the end because we know
  • 00:21:04 that this ID field will be available
  • 00:21:09 so now if I save this again and I give
  • 00:21:13 this another try with a first product
  • 00:21:15 this is our first product and sent this
  • 00:21:18 I still get back ID nothing here so we
  • 00:21:22 still have a problem so look at the
  • 00:21:25 controller
  • 00:21:28 we should be getting our generated ID
  • 00:21:30 but yeah there is one issue and it's it
  • 00:21:33 might be tricky to spot as I explained
  • 00:21:36 save returns a promise right and I'm
  • 00:21:39 using async await this Mexico to look
  • 00:21:41 like it's synchronous code but it isn't
  • 00:21:43 as I said the line after this line is
  • 00:21:46 simply wrapped into a van block now
  • 00:21:49 since we return here returning inside of
  • 00:21:51 a van block typically wouldn't return
  • 00:21:53 for the overall function so what happens
  • 00:21:55 here is that this technically here
  • 00:21:58 returns a new promise which the overall
  • 00:22:00 function returns at that overall promise
  • 00:22:02 will then yield the data you returned
  • 00:22:04 here so this overall function returns a
  • 00:22:06 promise hence in the controller where we
  • 00:22:09 reach out to insert product in their
  • 00:22:11 product now returns a promise we also
  • 00:22:13 see that here now since this returns a
  • 00:22:16 promise here we have to handle this IVA
  • 00:22:18 with then or by also using async await
  • 00:22:22 here and I'll do the latter so add a
  • 00:22:24 Singh here and then I'll wait this and
  • 00:22:26 now we get this back because now this
  • 00:22:28 will wait for this promise to complete
  • 00:22:30 before it didn't wait it did send the
  • 00:22:33 response immediately before this promise
  • 00:22:35 completed which is why we had no idea in
  • 00:22:37 there so that's an important adjustment
  • 00:22:40 and now whenever adjusting I'll make is
  • 00:22:42 in a product service type script isn't
  • 00:22:45 fully able to understand what insert
  • 00:22:47 product yields in the end it's a promise
  • 00:22:49 but it doesn't know which day that this
  • 00:22:50 promise resolves to we know that it of
  • 00:22:53 course will resolve to a string so what
  • 00:22:56 we could do here is we could add a
  • 00:22:58 string here and now we would have the
  • 00:23:01 correct type and Firenze here which
  • 00:23:03 definitely improves our code a little
  • 00:23:05 bit so with it let's save it and let's
  • 00:23:08 give it one more try let's do a second
  • 00:23:10 test with a second product here and if I
  • 00:23:13 sent this now we get back the newly
  • 00:23:16 generated ID here so this is now looking
  • 00:23:18 better and if we have a look at our
  • 00:23:19 collection and we refresh this here
  • 00:23:25 now we see free documents in there so
  • 00:23:27 that's how we can save data what about
  • 00:23:29 getting data in the products controller
  • 00:23:32 we have get all products and that's what
  • 00:23:34 I want to start with so we need to work
  • 00:23:35 on get products in the product service
  • 00:23:37 get products before just returned our
  • 00:23:40 array now that's of course too simple
  • 00:23:42 because now it's not just about
  • 00:23:44 returning an array instead now we want
  • 00:23:47 to return well the result from our
  • 00:23:49 database now again for this we can work
  • 00:23:53 with this product model so with this
  • 00:23:56 product model but now we don't create a
  • 00:23:58 new object based on it but this model
  • 00:24:01 being created for us by Mongoose also
  • 00:24:04 has some magic static methods for
  • 00:24:06 example the find method which allows us
  • 00:24:08 to well find data so now find will also
  • 00:24:13 get us some data and find although
  • 00:24:15 should yield a promise so let's again
  • 00:24:18 use async and a weight and let's see
  • 00:24:21 what our result here is let's
  • 00:24:24 console.log it so that we can get an
  • 00:24:27 impression so let's call the lock result
  • 00:24:30 here go back to get and get all our data
  • 00:24:35 now here we get an empty array of course
  • 00:24:37 because we haven't adjusted the our
  • 00:24:39 logic but in the console here we indeed
  • 00:24:41 see an array with free documents so
  • 00:24:45 that's looking good now since we know
  • 00:24:47 that result is that array products looks
  • 00:24:50 like a more fitting name here you can of
  • 00:24:53 course name this whatever you want and I
  • 00:24:55 don't want to log it but I want to
  • 00:24:56 return it so here I want to return my
  • 00:24:59 array of products in the end now one
  • 00:25:02 important adjustment by the way find
  • 00:25:05 does work like this but actually does
  • 00:25:08 return a real promise it only does so if
  • 00:25:10 you call exact after this it's a tiny
  • 00:25:12 improvement which I would recommend
  • 00:25:14 doing viryx otherwise as well but this
  • 00:25:16 gives you a real promise and therefore
  • 00:25:18 simply is a a bit better so now we still
  • 00:25:22 get our products here we could now
  • 00:25:24 return this products array which we just
  • 00:25:27 fetched we don't need to copy it anymore
  • 00:25:28 because it's created and new here
  • 00:25:32 anyways it's a fetch from database and a
  • 00:25:34 new products array is created here so no
  • 00:25:36 real need to copy it we're not managing
  • 00:25:38 here in memory so we can return our
  • 00:25:41 products and in the products controller
  • 00:25:43 where we get all products this now of
  • 00:25:45 course all the yields a promise promise
  • 00:25:47 off type any because again it's not able
  • 00:25:50 to infer what products looks like we
  • 00:25:53 think we can be clear here we know that
  • 00:25:55 it's a product array so product is my
  • 00:25:58 own interface here towards describes how
  • 00:26:00 a single product looks like and that's
  • 00:26:01 our array of products so now types could
  • 00:26:03 knows that get products returns a
  • 00:26:05 promise which eventually yields a list
  • 00:26:07 of products an array of products so in
  • 00:26:09 the products controller since this now
  • 00:26:12 returns a promise which eventually gives
  • 00:26:13 us the products array this has to be a
  • 00:26:17 sync or you can always of course use
  • 00:26:20 then and return a promise here but here
  • 00:26:24 I'll go with a sync and then all I'll
  • 00:26:30 wait my products here and then simply
  • 00:26:32 return products like this now let's see
  • 00:26:35 whether that works the way it should if
  • 00:26:37 we save this and I resent this request
  • 00:26:41 now I get back my products here now one
  • 00:26:45 tiny adjustment you see the ideas stored
  • 00:26:47 an underscore ID and we have two strange
  • 00:26:51 we thing here and I actually would like
  • 00:26:54 to have ID here instead of underscore ID
  • 00:26:56 that's relatively easy to do here in the
  • 00:26:58 service we can transform the data we're
  • 00:27:00 turning a little bit so that really fits
  • 00:27:02 our product description because now our
  • 00:27:04 product interface we're saying that a
  • 00:27:06 product has ID field not underscore ID
  • 00:27:08 and then only title description price
  • 00:27:10 and whilst it technically works even if
  • 00:27:12 we have the extra underscore we thing
  • 00:27:14 and a different ID name it's not really
  • 00:27:16 what I want to have so let's go back to
  • 00:27:19 the service and let's transform the data
  • 00:27:20 before we return it we can do that here
  • 00:27:23 by calling products map because product
  • 00:27:26 is an array so we can call the built in
  • 00:27:28 map method which is provided by
  • 00:27:30 JavaScript this takes a function which
  • 00:27:32 it runs on every element in this array
  • 00:27:33 which we get as argument therefore and
  • 00:27:36 we have to return a new element and the
  • 00:27:38 new element here should be a new object
  • 00:27:41 which should adhere to our product
  • 00:27:44 interface or which basically be based on
  • 00:27:47 our product interface so I want to have
  • 00:27:49 ID we get that from prot by
  • 00:27:51 calling ID as I said there is a quatre
  • 00:27:53 which gives us that ID it's not a
  • 00:27:55 property but I gather which Mongoose
  • 00:27:57 gives us on these object it returns then
  • 00:28:00 I want to have a title and that is broad
  • 00:28:03 dot title
  • 00:28:07 and I should wrap this here in brackets
  • 00:28:10 by the way to have a valid syntax where
  • 00:28:13 we just return an object in this inline
  • 00:28:15 arrow function then we have a
  • 00:28:17 description with prot description and we
  • 00:28:23 have a price with prot price so now I am
  • 00:28:28 mapping the data we're fetching from the
  • 00:28:29 database into this new format which I'd
  • 00:28:31 then return and now if we save dad and
  • 00:28:34 we fetch our data again now we see we
  • 00:28:36 have just ID here and we don't have that
  • 00:28:38 underscore underscore V thing a minor
  • 00:28:41 thing but still definitely something
  • 00:28:43 that makes sense here I guess so instead
  • 00:28:46 let's move on let's make sure we can
  • 00:28:47 also fetch a single product for dad we
  • 00:28:50 have to get single product method of
  • 00:28:51 course we don't call this find product
  • 00:28:55 anymore or we might but in this find
  • 00:28:59 product we definitely don't want to find
  • 00:29:01 a product in our array anymore in our
  • 00:29:03 local array but instead we want to find
  • 00:29:05 a product in the database and actually
  • 00:29:09 we don't really need find product like
  • 00:29:10 this because the index and so on that's
  • 00:29:13 not something we really need here so
  • 00:29:18 I will change this this will now just
  • 00:29:22 return a product nothing else and for
  • 00:29:26 that up here where we get our product I
  • 00:29:30 want to reach out or I want to use this
  • 00:29:32 product model again this model created
  • 00:29:34 by Mongoose and there again fine but now
  • 00:29:36 a slight variation of that find one find
  • 00:29:40 one is extra method that exists for
  • 00:29:42 cases where you know that you really
  • 00:29:43 need only one item that allows Mongoose
  • 00:29:46 to not scan all your items in the
  • 00:29:48 database but stop after it found the
  • 00:29:50 first one now found the first one that's
  • 00:29:53 something I'm saying because now we'll
  • 00:29:55 add a condition to find one we could
  • 00:29:56 have added one to find as well to only
  • 00:29:59 find products with a title of something
  • 00:30:02 or with a price of something and you can
  • 00:30:05 learn all about the different ways of
  • 00:30:07 writing queries and writing conditions
  • 00:30:09 in my mom would EB course if you want
  • 00:30:11 link to dead all below the video but
  • 00:30:13 here we'll have a very simple condition
  • 00:30:15 we'll find one we'll find one by ID for
  • 00:30:19 dad Mongoose actually has an even batter
  • 00:30:20 method we can use fine by ID which is a
  • 00:30:24 method provided by Mongoose where we
  • 00:30:26 just pass in the ID which we're getting
  • 00:30:28 as an argument here and then Mongoose
  • 00:30:29 will find us this element in the
  • 00:30:31 database and return it now of course
  • 00:30:34 this is asynchronous so let's add the
  • 00:30:37 async keyword and then await the result
  • 00:30:40 here and therefore here we don't return
  • 00:30:42 a product but in the end a promise which
  • 00:30:45 yields a product the correct type
  • 00:30:47 description would be this and here we
  • 00:30:51 get our data
  • 00:30:52 now if product is not the fine
  • 00:30:54 thereafter we still can throw this
  • 00:30:56 exception still make sense at this point
  • 00:30:58 here but here of course I'll now just
  • 00:31:01 return product though now just as before
  • 00:31:04 the product we're fetching would look a
  • 00:31:06 bit different it would have underscore
  • 00:31:08 ID ins on so let's actually return a new
  • 00:31:11 object here where ideas product ID title
  • 00:31:16 is product title description is product
  • 00:31:19 description
  • 00:31:23 and price is product price and now what
  • 00:31:28 we have here is again a transformed
  • 00:31:30 object which looks like our product
  • 00:31:32 interface so let's define product helper
  • 00:31:35 method we can now use that here in
  • 00:31:38 insert not an insert excuse me in get
  • 00:31:40 single product of course this fine
  • 00:31:42 product we no longer need to access the
  • 00:31:44 first element of the return data because
  • 00:31:46 we're not returning a tuple or an array
  • 00:31:48 anymore
  • 00:31:48 we returning a promise instead so
  • 00:31:51 instead of accessing this which has to
  • 00:31:53 go let's Robert turn this into a async
  • 00:31:56 method so that we can use our weight
  • 00:31:58 here to find a product store that in
  • 00:32:01 product and then return it no need to
  • 00:32:03 copy at first we can do it like this and
  • 00:32:06 yeah that should be good now to avoid
  • 00:32:08 errors for the moment down there I'll
  • 00:32:12 comment out the code in update product
  • 00:32:15 so that we can save and test this
  • 00:32:17 without the app thrashing so let's give
  • 00:32:20 it a try let's try fetching a single
  • 00:32:22 product and for this we can copy such an
  • 00:32:24 ID here and then go to this get method
  • 00:32:27 where we fetch a single product enter
  • 00:32:29 the ID and hit send that's looking good
  • 00:32:32 now let's try an ID which doesn't exist
  • 00:32:34 by simply modifying this slightly and we
  • 00:32:38 get an error here now we're getting this
  • 00:32:40 error because cause to object that you
  • 00:32:42 failed that part ID for model product
  • 00:32:44 and yet the problem here is that fine by
  • 00:32:46 ID expects a valid Mongoose ID and this
  • 00:32:50 isn't a valid Mongoose or a valid
  • 00:32:52 MongoDB ID and it can already tell that
  • 00:32:55 this is not valid so what we should do
  • 00:32:57 here is we should wrap this into a
  • 00:32:59 try-catch block to catch such errors as
  • 00:33:02 we're having it here and then handle it
  • 00:33:04 for example here to still throw our own
  • 00:33:08 not found exception to return a better
  • 00:33:11 error message instead of have our server
  • 00:33:13 crash of course that means that product
  • 00:33:16 isn't always set so let's set product to
  • 00:33:19 a variable here and override it here in
  • 00:33:21 try-catch so that even after this try
  • 00:33:24 catch block we always have a product it
  • 00:33:26 might just be undefined which were
  • 00:33:27 handling here and now let's try saying
  • 00:33:30 this request again and now we get a 404
  • 00:33:33 error now let's try using a valid
  • 00:33:35 MongoDB database but still one which
  • 00:33:38 doesn't
  • 00:33:38 and we get a 404 error in this case as
  • 00:33:41 well and for a valid ID we still get the
  • 00:33:44 product so fetching single products and
  • 00:33:47 handling errors all the works let's now
  • 00:33:50 move on to the next method which is for
  • 00:33:53 updating a product now for updating a
  • 00:33:55 product I'm calling update product in my
  • 00:33:58 service and an update product in the
  • 00:34:00 service in the end what we're doing is
  • 00:34:01 we're first of all fetching the product
  • 00:34:04 from the database we're thus far from
  • 00:34:06 the local array but now we'll have to
  • 00:34:08 fetch it from the database and then we
  • 00:34:10 can edit this product and save it back
  • 00:34:13 to the database that's the plan
  • 00:34:14 updating is super simple with Mongoose
  • 00:34:17 first of all for that you fetch your
  • 00:34:19 item so in this case our product and
  • 00:34:21 here we can simply use our find product
  • 00:34:24 helper method where we pass the ID which
  • 00:34:26 is the product I would you were
  • 00:34:28 extracting here now of course find
  • 00:34:30 product returns a promise so we could
  • 00:34:33 add a van block or add async and then
  • 00:34:35 I'll wait this and now we have our
  • 00:34:37 product here now that's nice we got our
  • 00:34:41 product in in this case here now we want
  • 00:34:44 to update this product and now updating
  • 00:34:47 is really simple in Mongoose we can
  • 00:34:48 simply edit this product object here by
  • 00:34:51 overriding the data we want to override
  • 00:34:53 and then just saving it back to the
  • 00:34:55 database so we got our product here
  • 00:34:57 previously we copied that now there is
  • 00:35:00 no real need because this is a newly
  • 00:35:01 created object anyways it fetches the
  • 00:35:03 data from the database and creates a new
  • 00:35:05 object so no need to copy it instead
  • 00:35:08 I'll name it updated product remove this
  • 00:35:11 line here and now we're editing the
  • 00:35:13 updated product and now what I meant is
  • 00:35:15 that we just have to say updated product
  • 00:35:18 save at least normally we could here the
  • 00:35:22 problem is that find product in the end
  • 00:35:25 does not return the Mongoose object
  • 00:35:29 which is created here but our own object
  • 00:35:33 which adheres to our product description
  • 00:35:37 and that's not really what I want to
  • 00:35:39 have here because well this doesn't have
  • 00:35:42 a safe method and indeed it doesn't so
  • 00:35:45 to still use this helper method would
  • 00:35:47 all do here's all not return my own
  • 00:35:50 product here but allons
  • 00:35:52 that just returned the product which
  • 00:35:53 Mongoose fetched and created here
  • 00:35:55 because it will be that object that has
  • 00:35:57 all our data but that also has this mom
  • 00:35:59 whose magic behind the scenes so here we
  • 00:36:02 don't want to return a promise with with
  • 00:36:04 our product as we define it here just as
  • 00:36:07 interface but instead we kind of need to
  • 00:36:09 let typescript know that our product
  • 00:36:11 here has these properties but is
  • 00:36:14 actually based on the Mongoose model
  • 00:36:19 class so to say so on the base class
  • 00:36:22 every Mongoose model has and right now
  • 00:36:25 typescript doesn't notice but to let it
  • 00:36:27 know we can install one extra package
  • 00:36:29 here with npm install' – – safe def and
  • 00:36:32 that's the ad types mongoose package
  • 00:36:35 this ads type annotations for Mongoose
  • 00:36:38 and helps us with working with this
  • 00:36:40 Mongoose package with that added here on
  • 00:36:44 our interface we can add extend and
  • 00:36:47 extend Mongoose dot document now extends
  • 00:36:51 is a keyword you might know from classes
  • 00:36:53 in typescript you can also extend
  • 00:36:55 interfaces and this means that our
  • 00:36:57 interface here is based on this based
  • 00:36:59 interface your document is an interface
  • 00:37:02 provided by mongoose hence Mongoose dot
  • 00:37:04 document we're importing everything
  • 00:37:06 under this mongoose package up there and
  • 00:37:08 then we extend this mongoose document
  • 00:37:11 interface and we add our own properties
  • 00:37:13 to it and with this adjustment made in
  • 00:37:16 the product service we get rid of this
  • 00:37:18 save error because now it's clear to
  • 00:37:20 drive script that updated product is
  • 00:37:23 nian based on a constructor on this
  • 00:37:25 model which has our own data description
  • 00:37:28 title and price but which also has all
  • 00:37:30 these mongoose magic methods and
  • 00:37:33 properties and now for a get single
  • 00:37:36 product we need to make a slight
  • 00:37:37 adjustment to return proper data I'll do
  • 00:37:39 the conversion here and set this to
  • 00:37:43 product ID title to product title
  • 00:37:48 description to product description
  • 00:37:54 and prize to product price so now I'm
  • 00:37:57 converting that data here and get single
  • 00:37:59 product and an update product now find
  • 00:38:02 product returns as a mongoose model
  • 00:38:04 object in the end and now updated
  • 00:38:06 product which we get from find product
  • 00:38:08 which is our helper method is such an
  • 00:38:10 object created by mongoose
  • 00:38:12 therefore it wraps our data but it also
  • 00:38:14 has the Mongoose helper methods and
  • 00:38:16 therefore now we can call save and now
  • 00:38:18 Mongoose automatically tracks all the
  • 00:38:20 changes we did so for example that we
  • 00:38:22 maybe change the title or maybe changed
  • 00:38:24 the description or all of that and then
  • 00:38:27 when we call save again it won't enter a
  • 00:38:29 new document but since we're doing this
  • 00:38:31 on an existing one which already has an
  • 00:38:33 ID which was fetched from the database
  • 00:38:35 since we're doing this in an existing
  • 00:38:37 one it will update the existing one in
  • 00:38:39 the database and now a safe will
  • 00:38:41 automatically sent the right query to
  • 00:38:43 write that update to the database so if
  • 00:38:46 we save this let's quickly check if
  • 00:38:49 getting a single product still works yes
  • 00:38:52 it does and now let's use that ID here
  • 00:38:55 together with patch to update a product
  • 00:38:57 so here I want to update this product
  • 00:38:59 with a first test is the first product
  • 00:39:01 and the new data I send is an updated
  • 00:39:04 title and a new price
  • 00:39:05 so let's it send here and I get ok I
  • 00:39:10 forgot something of course update
  • 00:39:13 product returns a promise now because
  • 00:39:15 we're using async await hence in the
  • 00:39:17 controller we should also in update
  • 00:39:20 product either use then or add async
  • 00:39:23 here and then I'll wait this before we
  • 00:39:28 return anything but what if we returned
  • 00:39:30 null anyways so this is still a correct
  • 00:39:32 change to make so that we only send the
  • 00:39:34 response once this is done and not too
  • 00:39:36 early especially if this should crash we
  • 00:39:38 would otherwise send two responses which
  • 00:39:40 isn't a good idea but to see whether it
  • 00:39:42 worked let's go to the collection and
  • 00:39:44 let's refresh our database in our
  • 00:39:47 collection here and load documents again
  • 00:39:49 and what we see is that the title was
  • 00:39:52 updated and the price as well now let's
  • 00:39:54 see what happens if we try this on a
  • 00:39:56 document that does not exist we get a
  • 00:39:59 404 error that makes sense and if I
  • 00:40:01 update a different product let's say
  • 00:40:04 this one a third test which still has a
  • 00:40:07 third
  • 00:40:07 test as a title in the database if we
  • 00:40:10 send an update there so for this ID and
  • 00:40:13 I changed description this is a brand
  • 00:40:21 new description and I sent this
  • 00:40:28 okay now let's reload our documents here
  • 00:40:31 and see whether that worked
  • 00:40:35 brand-new description so that worked we
  • 00:40:37 can of course also validated here by
  • 00:40:40 getting that single product and we see
  • 00:40:42 it here as well so this is all working
  • 00:40:44 the missing piece is removing a product
  • 00:40:47 there we call delete product in a
  • 00:40:49 service so let's go to the service to
  • 00:40:51 delete product here we find a product
  • 00:40:54 because we needed the index of the
  • 00:40:56 product to then remove it from our array
  • 00:40:58 now this will be done in a totally
  • 00:41:00 different way of course we'll still work
  • 00:41:03 with promises let's add a sync and let's
  • 00:41:07 now use our product model again and on
  • 00:41:10 that product
  • 00:41:10 model here we can now call delete one to
  • 00:41:14 delete one element and there we have to
  • 00:41:18 pass in a filter criteria which is a
  • 00:41:20 JavaScript object where you would define
  • 00:41:22 the key by what you want to fall through
  • 00:41:24 like the ID and then the value for that
  • 00:41:28 key in this case prod ID of course and
  • 00:41:31 this of course returns a promise promise
  • 00:41:35 at least if we call a X like behind it
  • 00:41:38 it works without that as well but the
  • 00:41:41 batter should also do that here on find
  • 00:41:44 by ID by the way and now we are waiting
  • 00:41:46 for this to be deleted then here we
  • 00:41:50 don't really have to return anything
  • 00:41:52 just one two well wait for this to
  • 00:41:54 finish in the end this should now delete
  • 00:41:57 a product where the idea is like product
  • 00:42:00 ID and in the products controller here
  • 00:42:03 under removed product we should now also
  • 00:42:05 add async and I'll wait this operation
  • 00:42:08 and then we can return now so let's get
  • 00:42:13 a single product like this one here that
  • 00:42:15 still works and now let's send a delete
  • 00:42:17 request for that ID like this so that
  • 00:42:21 looks good if I now go back and I try to
  • 00:42:23 get data for that single product that
  • 00:42:26 still works though and if i refresh here
  • 00:42:31 nothing was removed the reason for that
  • 00:42:35 oh yeah is ID now ID as I said is a
  • 00:42:39 getter we can use on that object
  • 00:42:42 mongoose crates for us to get the ID
  • 00:42:44 store in the database in the database is
  • 00:42:46 stored on underscore ID though so we
  • 00:42:48 should also use underscore ID here not
  • 00:42:51 ID because here we have to use the key
  • 00:42:53 as it's stored in the database so let's
  • 00:42:56 try it again with underscore ID in
  • 00:42:58 delete product send this request again
  • 00:43:02 and it works and if I now refetch this
  • 00:43:05 now we get not found which makes more
  • 00:43:07 sense because now if we update this here
  • 00:43:10 we shouldn't find the data here either
  • 00:43:13 now what you might have noticed is that
  • 00:43:15 before when we had the wrong criteria
  • 00:43:18 here we still weren't made aware of this
  • 00:43:21 right so that this succeded is not
  • 00:43:23 something we found out or we didn't find
  • 00:43:26 out that it failed actually so it would
  • 00:43:28 be nice of course to return a error if
  • 00:43:30 it fails for that let's get the result
  • 00:43:33 and console.log the result to get an
  • 00:43:35 idea of what we're getting back when
  • 00:43:36 this fails for example so here in the
  • 00:43:39 lead product I'm logging the result and
  • 00:43:41 now if I try to delete that same product
  • 00:43:43 which I just deleted which therefore
  • 00:43:44 isn't there anymore here we get a 200
  • 00:43:47 response which doesn't make that much
  • 00:43:48 sense but in the response but in the
  • 00:43:51 result we're getting here we see we get
  • 00:43:54 a little bit of output and we find
  • 00:43:56 information about the operation which
  • 00:43:58 was done for example there we have a
  • 00:44:00 deleted count which is zero or generally
  • 00:44:03 n which is the number of affected
  • 00:44:05 documents which is zero and if on the
  • 00:44:08 other end I use an our document like
  • 00:44:09 this one which does exist and I delete
  • 00:44:12 this then you will see that in the log
  • 00:44:16 we have deleted count 1 and also N 1 so
  • 00:44:20 this is our indicator for whether
  • 00:44:21 something was deleted or not so here we
  • 00:44:23 can check if result n is greater than
  • 00:44:27 zero then we know it's exceeded or if
  • 00:44:29 it's equal to zero then we know it
  • 00:44:31 failed so here we could then throw a new
  • 00:44:35 exception then you will not found
  • 00:44:38 exception again because it probably felt
  • 00:44:40 because we didn't find a product so a
  • 00:44:43 wolf road is if we didn't find a
  • 00:44:45 so that we returned a correct error
  • 00:44:47 message if well we indeed failed to
  • 00:44:49 delete the product so let's save that
  • 00:44:53 and I'll rerun that query for that
  • 00:44:56 product which doesn't exist anymore and
  • 00:44:58 now we get 404 and now if I delete my
  • 00:45:01 last product which should still exist
  • 00:45:04 whoops and I use this as ID here we get
  • 00:45:08 200 and if I try it again because now it
  • 00:45:10 was deleted we get 404 I now get all
  • 00:45:12 products we should get nothing because
  • 00:45:14 well there are no products anymore so
  • 00:45:17 that is how you can store or manage your
  • 00:45:20 data with the help of MongoDB it also
  • 00:45:22 means that in the product service we can
  • 00:45:24 of course get rid of that private
  • 00:45:26 products array which we now don't need
  • 00:45:27 anymore
  • 00:45:28 and I hope that it's clear how you now
  • 00:45:30 generally can work with MongoDB here
  • 00:45:33 with the help of Mongoose from inside of
  • 00:45:35 your nest Reyes application in general
  • 00:45:37 whatever you learn about MongoDB and
  • 00:45:39 Mongoose can be used in the same way
  • 00:45:41 here in SAS
  • 00:45:42 the most important difference to a
  • 00:45:44 normal node Express app is regarding how
  • 00:45:47 you set up your schema and more
  • 00:45:49 importantly your model with for a
  • 00:45:51 feature and that you can then simply
  • 00:45:52 inject your model and and work with it
  • 00:45:54 you could also work with Mongoose just
  • 00:45:57 as you know it from node Express manage
  • 00:45:59 everything manually instead of using
  • 00:46:00 injections on and that would all work
  • 00:46:02 but of course if you have the tools then
  • 00:46:05 this approach makes sure you stay more
  • 00:46:07 in the nest J's world and that is never
  • 00:46:11 a bad thing I hope this was helpful
  • 00:46:13 definitely share your thoughts and ideas
  • 00:46:15 in the comments I hope you like this
  • 00:46:17 video bye