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.