Section 5: Programming
πΉ MongoDB with Go (Golang)
Complete tutorial on using MongoDB with Go - CRUD operations, aggregation, best practices
8
Complete Examples
CRUD
Full Operations
100%
Production Ready
Go 1.18+
Modern Go
Setup & Installation
Get started with MongoDB Go driver
Install Go Driver
Install the official MongoDB Go driver:
Terminal
go get go.mongodb.org/mongo-driver/mongo go get go.mongodb.org/mongo-driver/bson
π‘ Driver Version
This tutorial uses the official MongoDB Go driver v1.12+. Make sure you have Go 1.18 or later installed.
Project Structure
Project Layout
myproject/
βββ go.mod
βββ go.sum
βββ main.go
βββ models/
βββ user.go
Connecting to MongoDB
Establish database connection
Basic Connection
main.go
package main import ( "context" "fmt" "log" "time" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) func main() { // Create context with timeout ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() // Connection string // Local: "mongodb://localhost:27017" // Atlas: "mongodb+srv://user:pass@cluster0.mongodb.net/" uri := "mongodb://localhost:27017" // Create client client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri)) if err != nil { log.Fatal(err) } defer func() { if err = client.Disconnect(ctx); err != nil { log.Fatal(err) } }() // Ping the database err = client.Ping(ctx, nil) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") // Get database and collection database := client.Database("myapp") collection := database.Collection("users") fmt.Println("Collection:", collection.Name()) }
β
Connection Established!
Run with: go run main.go
Define Data Model
models/user.go
package models import ( "time" "go.mongodb.org/mongo-driver/bson/primitive" ) type User struct { ID primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"` Name string `json:"name" bson:"name"` Email string `json:"email" bson:"email"` Age int `json:"age" bson:"age"` Active bool `json:"active" bson:"active"` CreatedAt time.Time `json:"created_at" bson:"created_at"` UpdatedAt time.Time `json:"updated_at" bson:"updated_at"` }
π‘ BSON Tags
bson:"_id,omitempty"- MongoDB's _id fieldbson:"name"- Maps Go field to BSON fieldjson:"name"- JSON serializationomitempty- Omit if empty
Insert Operations
Create documents
Insert One Document
Insert One
func insertOne(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Create user user := models.User{ Name: "Alice Johnson", Email: "alice@example.com", Age: 28, Active: true, CreatedAt: time.Now(), UpdatedAt: time.Now(), } // Insert document result, err := collection.InsertOne(ctx, user) if err != nil { log.Fatal(err) } fmt.Printf("Inserted document with ID: %v\n", result.InsertedID) }
Insert Many Documents
Insert Many
func insertMany(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Create users users := []interface{}{ models.User{ Name: "Bob Smith", Email: "bob@example.com", Age: 35, Active: true, CreatedAt: time.Now(), UpdatedAt: time.Now(), }, models.User{ Name: "Carol White", Email: "carol@example.com", Age: 42, Active: false, CreatedAt: time.Now(), UpdatedAt: time.Now(), }, models.User{ Name: "David Brown", Email: "david@example.com", Age: 29, Active: true, CreatedAt: time.Now(), UpdatedAt: time.Now(), }, } // Insert documents result, err := collection.InsertMany(ctx, users) if err != nil { log.Fatal(err) } fmt.Printf("Inserted %d documents\n", len(result.InsertedIDs)) }
Find Operations
Query documents
Find One Document
Find One
import "go.mongodb.org/mongo-driver/bson" func findOne(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Create filter filter := bson.M{"email": "alice@example.com"} // Find one document var user models.User err := collection.FindOne(ctx, filter).Decode(&user) if err != nil { if err == mongo.ErrNoDocuments { fmt.Println("No document found") return } log.Fatal(err) } fmt.Printf("Found user: %+v\n", user) }
Find Many Documents
Find Many
func findMany(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Find active users filter := bson.M{"active": true} // Options: Sort by name, limit to 10 opts := options.Find().SetSort(bson.D{{"name", 1}}).SetLimit(10) // Find documents cursor, err := collection.Find(ctx, filter, opts) if err != nil { log.Fatal(err) } defer cursor.Close(ctx) // Iterate through results var users []models.User if err = cursor.All(ctx, &users); err != nil { log.Fatal(err) } fmt.Printf("Found %d users\n", len(users)) for _, user := range users { fmt.Printf(" - %s (%s)\n", user.Name, user.Email) } }
Query Operators
Complex Queries
func complexQuery(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Find users with age >= 25 and age <= 40 filter := bson.M{ "age": bson.M{ "$gte": 25, "$lte": 40, }, "active": true, } cursor, err := collection.Find(ctx, filter) if err != nil { log.Fatal(err) } defer cursor.Close(ctx) var users []models.User cursor.All(ctx, &users) fmt.Printf("Found %d users between 25-40\n", len(users)) }
π‘ Common Query Operators
$eq- Equal to$gt, $gte- Greater than (or equal)$lt, $lte- Less than (or equal)$in- Matches any value in array$and, $or- Logical operators$regex- Regular expression match
Update Operations
Modify documents
Update One Document
Update One
func updateOne(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Filter filter := bson.M{"email": "alice@example.com"} // Update update := bson.M{ "$set": bson.M{ "age": 29, "updated_at": time.Now(), }, } // Update one document result, err := collection.UpdateOne(ctx, filter, update) if err != nil { log.Fatal(err) } fmt.Printf("Matched %d, Modified %d\n", result.MatchedCount, result.ModifiedCount) }
Update Many Documents
Update Many
func updateMany(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Update all inactive users filter := bson.M{"active": false} update := bson.M{ "$set": bson.M{ "active": true, "updated_at": time.Now(), }, } // Update many documents result, err := collection.UpdateMany(ctx, filter, update) if err != nil { log.Fatal(err) } fmt.Printf("Updated %d documents\n", result.ModifiedCount) }
π‘ Update Operators
$set- Set field value$unset- Remove field$inc- Increment numeric value$push- Add to array$pull- Remove from array
Delete Operations
Remove documents
Delete One & Many
Delete Operations
func deleteOne(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Delete by email filter := bson.M{"email": "alice@example.com"} result, err := collection.DeleteOne(ctx, filter) if err != nil { log.Fatal(err) } fmt.Printf("Deleted %d document\n", result.DeletedCount) } func deleteMany(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Delete users older than 50 filter := bson.M{ "age": bson.M{"$gt": 50}, } result, err := collection.DeleteMany(ctx, filter) if err != nil { log.Fatal(err) } fmt.Printf("Deleted %d documents\n", result.DeletedCount) }
Aggregation Pipeline
Complex data operations
Basic Aggregation
Aggregation Example
func aggregation(collection *mongo.Collection) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Pipeline: Group by active status and count pipeline := mongo.Pipeline{ bson.D{{"$match", bson.D{{"age", bson.D{{"$gte", 25}}}}}}, bson.D{{"$group", bson.D{ {"_id", "$active"}, {"count", bson.D{{"$sum", 1}}}, {"avgAge", bson.D{{"$avg", "$age"}}}, }}}, bson.D{{"$sort", bson.D{{"count", -1}}}}, } // Execute aggregation cursor, err := collection.Aggregate(ctx, pipeline) if err != nil { log.Fatal(err) } defer cursor.Close(ctx) // Process results type Result struct { ID bool `bson:"_id"` Count int `bson:"count"` AvgAge float64 `bson:"avgAge"` } var results []Result if err = cursor.All(ctx, &results); err != nil { log.Fatal(err) } for _, result := range results { fmt.Printf("Active: %v, Count: %d, Avg Age: %.1f\n", result.ID, result.Count, result.AvgAge) } }
Best Practices
Production-ready code
Connection Pool & Context
β οΈ Important Tips
- Reuse Client: Create one client, reuse across app
- Use Context: Always use context with timeout
- Defer Close: Always close cursors and disconnect
- Error Handling: Check all errors properly
- Connection Pool: Driver handles pooling automatically
Complete Example
Production-Ready Code
package main import ( "context" "fmt" "log" "time" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) type MongoDB struct { Client *mongo.Client DB *mongo.Database } func NewMongoDB(uri, dbName string) (*MongoDB, error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri)) if err != nil { return nil, err } if err := client.Ping(ctx, nil); err != nil { return nil, err } return &MongoDB{ Client: client, DB: client.Database(dbName), }, nil } func (m *MongoDB) Close() error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() return m.Client.Disconnect(ctx) } func main() { // Initialize db, err := NewMongoDB("mongodb://localhost:27017", "myapp") if err != nil { log.Fatal(err) } defer db.Close() fmt.Println("β Connected to MongoDB!") // Use collections collection := db.DB.Collection("users") // Your operations here... }