Coding

#7 Dynamic Relations | Build a Complete App with GraphQL, Node.js, MongoDB and React.js

  • 00:00:01 hi welcome back to this serious where we
  • 00:00:04 will build an entire graph QL API and a
  • 00:00:08 react front-end connected to it now we
  • 00:00:11 started working on the graph QL API will
  • 00:00:14 build an event booking API so we got
  • 00:00:17 events and we got users thus far we got
  • 00:00:20 our API schema which well allows us to
  • 00:00:23 interact with that but there are still
  • 00:00:25 some features missing and there are some
  • 00:00:27 things we can polish about this API as
  • 00:00:30 we currently have it I'll work on this
  • 00:00:32 in this video and in the next video of
  • 00:00:34 this series I'll then work on the actual
  • 00:00:36 bookings which we can make or which we
  • 00:00:39 can make as a user of this event booking
  • 00:00:41 service
  • 00:00:45 so let's dive into the polishing and the
  • 00:00:48 completion of the API as we currently
  • 00:00:51 have it now obviously there are more
  • 00:00:54 missing features but about the API as we
  • 00:00:56 currently have it there's one big thing
  • 00:00:59 that misses and that is our relation
  • 00:01:02 between users and events in our mongoose
  • 00:01:06 models which have no direct effect on
  • 00:01:08 the api I really want to emphasize that
  • 00:01:10 in these models we see that we have for
  • 00:01:14 a user a list of created events and in
  • 00:01:17 that list we store well a list of event
  • 00:01:20 IDs and for an event object or an event
  • 00:01:24 entity in the database we have that
  • 00:01:26 creator field which is a single user ID
  • 00:01:30 now currently I can't fetch that data
  • 00:01:34 through the API and that is the first
  • 00:01:36 thing I want to change so here for my
  • 00:01:39 event type I want to add that creator
  • 00:01:42 field and dad will return me a user
  • 00:01:45 object that is the idea and a user is
  • 00:01:49 defined as it is down there and for a
  • 00:01:52 user on the other hand I will have the
  • 00:01:56 created events field and you could pick
  • 00:01:59 different name than you have here in
  • 00:02:01 your mangu schemas but I will use the
  • 00:02:03 same names and the created events field
  • 00:02:05 should return me an array of events this
  • 00:02:09 may actually be now if a user hasn't
  • 00:02:11 created any events yet but the but if it
  • 00:02:15 has data in there then it has to be an
  • 00:02:18 event object and not a null object so
  • 00:02:21 now we updated this and we can now try
  • 00:02:23 to use that so here in graphical I'll
  • 00:02:26 now send a query to the events endpoint
  • 00:02:29 and there let me fetch the creator and I
  • 00:02:33 need to reload that page to get auto
  • 00:02:35 completion now let me get that creator
  • 00:02:39 and there let me get the ID now this
  • 00:02:44 works here in graphical because it fits
  • 00:02:46 my graph QL schema but if I hit enter I
  • 00:02:50 get this ID cannot represent value error
  • 00:02:53 okay so let's try with the email of the
  • 00:02:56 Creator here I actually get an average
  • 00:02:59 that I cannot return null for a non-null
  • 00:03:01 above field user email and what's the
  • 00:03:04 issue here the issue is that whilst I do
  • 00:03:09 say that an event has a creator which is
  • 00:03:12 of type user once I say that here in my
  • 00:03:15 schema definition this is not what I
  • 00:03:17 actually record in my resolver because
  • 00:03:20 for events here I do return my event my
  • 00:03:24 event objects as I do fetch them from
  • 00:03:26 the database but we always have to keep
  • 00:03:28 in mind that in the database there is no
  • 00:03:31 complete user object stored in a single
  • 00:03:35 event instead creator is simply holding
  • 00:03:39 the ID of the user so all I'm returning
  • 00:03:42 here is an event object where the
  • 00:03:44 creator field has the idea of the user
  • 00:03:46 the creator field is not an object with
  • 00:03:50 the user email or anything like that
  • 00:03:53 and therefore when I try to query for
  • 00:03:55 that it is certain to fail because I
  • 00:03:58 can't get the email if all I get back
  • 00:04:01 from the database is in the end a single
  • 00:04:03 string so this will actually not work
  • 00:04:08 here as a consequence we have to adjust
  • 00:04:11 the day that we return here and we
  • 00:04:13 should make sure that the events we
  • 00:04:15 return actually do have all the user
  • 00:04:18 information for that I obviously need to
  • 00:04:21 fetch information for the user who
  • 00:04:23 created the event I can use a feature
  • 00:04:26 provided by Mongoose to get this
  • 00:04:29 additional data I can find and before I
  • 00:04:33 call then I can add populate populate
  • 00:04:36 this a method provided by Mongoose to
  • 00:04:38 populate any relations at nose and
  • 00:04:41 Mongoose knows a relation by this ref
  • 00:04:44 key so here creator for an event has
  • 00:04:47 that ref key so when we now call
  • 00:04:49 populate Mongoose goes and visits that
  • 00:04:53 collection or that model were pointing
  • 00:04:55 at here on the ref key and tries to pull
  • 00:04:58 in all that extra data from our database
  • 00:05:00 to for the given user ID which is
  • 00:05:03 actually stored in this creator field so
  • 00:05:05 therefore here I can populate I just
  • 00:05:07 have to tell Mongoose which field i want
  • 00:05:09 to populate and that would be the
  • 00:05:11 creator field so it
  • 00:05:13 should look into that field and see if
  • 00:05:14 it can find a reference there and now
  • 00:05:17 with that if we save that it will
  • 00:05:19 restart and now let's try it again let's
  • 00:05:22 try to fetch the email for the creator
  • 00:05:24 and there it is this now works now if I
  • 00:05:28 try to fetch the ID here I get the error
  • 00:05:31 we already know from the past videos
  • 00:05:33 this is related to how the ID is stored
  • 00:05:36 and that it is this object ID object
  • 00:05:39 which is not understood by graph QL and
  • 00:05:42 we could fix that by going into our
  • 00:05:45 returned object and overwriting the
  • 00:05:48 Creator and there I actually want to get
  • 00:05:52 all my event dark creator data or of the
  • 00:06:00 Creator document but I want to override
  • 00:06:02 the ID and set this to event dark
  • 00:06:05 creator ID without the underscore to use
  • 00:06:09 that built-in ID virtual getter provided
  • 00:06:12 by Mongoose now if I hit enter this
  • 00:06:14 looks much better and the other fields
  • 00:06:16 also should still work so now we are
  • 00:06:19 populating our event data now obviously
  • 00:06:23 we could now say okay we get a creator
  • 00:06:26 here a Creator has created events and
  • 00:06:28 created events are events with the title
  • 00:06:31 and so on but if I hit enter we face the
  • 00:06:34 same problem because now we did populate
  • 00:06:36 our event with the rich user data for
  • 00:06:39 the creator field but then that extra
  • 00:06:42 user data that was pulled and merged
  • 00:06:44 into the creator field by Mongoose
  • 00:06:47 that still has the created events field
  • 00:06:51 then but that again is just an array of
  • 00:06:54 our IDs of events someone goose does not
  • 00:06:58 recursively kind of populate this and
  • 00:07:01 this is good because we would enter an
  • 00:07:03 infinite loop
  • 00:07:03 because if Mongoose would now populate
  • 00:07:05 all the created events there well then
  • 00:07:08 we would again have events with a
  • 00:07:09 creator field and if Mongoose would
  • 00:07:12 populate this again then we would have
  • 00:07:14 to created events again and Mongoose
  • 00:07:16 would have to populate this again and
  • 00:07:18 you see where this would be going and
  • 00:07:20 therefore this is not necessarily the
  • 00:07:23 best approach I can think of because we
  • 00:07:25 can only
  • 00:07:26 add a certain amount of nesting and we
  • 00:07:28 don't have the full flexibility of
  • 00:07:30 querying as deep as we want and
  • 00:07:33 therefore to get this flexibility I will
  • 00:07:36 actually implement this merging manually
  • 00:07:40 with a more flexible approach and for
  • 00:07:44 that I will add a function here in my
  • 00:07:47 app J's file and I will name this
  • 00:07:50 function user now this will be an arrow
  • 00:07:53 function which receives an user ID as an
  • 00:07:57 argument and then here I will return
  • 00:08:00 user find by ID to find a user by that
  • 00:08:05 ID in my database so by that user ID and
  • 00:08:08 here I will then have then and catch and
  • 00:08:13 if I have a problem here I will throw an
  • 00:08:16 error in the then block however I will
  • 00:08:18 have my user data and there I simply
  • 00:08:23 want to return user doc where I
  • 00:08:27 overwrite the ID so just use your ID
  • 00:08:31 here with that I have all the logic to
  • 00:08:35 fetch a user by its ID now I can use
  • 00:08:39 that user down there where I want to get
  • 00:08:43 data for my creator we can now get rid
  • 00:08:45 of the populate method here and then
  • 00:08:48 stared here on the creator I can point
  • 00:08:51 at my user function so keep in mind user
  • 00:08:54 here is really just pointing at this
  • 00:08:58 constant not at this at this constant
  • 00:09:01 here which holds my arrow function in
  • 00:09:04 the end so I can point at this function
  • 00:09:06 down there and I just need to make sure
  • 00:09:09 that the argument is passed in so that
  • 00:09:11 this user ID is passed in and I do this
  • 00:09:13 with the bind method and the second
  • 00:09:16 argument I passed there will be the
  • 00:09:18 argument received in the user function
  • 00:09:20 we defined above and there I will pass
  • 00:09:22 in my event
  • 00:09:26 doc Creator field and that will be on
  • 00:09:32 that object ID which mangu is retrieved
  • 00:09:35 from the database now let me save that
  • 00:09:38 and let's give this a
  • 00:09:40 try we still will not be able to get
  • 00:09:42 access to the created events yet but if
  • 00:09:45 I hit enter like this this still works
  • 00:09:47 and for my events I can get the email
  • 00:09:49 address of my Creator so this proves
  • 00:09:52 that my manual population approach here
  • 00:09:56 works now the cool thing is I can now
  • 00:09:59 also add never a constant which I'll
  • 00:10:02 name events and there I expect to get
  • 00:10:05 multiple event IDs and here I will then
  • 00:10:09 return event find and there I will look
  • 00:10:13 for all events were the ID and now here
  • 00:10:17 comes some special MongoDB query syntax
  • 00:10:19 where the ID is in dollar sign in that
  • 00:10:23 is a special operator understood by
  • 00:10:25 MongoDB in in a list of ID's
  • 00:10:28 so I basically write a query where I
  • 00:10:30 want to get all events where the idea of
  • 00:10:32 the event is one of the IDS to find in
  • 00:10:35 an array I'm passing here and that of
  • 00:10:37 course is the event IDs array which I
  • 00:10:39 expect as an argument so here I can then
  • 00:10:42 find a list of events basically all
  • 00:10:45 events that have their ID in that pool
  • 00:10:47 of ID's I'm getting and there I then
  • 00:10:51 also have then and catch and I might
  • 00:10:55 have an error which I just want to throw
  • 00:10:57 in the then block I know I have a couple
  • 00:11:00 of events and there I just want to
  • 00:11:02 return my events in a mapped version to
  • 00:11:07 transform each event and basically
  • 00:11:11 return a new object for every event in
  • 00:11:14 that array get my doc data but then also
  • 00:11:19 override the ID like this and
  • 00:11:23 importantly overwrite the creator field
  • 00:11:27 to make sure that there I point at user
  • 00:11:30 so add my function down there which I
  • 00:11:33 can thanks to hoisting so I point at
  • 00:11:36 user bind this and then there I want to
  • 00:11:41 pass this creator field so event dot
  • 00:11:45 Creator okay so basically here I'm just
  • 00:11:49 setting up that my creator property it
  • 00:11:53 does not hold us
  • 00:11:54 value but instead we'll call a function
  • 00:11:57 when I try to access it and for my user
  • 00:12:00 down there I will also make sure that
  • 00:12:02 they created events field which I have
  • 00:12:05 will also not return its value but
  • 00:12:07 instead will point at my events function
  • 00:12:11 here and why am i doing this I'll
  • 00:12:13 explain it in a second
  • 00:12:15 so here I'll point at events and I'll
  • 00:12:17 just make sure that I bind so that the
  • 00:12:19 event IDs are passed as an argument and
  • 00:12:22 here the event IDs can be found on user
  • 00:12:24 dock and then there
  • 00:12:27 it's the created events field so why am
  • 00:12:31 I doing this why am i replacing created
  • 00:12:33 events and creator with functions
  • 00:12:35 because the way graph QL works whenever
  • 00:12:38 through an incoming query I try to
  • 00:12:41 access a certain property this will
  • 00:12:43 actually see if the property is a value
  • 00:12:46 like a string or a number and it will
  • 00:12:48 just give me that value or if it is a
  • 00:12:51 function and if it is a function it will
  • 00:12:53 call that function for me and return the
  • 00:12:55 result of that function as a value for
  • 00:12:58 the property I tried to query so that is
  • 00:13:00 a flexibility we have in graph QL and
  • 00:13:02 this now allows me to model relations in
  • 00:13:07 a highly flexible way because now down
  • 00:13:11 there where I get all my events I make
  • 00:13:13 sure that D creator points at that user
  • 00:13:15 function so when I access this creator
  • 00:13:18 in my graph QL query we call that
  • 00:13:20 function or graph GL calls that function
  • 00:13:23 and gives me the data return pilot
  • 00:13:25 function the write the data returned by
  • 00:13:27 the user function happens to be there's
  • 00:13:30 a rich object with all the user fields
  • 00:13:33 and with the created events field and if
  • 00:13:35 I drill deeper into that and I want to
  • 00:13:37 get access to D created events and fetch
  • 00:13:40 some event data then this function would
  • 00:13:42 get called and therefore it would
  • 00:13:44 execute this function and give me that
  • 00:13:46 rich event data where again I could
  • 00:13:48 drill deeper into the Creator now this
  • 00:13:51 is not an infinite loop because these
  • 00:13:52 functions are not executed as long as I
  • 00:13:55 don't request that specific value on
  • 00:13:58 this specific level and therefore now if
  • 00:14:02 I save that and it reloads we can reload
  • 00:14:05 here and I can still get the email
  • 00:14:08 for the creator but I can also get to
  • 00:14:10 created events and there get the title
  • 00:14:12 and you see this works and I can now for
  • 00:14:15 all these created events again get the
  • 00:14:18 creator email and this now all the works
  • 00:14:23 and now I can drill into this without
  • 00:14:25 entering an infinite loop and this gives
  • 00:14:27 us all the flexibility we want or we
  • 00:14:29 could need so if I now add an hour event
  • 00:14:33 and not a user and event with event
  • 00:14:36 input and this will be added for the
  • 00:14:39 single use I have because I hard-coded
  • 00:14:41 that user ID in my back-end an hour
  • 00:14:45 and I give this a description this is
  • 00:14:49 just another test and I give the
  • 00:14:52 surprise of 999 999.9 9 and I also gift
  • 00:14:59 is a date off let's use to good old
  • 00:15:02 developer tools again real quick to get
  • 00:15:05 that date so here I'll just call new
  • 00:15:10 date UI so string real quick now I have
  • 00:15:13 that date string and let's answer this
  • 00:15:17 here and here I get back my created
  • 00:15:21 event and I will actually also have
  • 00:15:22 access to the user who created this if I
  • 00:15:25 hit enter I get an error for user email
  • 00:15:28 okay let's try without that and
  • 00:15:31 investigate this in a second
  • 00:15:32 so this generally worked now let's again
  • 00:15:36 get all our events here and for the
  • 00:15:41 events
  • 00:15:41 let's get the title and let's get the
  • 00:15:45 creator and for the creator let's get
  • 00:15:47 the email and there's no works for
  • 00:15:50 multiple events and I have another event
  • 00:15:52 twice because of that error I created it
  • 00:15:54 twice but this now works this gives us
  • 00:15:56 this gives us all the flexibility now
  • 00:15:59 regarding that error I mentioned well
  • 00:16:01 there the problem was simply that for
  • 00:16:04 create event we all return an event in
  • 00:16:07 the end that created event and the
  • 00:16:10 problem here is that there I'm not using
  • 00:16:12 that creator functionality so when I
  • 00:16:16 assign a value to created event which
  • 00:16:19 I'm doing here then
  • 00:16:21 I also of course need to make sure that
  • 00:16:24 I replace creator here with user and
  • 00:16:27 then bind this to result because we're
  • 00:16:30 salt here it's the variable holding that
  • 00:16:32 event data in this place result dark
  • 00:16:37 creator and now we will actually also
  • 00:16:40 enrich this here and now if I do create
  • 00:16:42 an event again so if I go back to
  • 00:16:44 graphical and I do create an ever um
  • 00:16:48 event here with create event event input
  • 00:16:52 and there let's insert a title this
  • 00:16:56 should now work let's add a description
  • 00:17:00 it really should let's give it a price
  • 00:17:05 of 29.99 and date of that same date
  • 00:17:11 string I used before now I should be
  • 00:17:13 able to drill into my Creator here yeah
  • 00:17:16 and this now works at this now proofs
  • 00:17:19 that we got this rich merging going on
  • 00:17:23 now thanks to the capability of graph
  • 00:17:25 queue of not just returning values like
  • 00:17:27 strings and numbers but also using
  • 00:17:30 values that are functions because the
  • 00:17:33 graft UL parser the package we're using
  • 00:17:36 here will then execute the function and
  • 00:17:38 used ad return value and this is an
  • 00:17:41 extremely important part of graph QL
  • 00:17:43 which gives us a lot of flexibility and
  • 00:17:46 power of course now to end this video
  • 00:17:50 here I actually want to clean up my
  • 00:17:52 files because we have that large app.js
  • 00:17:54 file now I want to start moving to a
  • 00:17:57 different structure and it will add a
  • 00:17:59 new folder graph QL you could name it
  • 00:18:01 differently and in there I want to have
  • 00:18:04 my schema folder and I want to have my
  • 00:18:08 resolvers a folder and in the schema
  • 00:18:11 folder I'll add index.js file and in
  • 00:18:16 that index.js file I basically want to
  • 00:18:18 export my schema we can further split
  • 00:18:21 this up later but for now I just want to
  • 00:18:23 basically export this call to build
  • 00:18:27 schema here so I'll cut it out of app
  • 00:18:30 jeaious remember that we also will need
  • 00:18:33 this import
  • 00:18:35 therefore an indexed Reyes I will import
  • 00:18:37 build schema and not from but by
  • 00:18:41 requiring graph QL like this and this is
  • 00:18:47 using the destructuring syntax the
  • 00:18:49 object restructuring syntax and then
  • 00:18:51 here I will module exports well
  • 00:18:54 basically what I had an app shares
  • 00:18:55 before build schema with our schema
  • 00:18:57 definition string and in the resolvers
  • 00:19:01 there I will add an index J as file
  • 00:19:04 queue and later we will add more files
  • 00:19:06 but for now I'll go with one file at
  • 00:19:08 least and it will now grab my root value
  • 00:19:12 so this object here I will grab that and
  • 00:19:17 we'll move that into dad resolvers file
  • 00:19:20 there I will module exports this but of
  • 00:19:23 course here we also have a couple of
  • 00:19:25 dependencies which we need first of all
  • 00:19:27 I need to grab my events and my user
  • 00:19:31 function here from app KS which I use in
  • 00:19:33 my resolvers so we should insert this
  • 00:19:36 year as well and of course we need a
  • 00:19:38 couple of imports for example we need to
  • 00:19:41 imports for be tripped
  • 00:19:43 we need our event and user import so I
  • 00:19:46 can cut dad out of app trace and move it
  • 00:19:49 into the index.js file in the resolvers
  • 00:19:52 like this and the nap trace I can also
  • 00:19:55 remove the build schema import here of
  • 00:19:57 course so now we just need to make sure
  • 00:20:00 that we import the things we now outs
  • 00:20:03 worst into our files back into this file
  • 00:20:05 here for that well I simply add a couple
  • 00:20:09 of imports in app j s i'll name this
  • 00:20:12 graph QL schema the name is totally up
  • 00:20:15 to you and I will require well basically
  • 00:20:19 what I get from the graph QL folder and
  • 00:20:22 there from the schema folder and there
  • 00:20:23 from that index file and it will also
  • 00:20:26 import the graph QL resolvers by
  • 00:20:31 requiring that from graph QL resolvers
  • 00:20:35 in XJS and now I will but use both here
  • 00:20:40 so here I have to graph QL schema and
  • 00:20:42 for the root value I have to graph QL
  • 00:20:45 resolvers and now this makes this file a
  • 00:20:47 bit easier to read
  • 00:20:48 now it crashes let's see what's wrong
  • 00:20:52 yeah the import pops of course are wrong
  • 00:20:55 here in the resolver the models are now
  • 00:20:58 actually two levels above where they
  • 00:21:01 previously were now this looks better
  • 00:21:06 and now if I go back and I reload
  • 00:21:10 graphical let's see if I go for the
  • 00:21:13 events again doesn't look too bad
  • 00:21:24 so this works not done yet though this
  • 00:21:28 is a great first step now one problem I
  • 00:21:30 have is for example if I fetch the date
  • 00:21:33 here this is just a string which looks
  • 00:21:36 like that it's not actually a readable
  • 00:21:38 date now that is due to the fact that
  • 00:21:40 the date is stored as a date object in
  • 00:21:43 MongoDB but when we then parse it back
  • 00:21:46 into a string this does not yield a
  • 00:21:49 readable date and that is of course our
  • 00:21:51 responsibility to change this therefore
  • 00:21:54 in the places where I do fetch my events
  • 00:21:58 there I now want to well also replace
  • 00:22:03 the date field by accessing my date but
  • 00:22:08 I'll wrap this into a new date call and
  • 00:22:11 then I'll call to I so string to create
  • 00:22:14 a date string that is more readable than
  • 00:22:18 what we had before and therefore I will
  • 00:22:20 also do that down there of course here I
  • 00:22:23 also need to replace that with event doc
  • 00:22:27 date wrapped a new date with two eyes of
  • 00:22:29 string and although when we create an
  • 00:22:32 event therefore the created event I
  • 00:22:35 should also do that and yes you could
  • 00:22:36 refactor that for sure
  • 00:22:38 I'll keep it like this for now but with
  • 00:22:40 that if I now fetch this again we should
  • 00:22:44 have a more readable date yes this is
  • 00:22:46 looking great now last but not least
  • 00:22:48 there's one other thing we could do and
  • 00:22:50 that is we can use async a weight of
  • 00:22:52 course instead of this promise syntax
  • 00:22:56 with then and catch and this is 100%
  • 00:22:58 optional you don't need to use async
  • 00:23:00 await but you can
  • 00:23:02 if you wanna use it it's relatively easy
  • 00:23:05 here in this resolver for example here
  • 00:23:08 for this events function you add a sink
  • 00:23:10 in front of the function so in front of
  • 00:23:12 your argument list and then inside of
  • 00:23:14 the function you don't need to return
  • 00:23:16 this anymore
  • 00:23:17 it will be returned implicitly because
  • 00:23:19 in an async function you always return
  • 00:23:23 your topmost promise so to say so
  • 00:23:27 instead here we just need to await this
  • 00:23:29 now of course and this will make sure
  • 00:23:31 that this also gets returned this of
  • 00:23:34 course all the means that we no longer
  • 00:23:35 use then like this instead we await our
  • 00:23:38 events like this year so we get rid of
  • 00:23:41 this line now and if async await is the
  • 00:23:45 syntax you don't know obviously you
  • 00:23:46 should learn this first but the core
  • 00:23:48 idea is that we can transform this code
  • 00:23:51 into a way that looks like it runs
  • 00:23:53 synchronously even though it still
  • 00:23:55 doesn't it still uses a promise behind
  • 00:23:57 the scenes just a different syntax but
  • 00:24:00 now I wait my events here that means
  • 00:24:02 that in the next line where I return
  • 00:24:04 events map I don't do it like this I
  • 00:24:09 will just call map here I will just map
  • 00:24:12 it like this and how do we handle errors
  • 00:24:15 well now we do this with try-catch so I
  • 00:24:18 will now simply wrap this block here
  • 00:24:21 with a try block and then I can catch
  • 00:24:23 any errors we might get and then execute
  • 00:24:28 the error handling code like this and
  • 00:24:32 let's remove that closing parenthesis
  • 00:24:33 and now I successfully converted this
  • 00:24:36 first function to use async await now
  • 00:24:39 one thing I need to do here at the end
  • 00:24:41 OS here I now need to return events so
  • 00:24:44 to make sure that we return something
  • 00:24:46 graph QL can consume otherwise it waits
  • 00:24:50 for it to complete but we return no
  • 00:24:52 value and now if I run this query just
  • 00:24:56 looks good and if I now dive into the
  • 00:24:57 created events and I get the titles here
  • 00:25:00 this also looks quite good perfect so
  • 00:25:05 this works and now of course we can
  • 00:25:08 convert this to use async/await to this
  • 00:25:11 user function just as before I now get
  • 00:25:14 my user here by a waiting
  • 00:25:16 for this can remove that and remove dis
  • 00:25:19 pair wrap it in try-catch catch that
  • 00:25:26 error we might be getting and get rid of
  • 00:25:30 this line and of this closing
  • 00:25:32 parenthesis and now here i also use try
  • 00:25:36 catch and here i already am returning
  • 00:25:40 this and this is exactly what i need to
  • 00:25:41 do so it just looks good and now of
  • 00:25:45 course we can also do it down there so
  • 00:25:47 here i can also add a sync in front of
  • 00:25:49 this function which i map to my events
  • 00:25:51 key here and then here I get my events I
  • 00:25:54 can await for this that means I can get
  • 00:26:01 rid of this line here I still map it
  • 00:26:04 down there like this I get rid of that
  • 00:26:06 here we should wrap this with try-catch
  • 00:26:11 still so let's add this here catch any
  • 00:26:15 errors remove that line removed at
  • 00:26:18 closing single parenthesis that looks
  • 00:26:21 good and now all the way we create an
  • 00:26:23 event then I can also turn this into a
  • 00:26:26 sinc function here I will await event
  • 00:26:30 save and this will give me the result
  • 00:26:32 which I want to store in a constant so
  • 00:26:34 now we remove that then block here get
  • 00:26:37 my created event where I use that result
  • 00:26:39 let's get rid of this and in the next
  • 00:26:42 step I want you not return user find by
  • 00:26:48 but instead a wait user find by here get
  • 00:26:52 rid of this then block of course have
  • 00:26:55 our check here push and then also here
  • 00:26:58 get an average alt and here I'll name
  • 00:27:01 this user save result because I already
  • 00:27:05 use the constant result above and now
  • 00:27:08 the scoping is different than before so
  • 00:27:11 here I will now a wait user save get rid
  • 00:27:14 of this get rid of this here actually we
  • 00:27:20 don't even need to store this in a
  • 00:27:21 constant we're not using the result
  • 00:27:22 anyways so let's instead write all that
  • 00:27:27 code like that
  • 00:27:29 it's all they used try-catch and wrap
  • 00:27:31 all that code up to the catch statement
  • 00:27:33 in a try block and then open the catch
  • 00:27:37 handler removed that closing parentheses
  • 00:27:40 and I now converted this to async await
  • 00:27:43 too by the way if this is too fast you
  • 00:27:45 of course find that finished code
  • 00:27:47 attached to this video were in a link in
  • 00:27:50 the video description last but not least
  • 00:27:52 I'll also set async
  • 00:27:55 dudas create user function to use async
  • 00:27:57 await so here I'll get my user by
  • 00:28:02 waiting for the result of find one don't
  • 00:28:05 need to then block here therefore remove
  • 00:28:07 that as well here I get my hashed
  • 00:28:14 password by a waiting for be tripped
  • 00:28:17 hash get rid of this then block
  • 00:28:19 therefore get rid of this here I want to
  • 00:28:23 get my result by a waiting for the
  • 00:28:27 result of users save whoops and there I
  • 00:28:33 accidentally removed the closing
  • 00:28:35 parentheses of my user constructor don't
  • 00:28:37 want to do that let's get rid of this
  • 00:28:40 down here let's also just as before wrap
  • 00:28:44 this all in a try-catch block all the
  • 00:28:46 way to the catch statement here so catch
  • 00:28:51 the error get rid of this line and of
  • 00:28:57 the closing signal normal bracket and
  • 00:29:01 here I might have a typo yeah password
  • 00:29:05 should have two S's this looks now
  • 00:29:07 better but there seems to be an error
  • 00:29:10 somewhere user has already been declared
  • 00:29:13 yeah here I'm fetching my user and then
  • 00:29:17 I recreate that user object so I will
  • 00:29:20 just rename that first user to existing
  • 00:29:24 user in these two places now if I save
  • 00:29:27 that that looks better
  • 00:29:29 it recompiles and now let's quickly
  • 00:29:31 check that all let's add a mutation
  • 00:29:33 where I create a user with my user input
  • 00:29:36 which has to email test – or let's first
  • 00:29:40 of all create one with an email address
  • 00:29:42 that alright
  • 00:29:43 exists let's get the ID now I get
  • 00:29:49 userexists already which I should a new
  • 00:29:52 email address does work now let me
  • 00:29:55 create an event and I will create this
  • 00:29:58 with event input there I will add a
  • 00:30:01 title this is a test description should
  • 00:30:07 be user to end I will actually copy the
  • 00:30:12 email app the idea of that user we just
  • 00:30:14 created because I want a hard code add
  • 00:30:16 into the code now so that we have
  • 00:30:17 different users for the different events
  • 00:30:19 so first of all let's add a price here
  • 00:30:23 $39.99 and date I'll fill that in in a
  • 00:30:27 second first of all I'll go back to my
  • 00:30:29 code and in all the places where I
  • 00:30:31 hard-coded the user ID and will change
  • 00:30:33 its later but where I did do that I will
  • 00:30:35 paste in that user ID of the newly
  • 00:30:37 created user so that would be here in
  • 00:30:39 the create event function and I'll
  • 00:30:41 restart this and now here on the
  • 00:30:44 front-end I'll again create my date
  • 00:30:47 whoops I'll create my date string real
  • 00:30:53 quick copy that and move it in here and
  • 00:31:00 get back the title user is not defined
  • 00:31:08 now looking into the MongoDB
  • 00:31:10 Atlas database I see that this event was
  • 00:31:13 created however so this user is not
  • 00:31:17 defined method here has to be stemming
  • 00:31:20 from the code which I just changed here
  • 00:31:22 and actually there the problem is that I
  • 00:31:25 use user as a name again
  • 00:31:27 that obviously clashes with user
  • 00:31:30 function i define up here so to solve
  • 00:31:34 this problem down there I will simply
  • 00:31:39 name this creator here and in all the
  • 00:31:44 places where I used user I'll use
  • 00:31:46 creator only in that function if I now
  • 00:31:49 save that let's rerun that query
  • 00:31:55 looks better and now we should have that
  • 00:31:57 event with this is a test and user two
  • 00:32:00 as a description we should have that in
  • 00:32:01 our collection twice because I now well
  • 00:32:04 basically ran that query twice yeah
  • 00:32:06 there it is
  • 00:32:07 and this now all seems to work let's
  • 00:32:10 improve this by running one final query
  • 00:32:13 a query here where I get all events and
  • 00:32:18 there I want to get the titles of all
  • 00:32:21 events and from the off the creators I
  • 00:32:23 want to get the email address let's say
  • 00:32:25 let's execute that and here we actually
  • 00:32:27 see the different users here we have
  • 00:32:29 different different email addresses and
  • 00:32:31 this now all seems to work this was a
  • 00:32:33 pretty complex video I guess especially
  • 00:32:37 with this dynamic graph QL can use this
  • 00:32:40 as a function and get the value thing
  • 00:32:43 but this is a core feature of graph QL
  • 00:32:45 and really powerful as you can tell and
  • 00:32:47 combined with the code which is now at
  • 00:32:49 least a bit more organized I'm really
  • 00:32:53 liking the progress we made thus far
  • 00:32:54 this was a huge step forward definitely
  • 00:32:57 dive into my source code which you find
  • 00:33:00 in the video description to have a look
  • 00:33:03 at it in detail in case I lost you
  • 00:33:05 somewhere otherwise of course I hope I
  • 00:33:08 see you in the next part too