1 00:00:02,300 --> 00:00:08,720 Now with our basic interactions setup, we have to optimize our code a bit and move it into a more realistic 2 00:00:08,720 --> 00:00:09,910 setup. 3 00:00:10,080 --> 00:00:17,660 Now for that more realistic setup, I'll create a new file next to app.js and I'll name it database or 4 00:00:17,980 --> 00:00:20,500 db.js. 5 00:00:20,570 --> 00:00:29,250 Now in this file, I will import mongodb here and then I'll write some code here which gives me a 6 00:00:29,250 --> 00:00:34,920 nice utility script to set up a connection to the database and then get access to the established connection. 7 00:00:35,700 --> 00:00:36,410 For this, I'll 8 00:00:36,540 --> 00:00:39,860 first of all create a new constant, 9 00:00:39,940 --> 00:00:46,890 initDb which simply points at a function which receives a callback, 10 00:00:46,950 --> 00:00:49,660 so another function it can execute as an argument 11 00:00:50,390 --> 00:01:02,740 and here additionally in that file, I'll add a variable with let _db, it has no initial value. Inside 12 00:01:02,740 --> 00:01:03,290 of initDb, 13 00:01:03,310 --> 00:01:11,530 I'll check if db is uninitialized and if it is not uninitialized, so if this returns true which 14 00:01:11,530 --> 00:01:13,560 only happens if it is initialized, 15 00:01:15,070 --> 00:01:21,670 then I'll simply log database is already initialized 16 00:01:24,200 --> 00:01:26,460 and I'll just return my callback, 17 00:01:26,460 --> 00:01:27,860 so I basically call the callback 18 00:01:27,890 --> 00:01:34,220 I basically expect to get a function as an argument so to say and I'll execute that function here and I pass null 19 00:01:34,220 --> 00:01:38,180 as a first argument because my callback will receive an error as a first argument 20 00:01:38,210 --> 00:01:40,030 and I don't want to throw an error here, 21 00:01:40,040 --> 00:01:42,010 it's fine that we already are connected, 22 00:01:42,020 --> 00:01:44,840 so I just return the existing database 23 00:01:44,840 --> 00:01:50,300 but of course this is a case we can't reach right now because we have no code to actually store something 24 00:01:50,300 --> 00:01:51,840 in _db. 25 00:01:52,130 --> 00:01:53,490 So this is what happens now, 26 00:01:53,960 --> 00:02:02,000 I will create my constant mongo client here and use mongodb mongo client to well get access to 27 00:02:02,000 --> 00:02:03,400 the client. 28 00:02:03,420 --> 00:02:11,290 I'll also create a new constant, mongoDbUrl 29 00:02:11,310 --> 00:02:13,730 and that will be my connection 30 00:02:13,740 --> 00:02:14,410 url, 31 00:02:14,490 --> 00:02:20,000 so basically the url I'm using in the products.js file right now here for the connect method. 32 00:02:20,140 --> 00:02:26,280 This string, that is what I copy and that is what I move into the db.js file and which I store here 33 00:02:26,460 --> 00:02:30,740 as a string as about. Now back in initDb, 34 00:02:30,740 --> 00:02:36,670 I will use the mongo client here and call connect and use that mongoDbUrl, 35 00:02:36,680 --> 00:02:41,850 so basically the same code I have in products.js. Now by the way, 36 00:02:41,850 --> 00:02:45,200 you can also, that should have a lowercase l, 37 00:02:45,330 --> 00:02:50,180 you can also pass a second argument where you configure this connection here. 38 00:02:50,190 --> 00:02:54,270 Now this is a bit more advanced and you should check out the official driver docs to learn what you 39 00:02:54,270 --> 00:02:55,530 can configure here, 40 00:02:55,710 --> 00:02:59,650 the default settings should be fine and they are fine for us here. 41 00:03:00,910 --> 00:03:07,790 So I will just connect like this and then here of course, we have a promise then and catch are 42 00:03:07,810 --> 00:03:13,260 therefore functions we can use here. Now in catch, we'll get any error that occurs during the connection 43 00:03:13,760 --> 00:03:22,750 and therefore here in the error case, I will execute my callback and pass that error as the first argument 44 00:03:22,840 --> 00:03:28,480 because I mentioned that the callback, the function I receive here, will be a function I call and I expect 45 00:03:28,480 --> 00:03:34,060 to whoever who passed this function to me to implement this function in a way that it is able to handle 46 00:03:34,060 --> 00:03:36,980 the first argument as a potential error. 47 00:03:37,360 --> 00:03:43,390 So that's the worse, the bad case, the good case is that we are successful so that we do it successfully 48 00:03:43,390 --> 00:03:44,230 connect 49 00:03:44,230 --> 00:03:48,190 and in this case, I get access to the client here in the then block, 50 00:03:48,310 --> 00:03:51,050 so the logic is the same as in the products.js file. 51 00:03:51,400 --> 00:03:56,210 So this client here allows me to then simply store the database, 52 00:03:56,260 --> 00:03:59,540 so db is then equal to client.db, 53 00:03:59,950 --> 00:04:07,280 so this gives me access to the database which was created. 54 00:04:07,360 --> 00:04:11,750 So now I have some method which I can execute to establish a connection, 55 00:04:11,770 --> 00:04:18,130 I'll now create a second constant in the same file which I'll name getDb to get access to this established database 56 00:04:18,130 --> 00:04:19,740 connection, 57 00:04:19,790 --> 00:04:25,440 whoops, it should be written like this, will also be an arrow function 58 00:04:25,880 --> 00:04:30,090 and here I simply return _db. 59 00:04:30,180 --> 00:04:31,870 However first of all, I'll quickly add an 60 00:04:32,000 --> 00:04:34,330 if check, if not _db so 61 00:04:34,370 --> 00:04:44,000 if this is uninitialized, then I'll throw an error where I say database not initialized. 62 00:04:45,120 --> 00:04:46,330 So now I have two functions 63 00:04:46,360 --> 00:04:53,430 in here, initDb to establish a connection and getDb to get access to an existing connection. How 64 00:04:53,430 --> 00:04:54,890 do I use these now? 65 00:04:55,350 --> 00:05:00,540 Well in app.js which is the first file that gets executed when we start up our server, 66 00:05:00,810 --> 00:05:06,570 I can remove that mongodb import I have there and instead, I can add an import to my database 67 00:05:07,230 --> 00:05:08,480 utility file, 68 00:05:08,640 --> 00:05:15,150 so I'll just name it db and I do import my own file by typing require./db and you can omit 69 00:05:15,180 --> 00:05:15,620 the 70 00:05:15,630 --> 00:05:17,460 .js 71 00:05:17,460 --> 00:05:23,060 Now here before I call listen, I will call db 72 00:05:23,300 --> 00:05:29,500 and then what? Well I need to call the functions that are in that file and to make these functions callable, 73 00:05:29,600 --> 00:05:38,180 I add module exports at the end and I'll export an object here and that object will receive initDb 74 00:05:38,420 --> 00:05:44,630 and getDb and this syntax simply creates keys called initDb and getDb which receives their 75 00:05:44,630 --> 00:05:49,330 respective constants which are functions in the end as values. 76 00:05:49,340 --> 00:05:52,910 So now with that in app.js I can call db, initDb 77 00:05:52,940 --> 00:05:56,300 here and initDb needs a callback function 78 00:05:56,300 --> 00:06:07,710 as you learned, a callback function that will either give me an error or the database because here, I want 79 00:06:07,710 --> 00:06:14,840 to also call the callback with null and then the database, like this. And now in 80 00:06:14,890 --> 00:06:23,070 app.js, I know that if I'm in here, I can check if the error exists and if it does, I'll simply console log 81 00:06:23,070 --> 00:06:30,000 the error but else if I got no error, then I can call app listen which starts the nodejs server. So 82 00:06:30,000 --> 00:06:35,020 the nodejs server in this setup here here will start when the connection is established. 83 00:06:35,020 --> 00:06:41,220 Now you can always tweak this but this is a basic setup that ensures that the database is or that our 84 00:06:41,670 --> 00:06:48,370 app here connects to the database at application start up before it starts listening to incoming requests 85 00:06:48,540 --> 00:06:52,740 and then this simply will keep on running. Now in 86 00:06:52,750 --> 00:06:53,890 products.js, 87 00:06:54,000 --> 00:06:57,300 we also don't need the mongo client anymore, 88 00:06:57,300 --> 00:07:00,400 we need mongodb though for the decimal import 89 00:07:00,630 --> 00:07:04,390 but I can now add my own import db by requiring 90 00:07:04,500 --> 00:07:09,190 and now we go up one level with two dots and then we point at db, like this, 91 00:07:09,220 --> 00:07:17,130 so in our db.js file and then in the places where we work with the database, we simply replace this entire 92 00:07:17,130 --> 00:07:19,790 part where we connect and so on 93 00:07:20,660 --> 00:07:26,890 with a call to db, getDb and that returns us the connected database and 94 00:07:26,930 --> 00:07:33,140 therefore this closing pair of brackets can be removed. And now we just interact with the database here 95 00:07:33,440 --> 00:07:36,750 and then the rest of the code stays as it is and in post, 96 00:07:36,750 --> 00:07:37,910 it's the same. 97 00:07:38,120 --> 00:07:47,900 We replace that code here with db, getDb and remove that redundant pair of brackets. With all these 98 00:07:47,900 --> 00:07:56,120 changes, let's quit our currently running backend server, restarting router get catch is not a function, 99 00:07:56,120 --> 00:07:57,590 let's see what's wrong here. 100 00:07:59,560 --> 00:08:02,020 Oh yeah, that catch block here, 101 00:08:02,140 --> 00:08:09,820 that is also redundant now because that was related to catching errors during the establishment of our connection, 102 00:08:09,820 --> 00:08:15,360 we don't need that anymore so let's remove that outer catch block on our get and post route 103 00:08:15,400 --> 00:08:21,670 so that we only have to catch block on forEach or the catch block on insert but not the one that was related 104 00:08:21,670 --> 00:08:23,220 to connecting 105 00:08:23,390 --> 00:08:25,260 and let's now try this again. 106 00:08:26,410 --> 00:08:28,140 This looks better, 107 00:08:28,270 --> 00:08:29,630 we get no error and 108 00:08:29,990 --> 00:08:35,440 if I now reload that front page here, now I have an error, 109 00:08:37,140 --> 00:08:40,090 client is not defined is the error I get here 110 00:08:41,440 --> 00:08:46,360 and that makes sense because I still have the code to close the connection which I don't need to do 111 00:08:46,400 --> 00:08:48,730 and I'll say some words about that in a second too, 112 00:08:48,860 --> 00:08:56,720 so make sure you remove all client close calls here in your products.js file and thereafter, restart. 113 00:08:58,340 --> 00:09:04,490 After reloading, I get a strange result because I accidentally deleted my products constant and therefore, 114 00:09:04,670 --> 00:09:10,400 I load my old products which I have up there. Now I should simply comment out my dummy products up there 115 00:09:10,490 --> 00:09:17,420 which I don't need anymore and then simply recreate my products down there as an empty array to which 116 00:09:17,420 --> 00:09:19,400 I push all the products. 117 00:09:19,400 --> 00:09:25,370 So now with that finally, if we now restart the backend server and we reload that starting page, we should 118 00:09:25,370 --> 00:09:28,600 see only that one product which we added. 119 00:09:28,610 --> 00:09:31,560 So now we have the same functionality as before, 120 00:09:31,740 --> 00:09:38,920 let's also confirm this by adding a new product and for this, I'll just use some of my dummy data, 121 00:09:39,100 --> 00:09:40,210 lovely earrings, 122 00:09:43,130 --> 00:09:47,210 price and the image url here simply 123 00:09:47,210 --> 00:09:52,280 is this url 124 00:09:52,390 --> 00:09:58,760 and then in there, let's also add a description like this. 125 00:09:58,780 --> 00:10:02,510 Now if I create that product, you see the lovely earrings exist here too. 126 00:10:02,830 --> 00:10:05,510 So now we got that all set up, 127 00:10:05,560 --> 00:10:08,990 we're now able to store data, to get data, 128 00:10:09,040 --> 00:10:13,380 now the next step is of course to also get data for a single product 129 00:10:13,420 --> 00:10:16,780 if I click on details here, which right now doesn't work 130 00:10:16,780 --> 00:10:23,350 and I also want to drop some words on reusing that connection which we're currently doing. 131 00:10:23,470 --> 00:10:27,820 I'm using one and the same connection all the time now and this is actually something which you should 132 00:10:27,820 --> 00:10:34,480 do because you'll use a concept called connection pooling which is provided by the mongodb driver 133 00:10:34,480 --> 00:10:36,100 here by default. 134 00:10:36,100 --> 00:10:41,100 That means it actually established a couple of connections or at least it's ready to quickly establish 135 00:10:41,110 --> 00:10:46,480 them and therefore, you can handle multiple incoming requests to your node restAPI 136 00:10:46,490 --> 00:10:53,430 simultanenuously because you can only send one request per connection to mongodb normally 137 00:10:53,650 --> 00:10:59,110 but since you have a connection pool here of multiple available connections, even if you have multiple 138 00:10:59,110 --> 00:11:04,530 incoming connections to nodejs, you can forward them to mongodb 139 00:11:04,600 --> 00:11:06,470 thanks to this connection pooling. 140 00:11:06,490 --> 00:11:12,970 So this is also an advantage of this approach where we reuse one client because here, we actually have 141 00:11:13,090 --> 00:11:14,510 a shared connection pool then. 142 00:11:14,520 --> 00:11:19,990 Now to fully reuse that though, we should not call db here, 143 00:11:20,200 --> 00:11:25,590 so db should just be the client instead and therefore in products.js 144 00:11:25,590 --> 00:11:30,730 when you call getDb, we have to call db ourselves. 145 00:11:30,730 --> 00:11:36,400 So this is one tiny change you should make to be sure you can reuse your connections but with that out 146 00:11:36,400 --> 00:11:42,960 of the way and the backend server restarted one more time, everything should still work right. 147 00:11:43,070 --> 00:11:45,560 So now let's work on getting a single product.