Hi there!

Today we will look at how to use mongo with golang. And let’s start with the launch of mongo. I will use docker-compose. To do this, create a file named docker-compose.yml. In the file, you need to specify which version of the mongo to use. I’m not specifying the version which means that the latest version of mongo will be used. You must also specify a username and password and the port that will be open for access.

version: '3.1'

services:

  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
    ports:
      - 27017:27017

Once the file is saved, run the docker-compose up -d (Docker and docker-compose must be installed) and the mongo container will be launched.

The mongo configuration is complete and we can get started with the code. Initialize the go module and download the mongo driver

go mod init
go get go.mongodb.org/mongo-driver/mongo

Let’s create main.go and start coding. We will start with the mongoInsert method which will write data to the database. The method calls mongo.Connect in which the context and parameters are passed. As parameters, I pass a link to mongo in the format mongodb://username:password@mongoAddress:mongoPort. I also create a timeout context to automatically terminate queries if they last longer than necessary. To make a query, you need to create a structure that will have fields that need to be written to the database. I have a structure User with two fields Name and Surname of type string. An annotation should be added to each of the fields, indicating how the field will be named in the database. The method for writing data is InsertOne and it returns a mongo record ID. Which will be printed after a successful insert request. The database and collection will be created automatically after the insert operation.

package main

import (
    "context"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type User struct {
    Name    string `bson:"name"`
    Surname string `bson:"surname"`
}

func main() {
    err := mongoInsert()
    if err != nil {
        log.Fatalln(err)
    }
}

func mongoInsert() error {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://root:password@127.0.0.1:27017"))
    if err != nil {
        return err
    }
    defer client.Disconnect(ctx)

    collection := client.Database("mpostument").Collection("users")
    user := User{
        Name:    "Maksym",
        Surname: "Postument",
    }

    res, err := collection.InsertOne(ctx, user)
    if err != nil {
        return err
    }
    id := res.InsertedID
    log.Printf("Insert ID, %s", id)
    return nil

}

You can now connect to the database and see if there are any entries. To do this, connect to the docker container

docker ps
# Copy CONTAINER ID and execute
docker exec -it a61578b802e7 bash

Now let’s call the console client

mongo -u root -p password

Let’s connect to the created database

> use mpostument
switched to db mpostument

And get data from the database

> db.users.findOne()
{
    "_id" : ObjectId("6231a26576e5effdd561a9d8"),
    "name" : "Maksym",
    "surname" : "Postument"
}

Now let’s see how you can read the data from mongo with golang. The beginning of the method is the same, a client is created and connected to the collection. Next, create a variable user with type User(a structure which we created) and call the method FindOne in which I pass the context and filter to search. In my version, we are looking for an object in which the name field is equal to Maksym. And decode results in to a variable user

func main() {

    err = mongoGet()
    if err != nil {
        log.Fatalln(err)
    }
}

func mongoGet() error {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://root:password@127.0.0.1:27017"))
    if err != nil {
        return err
    }
    defer client.Disconnect(ctx)
    collection := client.Database("mpostument").Collection("users")

    var user User

    res := collection.FindOne(ctx, bson.D{{"name", "Maksym"}})
    res.Decode(&user)
    fmt.Println(user)
    return nil
}

You can also use the Find method instead of FindOne, which will return many objects.