# HTTP Servers Persisting Data in MongoDB

# HTTP Servers Persisting Data in MongoDB

In the previous article and the corresponding video, we wrote a basic HTTP server from scratch. We used Go 1.22's new capabilities to deal with different HTTP verbs and we deserialized data that was sent from an HTTP client.

Exchanging data is worthless if you forget it right away. We are going to persist that data using MongoDB. You will need a MongoDB Atlas cluster. The free one is more than enough. If you don't have an account, you can find guidance on how this is done on this workshop or YouTube. You don't have to do the whole lab, just the parts "Create an Account" and "Create a Cluster" in the "MongoDB Atlas" section. Call your cluster "NoteKeeper" in a **FREE** cluster. Create a username and password which you will use in a moment. Verify that your IP address is included. Verify that your server's IP address is allowed access. If you use the codespace, include the address 0.0.0.0 to indicate that access is allowed to any IP.

## Connect to MongoDB Atlas from Go

1.  So far, we have used packages of the standard library, but we would like to use the MongoDB driver to connect to our Atlas cluster. This adds the MongoDB Go driver to the dependencies of our project, including entries in `go.mod` for it and all of its dependencies. It also keeps hashes of the dependencies in `go.sum` to ensure integrity and downloads all the code to be able to include it in the program.
    ```shell
    go get go.mongodb.org/mongo-driver/mongo
    ```
2.  MongoDB uses BSON to serialize and store the data. It is more efficient and supports more types than JSON (we are looking at you, dates, but also BinData). And we can use the same technique that we used for deserializing JSON for converting to BSON, but in this case, the conversion will be done by the driver. We are going to declare a global variable to hold the connection to MongoDB Atlas and use it from the handlers. That is **not** a best practice. Instead, we could define a type that holds the client and any other dependencies and provides methods –which will have access to the dependencies– that can be used as HTTP handlers.
    ```go
    var mdbClient *mongo.Client
    ```
3.  If your editor has any issues importing the MongoDB driver packages, you need to have these two in your import block.
    ```go
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    ```
4.  In the `main` function, we initialize the connection to Atlas. Notice that this function returns two things. For the first one, we are using a variable that has already been defined at the global scope. The second one, `err`, isn't defined in the current scope, so we could potentially use the short variable declaration here. However, if we do, it will ignore the global variable that we created for the client (`mdbClient`) and define a local one only for this scope. So let's use a regular assignment and we need `err` to be declared to be able to assign a value to it.
    ```go
    var err error
    mdbClient, err = mongo.Connect(ARG1, ARG2)
    ```
5.  The first argument of that `Connect()` call is a context that allows sharing data and cancellation requests between the main function and the client. Let's create one that is meant to do background work. You could add a cancellation timer to this context, among other things.
    ```go
    ctxBg := context.Background()
    ```
6.  The second argument is a struct that contains the options used to create the connection. The bare minimum is to have a URI to our Atlas MongoDB cluster. We get that URI from the cluster page by clicking on "Get Connection String." We create a constant with that connection string. **Don't** use this one. It won't work. Get it from **your** cluster. Having the connection URI with user the and password as a constant isn't a best practice either. You should pass this data using an environment variable instead.
    ```go
    const connStr string = "mongodb+srv://yourusername:yourpassword@notekeeper.xxxxxx.mongodb.net/?retryWrites=true&w=majority&appName=NoteKeeper"
    ```
7.  We can now use that constant to create the second argument in place.
    ```go
    var err error
    mdbClient, err = mongo.Connect(ctxBg, options.Client().ApplyURI(connStr))
    ```
8.  If we cannot connect to Atlas, there is no point in continuing, so we log the error and exit. `log.Fatal()` takes care of both things.
    ```go
    if err != nil {
            log.Fatal(err)
    }
    ```
9.  If the connection has been successful, the first thing that we want to do is to ensure that it will be closed if we leave this function. We use `defer` for that. Everything that we defer will be executed when it exits that function scope, even if things go badly and a panic takes place. We enclose the work in an anonymous function and we call it because defer is a statement. This way, we can use the return value of the `Disconnect()` method and act accordingly.
    ```go
    defer func() {
            if err = mdbClient.Disconnect(ctxBg); err != nil {
                    panic(err)
            }
    }()
    ```

## Persist data in MongoDB Atlas from Go
 has all the code for this series and the next ones so you can follow along.

Stay curious. Hack your code. See you next time!

  [1]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt10326f71fc7c76c8/6630dc2086ffea48da8e43cb/persistence.jpg