Skip to main content

MongoDB Adapter

goclarc module post --db mongo --schema schemas/post.yaml

What Gets Generated

internal/modules/post/repository.go ← mongo-driver/v2 implementation

No SQL file is generated for MongoDB.

Repository Pattern

The generated repository uses mongo-driver/v2:

type repository struct {
coll *mongo.Collection
}

func NewRepository(db *mongo.Database) Repository {
return &repository{coll: db.Collection("posts")}
}

func (r *repository) GetByID(ctx context.Context, id string) (*Entity, error) {
oid, err := bson.ObjectIDFromHex(id)
if err != nil {
return nil, fmt.Errorf("post not found")
}
var doc bsonPost
if err := r.coll.FindOne(ctx, bson.M{"_id": oid}).Decode(&doc); err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, fmt.Errorf("post not found")
}
return nil, fmt.Errorf("post.repository.GetByID: %w", err)
}
return bsonToEntity(&doc), nil
}

Internal Document Type

The repository uses an internal bsonPost struct that maps the primary key to bson.ObjectID:

type bsonPost struct {
ID bson.ObjectID `bson:"_id,omitempty"`
Title string `bson:"title"`
Content string `bson:"content"`
}

The bsonToEntity() function converts ObjectID.Hex() back to the string ID in your Entity.

JSON Fields

For type: json fields, the MongoDB adapter uses bson.M:

// Entity
Metadata bson.M

// View
Metadata bson.M

Partial Updates

The Update method builds a $set document from non-nil fields only:

set := bson.M{}
if p.Title != nil { set["title"] = p.Title }
if p.Content != nil { set["content"] = p.Content }
r.coll.FindOneAndUpdate(ctx, bson.M{"_id": oid}, bson.M{"$set": set}, opts)

Required Imports

import (
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
go get go.mongodb.org/mongo-driver/v2

Connection Setup

client, err := mongo.Connect(options.Client().ApplyURI(cfg.MongoURI))
if err != nil {
logger.Fatal("mongo", zap.Error(err))
}
defer client.Disconnect(ctx)

db := client.Database("my-api")

postRepo := post.NewRepository(db)
postService := post.NewService(postRepo)
postHandler := post.NewHandler(postService)
post.RegisterRoutes(v1, postHandler, middleware.Auth())