Developing a RESTful API with Golang and a MongoDB NoSQL Database

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this tutorial we're gonna take a look at developing a REST API using the go programming language and MongoDB because as of right now does offer an official go SDK but before we get into the core material of this particular tutorial I want to give a shout out to digital ocean because they are a sponsor of this particular video if you're unfamiliar with digital ocean they are a great service that offers manage kubernetes compute object storage and a bunch of other great stuff towards developing and deploying your own applications if you'd want to get started with digital ocean I do have a promo code that I can give you go ahead and go to do dot CEO slash polyglot in your web browser and you'll get $100 credit towards your account if you sign up so jumping into the core material of this particular tutorial you'll notice that I do have my terminal up and I do have a shell client for what is actually docker open so I am running MongoDB through docker you could be running it locally you could be running it remotely maybe on digitalocean that's totally up to you but the fact of the matter is that I already have set up you'll notice in another tab I am in my go path so we will be developing our application here you just need to create a new directory in your go path and we'll want to create a new file in our go path called main dot go so with this ready to go let's go ahead and open up this project I'm going to be using atom by github in order to do my coding but feel free to use whatever you want whatever is most convenient to you so I do have my file open let's go ahead and actually before we start coding let's go ahead and get our project dependencies so there are two dependencies the first dependency will be our multiplexer for handling our HTTP requests so we can say go get github.com slash guerilla slash MUX so this is the gorilla MUX multiplexer the next thing we'll want is that MongoDB go SDK so we can say go get Hubb calm / MongoDB / go driver let's see that I make them the spelling mistake here so I actually messed that one up it's actually DB / go driver / sorry about that I was confused to what I was typing for a second but that is actually what you want so go ahead and do go get with the package manager those are the only two dependencies that we need with those we can go back into our code and we can start adding our boilerplate logic to our application so we can add our package we can add our main function and maybe we can even do a print message to show that it's working so we can save it you can see that my editor does add imports in for me automatically if yours doesn't don't worry at the end of this tutorial I'll scroll up and you'll have a chance to grab any of the dependencies that might have not been added on your end so with this with the line started we can start we there's a few things that we want to do we want to establish a connection to MongoDB we want to define our data model to be used throughout the application and in our collection and we wanted to find our endpoints so what we can do first is we can actually define our model so let's go ahead and say type person struct and we're basically going to have one collection and this collection is going to have a few properties as far as each of our documents goes and nothing more we're going to try to keep it simple but you could easily expand upon this on your own so we're gonna have an ID this is going to be a primitive and it's going to be object ID so this is MongoDB es own object ID for the ID we are gonna have annotations here so that way we can map our native go structure between both JSON and B song so we're gonna say JSON this is gonna be ID with an underscore omit empty for beasts on it's gonna be the same and we're doing this just so that way we have something to play around with something that prints nicely and beasts on is the official annotation for MongoDB so that beasts on will be used in order to Marshall and unmarshal our data structures into something understands but our JSON is going to be for something our web browser client understands so we have beasts on it's gonna be ID omit empty we're gonna have a first name this is gonna be of type string and we're gonna keep it simple JSON is gonna be first name we're gonna have beasts on it's gonna be first name I'm it empty we're gonna have a last name and you can see where we're going with this all right so we have our data model here which is our our structure and go the next thing we want to do is we want to create an instance for our client connection and we're going to do this outside of the main function so that way it can be used within each of our endpoints so I'm gonna say the following I'm gonna say VAR client and that's gonna be of type client inside of our main function we can actually establish the connection so that way when when we run our application the connection starts to get established but in order to do that we need to be defining timeouts for and go so we want to define what's called a context and then pass that context into our connection so first of all it would look something like this and I'm gonna skip the errors in production you definitely want to keep track of your errors and and respond appropriately but we're gonna skip them for this particular tutorial I'm gonna say context with the timeout the parent is gonna be context out background and then the timeout value let's go ahead and say that's 10 and that's gonna be seconds with our context value we can say something like client which we've already defined equals client we're going to pass in that context and we're gonna pass in our connection string in this case it's going to be DB localhost and we're gonna give it the port that it needs all right and it's actually not client again I made another business mistake this is actually doc connect all right so the next step is well we want to define our router so we're gonna say router equals MUX dot new router and we're gonna say HTTP dot listen and serve we're gonna listen on port 1 2 3 4 5 and we're going to pass in the router so you could go ahead and use the HTTP packages that ship with go but I've always found that the gorilla MUX multiplexer always works a little easier so we don't have any end points yet we just have a connection to and if we really wanted to we could run this and it should work out fine so let's go ahead and say go run and it says starting the application great everything should be good well trust it for now so let's go ahead and start adding our endpoints in so as of right now let's go ahead and assume that there's no data in our database so we're gonna create an endpoint for creating data so this will be a post endpoint but we're gonna say function let's go ahead and give it a name we'll call it create person endpoint it doesn't really matter what you call it but we're gonna have a response and this is gonna be of type HTTP response writer we're gonna have a request which is gonna be of type HTTP dot request and inside of it the first thing we want to do is we want to determine what our response type is going to be the user we could we could respond with whatever we want but the user will probably anticipate JSON because that's kind of the norm lately so we're gonna say response dot header dot add content type application slash JSON so with the response added let's go ahead and marshal in our request body because this is gonna be a post request we're gonna anticipate that we're gonna get a JSON payload or body so we need to we need to convert that into an object that we can actually work with and go so we're gonna save our person type person and we're gonna say equals JSON new decoder this is going to be request stop body dot decode and we're going to decode it right into that person alright so that would be whatever the user passes in to us and technically we we don't need this let's just go ahead and skip it let's go ahead and now what we want to do is we want to query the database well not query but we actually want to open our collection so let's say collection equals dot database right now we're not gonna we're just gonna hard code the database and each one of our our endpoints typically you would probably want to do this globally just like for the context do you could probably do this globally as well so that way it's kind of universal for everything but for this example we're just gonna hard code it right in so we're gonna say the polyglot developer that's gonna be the name of our database and I'm gonna use the collection people plural so we have our collection the next step is to define the timeout so I'm just gonna copy and paste it and once we have that timeout we can say something like result collection dot insert one provide that context and provide whatever we're planning on inserting which would in this case would be person and then finally it might make sense to actually return the results of that insert and will return something special so let's go and say json dot new encoder we're gonna say response encode result and i'm going to save it so as of right now all it should be good so we don't have anything hooked up to this function so let's go ahead and add that so what we want to do is we want to create our path we want to define what what method can access it and then we want to link up that function so we can say router dot handle function the path let's go ahead and say this is gonna be person we're gonna be passing in one particular person just add it a little bit more than we needed to here but this is gonna be create person endpoint and for methods it's going to be a post method I'm gonna save it so at this point it part makes sense to actually run this let's go ahead and go run it I'm going to open up postman we're gonna switch this to a post request I'm going to say localhost one two three four five have person for the body this is gonna be a JSON body and I'm gonna provide a first name which is going to be Nick and a last name which is gonna be Raboy and I'm gonna send it and you can see that I now have an inserted ID so if I had to take a wild guess I'd say that this insert probably succeeded so with that rather than looking directly in our database let's go ahead and create another endpoint this endpoint is going to be responsible for getting documents from our collection so let's go ahead and create another endpoint I'm gonna call it function let's say get people endpoint plural people response issue two P dot response writer and this is gonna be a request HTTP dot request again I wanted to find what the response formats gonna be in this case is gonna be JSON and this is gonna be where things get a little complicated because with MongoDB you will be working with cursors for all of your data similar to how you would with a relational database so if you've ever worked with Oracle or Java like I have you're probably familiar with working with cursors and having to iterate over them for your results it's not a big deal it just adds a little bit of complexity to your actual code and and it's not really complexity it's just length to your code but we want to do is we want to save our we want to say people this is gonna be a slice of person and we're gonna we're gonna establish our collection which is going to be people again so collection equals client database again the polyglot developer which could be hard-coded or put into a configuration file or passed in and this is going to be people which is could also be in a configuration file as well we're going to define our context so let me just copy this line again and we're gonna try to actually do a find and we're going to end up with a cursor so we're gonna say cursor we will catch our error this time collection dot find so this is gonna be our context and then we're gonna say be song dot em with an empty an empty object here and what we're saying by doing this is we're saying you know what return everything in our collection because if you've worked with the other languages before you can generally pass in the query parameters or even if you were using the the shell right now we're just we're just doing an empty object which would be everything let's go ahead and spell cursor correctly so that way it doesn't cause me problems down the line but let's go ahead and now first check to see if there was an error so if error not equal to nil then what we can say is we can say response dot right header we can say HTTP dot status internal server error if we want that should be HTTP so there are there are default kind of server errors here we're gonna say response dot right this is going to be a byte slice and we're just gonna say this is going to be message and we're gonna say error dot error so we're gonna we're gonna return this string and we're doing this because we want to return JSON because this is what we expect as far as our header goes and so that way the rest of our code doesn't execute we're going to return out but assuming that the error didn't trigger let's go ahead and proceed as normal so when we're done with the cursor when we're done with this function let's go ahead and close it so we can say defer cursor close passing in the context and we're gonna loop through that cursor now so we're gonna say for cursor dot next I'm gonna provide the context we're gonna save our person which is of type person I'm gonna say cursor dot decode we're going to decode the current value in that cursor to the person variable and we're going to append it to our people slice so people equals a pen people person and because remember we can't just assign it all to this person slice because it's it's not gonna be 4-minute correctly it's gonna be formatted in terms of Mungo cursor language or whatever you want to call it so we do have to loop through that cursor and we do have the store each item to be returned so we're adding it there after we're done with that after we've populated that people slice we're gonna check to see if there were any errors with the cursor because these would be different than the actual fine statement itself so we're gonna say if error equals cursor error we're gonna say error not equal to nil and we're gonna say let's go ahead and return an error let's so let's go ahead and copy what we have here save us some typing we're gonna say yeah this could be a server error and whatever the error is let's go ahead and return the message and return it so just just more error handling I know I said that I wasn't going to do it but this kind of makes sense to do the error handling here and then finally if there if everything went smooth what we can do is we can say JSON new encoder response and code people and save it so let's go ahead and restart that application here I'm gonna run it this time we should still have one item in the database so I'm gonna say this is a people endpoint now this is going to be get and I'm gonna say send 404 not found yeah so it's not found because I never actually configured it we created the function but we never hooked it up so let's go ahead and hook it up now I just clone that line I'm gonna call this people plural so this is going to be the get people endpoint and this is gonna be a get method so let's try to run it now I should work this time so going back to postman I'm gonna hit Send and it returned one item so remember my my native code data structure it includes an ID includes the first name and a last name could easily include more it doesn't matter but the fact of the matter is we have one item in the database and it returned it as an array so so far so good let's go ahead and add another end point so that way we can actually make use of our query a little bit better this time around we're going to query for one particular entry so let's go ahead and create another endpoint function so we're going to say actually what I want to do is I'm gonna I'm just gonna copy and paste so I copied one this is going to be instead of create person it'll be get person so person singular as in one person and we're gonna we're gonna do some minor changes inside of here so we're returning application JSON we're gonna say params equals MUX VARs request and the reason why we're doing this is because we will have route parameters in the request that we're going to extract so it's not just going to be a request body we're gonna say ID equals primitive dot object ID from hex and the reason why we're doing this is because we're gonna be passing in an ID and we need to actually convert it into a usable MongoDB object ID you can't just use a string you have to convert it so params ID we're gonna save our person person and we are going to set up our contacts and we're going to set up our opening of the collection so we can copy and paste that again so I copied and pasted it we were using the the polyglot developer database we're using the people collection and we're setting up our context with that out of the way we can say error equals collection dot find one and we're gonna say pass in our context and we're going to pass in our search remember how we use BCAM above this time we're gonna be a little more specific because we've modeled our data structure after our collection so what we can actually say is we can say person we're going to provide an ID and we're going to use the ID that we had set on line 62 and when that's done we're gonna decode it into our person object that we had set up if there was an error then we're gonna we're gonna return a negative response so we can just copy this again we're not using a cursor this time because we're only finding one record but if there's an error we're gonna return it otherwise json dot new encoder a response encode person let's go ahead and save it I'm gonna run it and then I'm gonna I'm gonna revisit this to just kind of reiterate some things so I'm going to restart it go back to postman here I'm going to copy this ID and then it changed the endpoint here to person pass in that route parameter it's gonna fail again because I just realized that I didn't I didn't create a route for it so let's go ahead and create that route this one's going to be person and we we do need to configure an ID so we need to say ID this will be get person endpoint if I restarted it now it should work so run it and I get one record back it's not an array which is good so you'll see that this right here is ID that matches what we have in our request parameters they could be name whatever you want as long as they match but just to reiterate here and this is something that kind of threw me up for a little bit I had a tough time understanding it based on the documentation that was available you can't you can't just say be song dot m and then pass in some parameters it didn't work that way what I had to do was I had to create I had to use the person object I had to use the person data structure I also had to not use a string I had to convert it into an actual object ID so those threw me up for a little while now if you wanted to you can continue to go down the line you could add update you could add delete it's more or less gonna be the same thing update would youwould what you do is you you would first get a document based on kind of like this get person in point then do it do a change so on and so forth but it's not too difficult but just just the kind of rehash here we did do our annotations for peace on so that way we could easily map our documents to our code data structures we established a MongoDB client which we connected to at the bottom here we did have to work with the context we created three end points using the guerilla MUX multiplexer and then in each one of these kind of queries or end points for what for example insert one we just used the the person payload because it was correctly mapped with beasts on forget people it was a little more complex because we had to use a cursor and loop through and and you could you could edit this you don't have to return everything you could return more than one document based on some parameters but inside of the get person we just we just got one particular document so this is some pretty powerful stuff you could easily host this on digitalocean or or wherever it's convenient for you but at least now you have an idea on how to use with the go programming language
Info
Channel: The Polyglot Developer
Views: 51,065
Rating: undefined out of 5
Keywords: golang, go, mongodb, nosql, database, rest, restful, api, mux
Id: oW7PMHEYiSk
Channel Id: undefined
Length: 24min 38sec (1478 seconds)
Published: Wed Feb 20 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.