Working with the database is a fundamental part of the backbone development, especially when you are creating an application that requires keeping data, questioning and updating data.
In the go, Official Mongo DB Driver Mongo provides a strong way to connect and interact with DB, a flexible NOSQL database that saves data in documents like JSON.
In this tutorial, you will not only learn how to contact Mango DB. You will take a step further by making a simple blog application. On the way, you will learn how to perform the CRUD (created, read, update, delete) and showcase your results using the web framework.
The table of content
Provisions
Before proceeding, make sure you have the following:
Basic knowledge Barley And the concepts of it
Go (version 1.24 or more) installed
Mongo DB Install (running locally on Port 27017)
The basic knowledge of nosql
Create a new GO Project
First, create a new GO project, convert new project directory, and start a new GO module by running the following orders:
mkdir go-mongodb-integration
cd go-mongodb-integrationgo
mod init go-mongodb
Next, install the Mango DB Go driver by running the following command:
go get go.mongodb.org/mongo-driver/mongo
go get go.mongodb.org/mongo-driver/bson
Included to the standard go library database/sql
The package to work with the SQL database, but it does not support Mango DB out of the box. Go to work with Mangod B, you will use the official Mongo DB driver, which provides you with everything you need to connect and interact with the Mango DB Database.
With the completion of the basic setup, now check the basic operations in Mongo DB.
Basic Mango DB Operations
In Mangod B, the database and Combination Adopting the “slow creation” approach, the first data is automatically created. In particular, a database is developed when you enter your first document, and so is a combination when the data is first inserted into it.
It is important to note that the functions are like client.Database()
And db.Collection()
Just create references to these structures – they do not create the original database or collection until the data is entered.
Enter the data in the collection
Let’s follow the way to enter a document in a collection in Mongo DB.
First, open your project in code editor, make a main.go
File, and Add the code below:
package main
import (
"context"
"log"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
Name string `bson:"name"`
Age int `bson:"age"`
}
func main() {
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal(err)
}
db := client.Database("test_db")
usersCollection := db.Collection("users")
newUser := User{
Name: "John Doe",
Age: 30,
}
result, err := usersCollection.InsertOne(ctx, newUser)
if err != nil {
log.Fatal(err)
}
log.Printf("Inserted user with ID: %v\n", result.InsertedID)
}
In the aforementioned code, you describe a User
Structure Which represents the structure of your document, then insert a new user document in the combination using it InsertOne
Method when you run the process of inserting, Mongo DB automatically creates both test_db
Database and users
Submitting if they are not already present.
Follow the code by running:
go run main.go
You should see the answer below, which shows that the user was successfully admitted.
Find documents in Mongo DB
Now that you have entered some data, it is time to inquire from the database and recover the documents.
Do your update main.go
File with the following code:
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
Name string `bson:"name"`
Age int `bson:"age"`
}
func main() {
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
db := client.Database("test_db")
usersCollection := db.Collection("users")
cursor, err := usersCollection.Find(ctx, bson.M{})
if err != nil {
log.Fatal(err)
}
defer cursor.Close(ctx)
var users ()User
if err = cursor.All(ctx, &users); err != nil {
log.Fatal(err)
}
for _, user := range users {
fmt.Printf("User: %s, Age: %d, ID: %s\n", user.Name, user.Age, user.ID.Hex())
}
}
In the aforementioned code, you use Find
To recover all documents from procedures with an empty filter (`bson.m}) users
Collection then, you use cursor.All
To decode all the results in a piece User
Structure
Each document is hidden on the terminal, showing each username, age and ID in the collection.
To run the code, use:
go run main.go
You should see the answer below in your terminal.
Update documents in Mongo DB
To update a document in your collection, change yourself main.go
As shown below file:
package main
import (
"context"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
Name string `bson:"name"`
Age int `bson:"age"`
}
func main() {
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
db := client.Database("test_db")
usersCollection := db.Collection("users")
var userToUpdate User
err = usersCollection.FindOne(ctx, bson.M{"name": "John Doe"}).Decode(&userToUpdate)
if err != nil {
log.Println("No user found to update")
} else {
update := bson.M{
"$set": bson.M{
"name": "Jane Doe",
"age": 25,
},
}
result, err := usersCollection.UpdateOne(
ctx,
bson.M{"_id": userToUpdate.ID},
update,
)
if err != nil {
log.Fatal(err)
}
log.Printf("Updated %v document(s)\n", result.ModifiedCount)
}
}
In the aforementioned code, you first find a user called “John Do” FindOne
Method If a match is found, you use UpdateOne
How to update their names and age. $set
The operator ensures that only specific fields are updated, which does not change the rest of the documents.
Follow the code by running:
go run main.go
You should see output in your terminal, which shows how many documents have been updated.
Delete documents in Mongo DB
Removing documents from a collection LOY, you can use DeleteOne
Method your refreshing main.go
File with the following code:
package main
import (
"context"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
Name string `bson:"name"`
Age int `bson:"age"`
}
func main() {
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
db := client.Database("test_db")
usersCollection := db.Collection("users")
result, err := usersCollection.DeleteOne(ctx, bson.M{"name": "Jane Doe"})
if err != nil {
log.Fatal(err)
}
log.Printf("Deleted %v document(s)\n", result.DeletedCount)
}
In the aforementioned code, you use DeleteOne
How to remove the first document that matches the filter { "name": "Jane Doe" }
.
You should see the bottom result in your terminal.
How to create a blog app with go-mangov driver and whom
Now when you think how to do basic crore operation with Mongo DB in GO, you are ready to make more full application.
Make a new directory for your project and start it as a go module. Go to your selected directory and run:
mkdir go-blog
cd go-blog
go mod init blog
Next, Install the desired dependent:
go get github.com/gin-gonic/gin
go get go.mongodb.org/mongo-driver/mongo
go get go.mongodb.org/mongo-driver/bson
The following structure will be in your project:
go-blog/
├── main.go
├── handlers/
│ └── main.go
└── templates/
├── index.html
├── post.html
├── create.html
└── edit.html
Which application start
To start a new application, make a new main.go
File and add the coded codes to the below:
package main
import (
"context"
"log"
"time"
"blog/handlers"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal(err)
}
log.Println("Connected to MongoDB!")
db := client.Database("blog_db")
h := handlers.NewHandler(db)
router := gin.Default()
router.LoadHTMLGlob("templates/*")
router.GET("/", h.HomePage)
router.GET("/post/:id", h.ViewPost)
router.GET("/create", h.CreatePost)
router.GET("/edit/:id", h.EditPost)
router.POST("/save", h.SavePost)
router.GET("/delete/:id", h.DeletePost)
log.Println("Server starting on :8080...")
router.Run(":8080")
}
The aforementioned code sets the Mango DB connection, which starts the router, and registers your routes.
Make HTML templates
Now, create a HTML templates to display the blog UI.
First, make a templates
Directory and add the following files:
Index.html:
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Go Blog with MongoDBtitle>
<script src="https://cdn.tailwindcss.com">script>
head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<header class="mb-8">
<h1 class="text-3xl font-bold text-center text-blue-600">Go Blog with MongoDBh1>
<div class="flex justify-center mt-4">
<a href="/create" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Create New Posta>
div>
header>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{{range .}}
<div class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300">
<div class="p-6">
<h2 class="text-xl font-semibold mb-2 text-gray-800">{{.Title}}h2>
<p class="text-gray-600 mb-4 line-clamp-3">
{{if gt (len .Content) 150}}
{{slice .Content 0 150}}...
{{else}}
{{.Content}}
{{end}}
p>
<div class="flex justify-between items-center text-sm text-gray-500">
<span>{{.CreatedAt.Format "Jan 02, 2006"}}span>
<a href="/post/{{.ID.Hex}}" class="text-blue-500 hover:text-blue-700">Read Morea>
div>
div>
<div class="flex border-t border-gray-200">
<a href="/edit/{{.ID.Hex}}" class="w-1/2 py-2 text-center text-sm text-gray-600 hover:bg-gray-100 border-r border-gray-200">Edita>
<a href="/delete/{{.ID.Hex}}" class="w-1/2 py-2 text-center text-sm text-red-600 hover:bg-gray-100" onclick="return confirm('Are you sure you want to delete this post?')">Deletea>
div>
div>
{{else}}
<div class="col-span-3 text-center py-12">
<p class="text-gray-600 text-lg">No posts yet. <a href="/create" class="text-blue-500 hover:underline">Create onea>!p>
div>
{{end}}
div>
div>
body>
html>
The template contains a list of all blog posts and includes buttons to make, edit or delete posts.
Post html:
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.Title}} | Go Blog with MongoDBtitle>
<script src="https://cdn.tailwindcss.com">script>
head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<header class="mb-8">
<h1 class="text-3xl font-bold text-center text-blue-600">Go Blog with MongoDBh1>
<div class="flex justify-center mt-4">
<a href="/" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Back to Homea>
div>
header>
<div class="max-w-3xl mx-auto bg-white rounded-lg shadow-md overflow-hidden">
<div class="p-6">
<h2 class="text-2xl font-bold mb-4 text-gray-800">{{.Title}}h2>
<div class="flex items-center text-sm text-gray-500 mb-6">
<span>Posted: {{.CreatedAt.Format "Jan 02, 2006"}}span>
{{if ne .CreatedAt .UpdatedAt}}
<span class="mx-2">•span>
<span>Updated: {{.UpdatedAt.Format "Jan 02, 2006"}}span>
{{end}}
div>
<div class="prose max-w-none">
<p class="text-gray-700 whitespace-pre-line">{{.Content}}p>
div>
div>
<div class="flex border-t border-gray-200">
<a href="/edit/{{.ID.Hex}}" class="w-1/2 py-3 text-center text-blue-600 hover:bg-gray-100 border-r border-gray-200">Edit Posta>
<a href="/delete/{{.ID.Hex}}" class="w-1/2 py-3 text-center text-red-600 hover:bg-gray-100" onclick="return confirm('Are you sure you want to delete this post?')">Delete Posta>
div>
div>
div>
body>
html>
This template shows the same post.
create.html:
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Create New Post | Go Blog with MongoDBtitle>
<script src="https://cdn.tailwindcss.com">script>
head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<header class="mb-8">
<h1 class="text-3xl font-bold text-center text-blue-600">Go Blog with MongoDBh1>
<div class="flex justify-center mt-4">
<a href="/" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Back to Homea>
div>
header>
<div class="max-w-2xl mx-auto bg-white rounded-lg shadow-md overflow-hidden">
<div class="p-6">
<h2 class="text-2xl font-bold mb-6 text-gray-800">Create New Posth2>
<form action="/save" method="POST">
<div class="mb-4">
<label for="title" class="block text-gray-700 font-medium mb-2">Titlelabel>
<input type="text" id="title" name="title" required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
div>
<div class="mb-6">
<label for="content" class="block text-gray-700 font-medium mb-2">Contentlabel>
<textarea id="content" name="content" rows="10" required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">textarea>
div>
<div class="flex justify-end">
<button type="submit" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-md">
Save Post
button>
div>
form>
div>
div>
div>
body>
html>
This template allows you to create a new post.
Edit. html:
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Edit Post | Go Blog with MongoDBtitle>
<script src="https://cdn.tailwindcss.com">script>
head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<header class="mb-8">
<h1 class="text-3xl font-bold text-center text-blue-600">Go Blog with MongoDBh1>
<div class="flex justify-center mt-4">
<a href="/" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Back to Homea>
div>
header>
<div class="max-w-2xl mx-auto bg-white rounded-lg shadow-md overflow-hidden">
<div class="p-6">
<h2 class="text-2xl font-bold mb-6 text-gray-800">Edit Posth2>
<form action="/save" method="POST">
<input type="hidden" name="id" value="{{.ID.Hex}}">
<div class="mb-4">
<label for="title" class="block text-gray-700 font-medium mb-2">Titlelabel>
<input type="text" id="title" name="title" value="{{.Title}}" required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
div>
<div class="mb-6">
<label for="content" class="block text-gray-700 font-medium mb-2">Contentlabel>
<textarea id="content" name="content" rows="10" required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">{{.Content}}textarea>
div>
<div class="flex justify-between">
<a href="/post/{{.ID.Hex}}" class="text-gray-600 hover:text-gray-800">Cancela>
<button type="submit" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-md">
Update Post
button>
div>
form>
div>
div>
div>
body>
html>
This template is used to edit a post.
Make a handler
Next, set the handlers to connect Mongo DB and present the templates. Make a new folder that says handlers
In the Route Directory of your Project, then add main.go
File inside and enter the following code piece:
package handlers
import (
"context"
"log"
"net/http"
"time"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
)
type Post struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
Title string `bson:"title" json:"title"`
Content string `bson:"content" json:"content"`
CreatedAt time.Time `bson:"created_at" json:"created_at"`
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"`
}
type Handler struct {
db *mongo.Database
collection *mongo.Collection
}
func NewHandler(db *mongo.Database) *Handler {
return &Handler{
db: db,
collection: db.Collection("posts"),
}
}
func (h *Handler) HomePage(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
cursor, err := h.collection.Find(ctx, bson.M{})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer cursor.Close(ctx)
var posts ()Post
if err = cursor.All(ctx, &posts); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "index.html", posts)
}
func (h *Handler) ViewPost(c *gin.Context) {
id := c.Param("id")
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
return
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var post Post
err = h.collection.FindOne(ctx, bson.M{"_id": objID}).Decode(&post)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Post not found"})
return
}
c.HTML(http.StatusOK, "post.html", post)
}
func (h *Handler) CreatePost(c *gin.Context) {
c.HTML(http.StatusOK, "create.html", nil)
}
func (h *Handler) EditPost(c *gin.Context) {
id := c.Param("id")
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
return
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var post Post
err = h.collection.FindOne(ctx, bson.M{"_id": objID}).Decode(&post)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Post not found"})
return
}
c.HTML(http.StatusOK, "edit.html", post)
}
func (h *Handler) SavePost(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
id := c.PostForm("id")
title := c.PostForm("title")
content := c.PostForm("content")
now := time.Now()
if id == "" {
post := Post{
Title: title,
Content: content,
CreatedAt: now,
UpdatedAt: now,
}
result, err := h.collection.InsertOne(ctx, post)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
log.Printf("Created post with ID: %v\n", result.InsertedID)
} else {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
return
}
update := bson.M{
"$set": bson.M{
"title": title,
"content": content,
"updated_at": now,
},
}
result, err := h.collection.UpdateOne(ctx, bson.M{"_id": objID}, update)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
log.Printf("Updated post with ID: %s (Modified %d documents)\n", id, result.ModifiedCount)
}
c.Redirect(http.StatusSeeOther, "/")
}
func (h *Handler) DeletePost(c *gin.Context) {
id := c.Param("id")
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
return
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
result, err := h.collection.DeleteOne(ctx, bson.M{"_id": objID})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
log.Printf("Deleted %d document(s) with ID: %s\n", result.DeletedCount, id)
c.Redirect(http.StatusSeeOther, "/")
}
The aforementioned code includes all logic for the management of blog posts. What does every component here do:
Post structure: ID, title, content and timing describes the blog post document structure with fields for time stamp.
bson
Tags explains how the fields are stored in Mangod B, whilejson
Tags handle JSON serialization.Handler structure: The Mango DB Database and Posts contain a reference to the collection, which provides a central way to access the database in your handlers.
New Handler Function: A new handle with a database connection creates and opens the example and sets the posts collection reference.
Homepage: Recovering all blog posts from the database using
Find()
With an empty filter and offers them using themindex.html
Template.View Post: Takes the same post using by its Object
FindOne()
And shows itpost.html
Template.Cretepost and Edit Post: Offer relevant shapes to create new posts or edit existing settings.
Safe Post: Handle both to make new posts and update existing posts. It checks whether the ID has been provided. If not, it produces a new post by using
InsertOne()
. Otherwise, it updates an existing post by usingUpdateOne()
With Mangodb$set
OperatorDeltopost: Removes a post from the database using
DeleteOne()
And instruct to go back to the home page.
Run the application
With everything setup, you can now launch your blog. Open your terminal and drive:
go mod tidy && go run main.go
Then, see To look at your blog in your browser.
How to use Mongo DB with Go
In this tutorial, you created a simple blog application using Go and Mongo DB. You learned how to connect with the Mango DB Database using the Official Go driver, perform the crude operation, and present your results with the web framework.
Mongo DB’s flexible, documentary structure makes it a great fit of applications where the data model needs to be manufactured over time. It allows you to repeat it quickly and grow with the growing of your app.
When you expand this project, consider adding features such as user verification, tagging or rating, comments, pages, or search functionality to enhance the user experience.
Pleased to build more with Go and Mongo DB!