mongo

package
v0.7.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 19, 2026 License: MIT Imports: 16 Imported by: 0

README

MongoDB Data Source Library

A robust MongoDB client library wrapper based on the official mongo-driver, integrated with zap logging and providing a generic base repository pattern.

Features

  • Connection Management: Simplified connection setup with timeouts and health checks (Ping).
  • Integrated Logging: Automatic logging of connection status and operations using go.uber.org/zap.
  • Generic Repository: BaseRepository[T] implementation for standard CRUD operations.
  • Soft Delete: Built-in support for soft deletes via is_deleted field.
  • Custom Queries: Flexible support for custom BSON filters.

Dependencies

Installation

go get github.com/mbu-id/engine/ds/mongo

Quick Start

1. Configuration & Initialization

You can configure the connection manually or use the default environment variable loader.

Using Environment Variables:

# .env
MONGODB_SERVER=localhost:27017
MONGODB_AUTH_USERNAME=admin
MONGODB_AUTH_PASSWORD=password
package main

import (
    "os"
    "github.com/mbu-id/engine/ds/mongo"
    "go.uber.org/zap"
)

func main() {
    logger, _ := zap.NewProduction()

    // Load config from env
    cfg := mongo.ConfigDefault("my_database")

    // Connect
    if err := mongo.NewConnection(cfg, logger); err != nil {
        logger.Fatal("Failed to connect to MongoDB", zap.Error(err))
    }
    defer mongo.CloseConnection()

    // Application logic...
}

Manual Configuration:

cfg := &mongo.Config{
    Server:   "localhost:27017",
    Username: "user",
    Password: "password",
    Database: "mydb",
    // Optional: Full connection string overrides other fields
    // Datasource: "mongodb://user:pass@localhost:27017/mydb",
}

Base Repository

The BaseRepository[T] provides a standard, reusable interface for interacting with MongoDB collections. It leverages Go generics to provide type-safe CRUD operations.

Initialization
// NewBaseRepository creates a generic repository for a specific type T.
//
// col: The collection wrapper
// searchFields: List of fields to apply search filters on (for FindAll)
// enableSoftDelete: If true, filters out documents with is_deleted=true
repo := mongo.NewBaseRepository[User](col, []string{"name", "email"}, true)
Core Concepts
Context Chaining (WithContext)

The repository is designed to be immutable regarding the context. To perform an operation with a specific context.Context, use WithContext. This follows the pattern:

repo.WithContext(ctx).FindByID("...")
Custom Queries (CustomQueryFn)

For complex filtering, the repository uses a functional pattern CustomQueryFn which lets you modify the BSON filter directly.

type CustomQueryFn func(filter bson.M) bson.M
Methods Reference
FindByID(id any) (*T, error)

Finds a single document by its _id.

  • Checks is_deleted if soft delete is enabled.
  • Automatically converts string IDs to primitive.ObjectID.
user, err := repo.WithContext(ctx).FindByID("64f8a5c2e1b2c3d4e5f6g7h8")
Insert(entity *T) error

Inserts a new document.

  • Returns error if insert fails.
err := repo.WithContext(ctx).Insert(&User{Name: "John"})
Update(entity *T, fields ...string) error

Updates specific fields of an entity.

  • Uses reflection to map struct fields to BSON tags.
  • Only updates the fields specified in the fields argument.
// Update only name and email
err := repo.WithContext(ctx).Update(user, "name", "email")
SoftDelete(id any) error

Marks a document as deleted by setting is_deleted: true.

  • Requires enableSoftDelete to be set to true during initialization.
err := repo.WithContext(ctx).SoftDelete(userID)
FindOne(query CustomQueryFn) (*T, error)

Finds a single document matching criteria.

user, err := repo.WithContext(ctx).FindOne(func(f bson.M) bson.M {
    f["email"] = "john@example.com"
    f["status"] = "active"
    return f
})
FindAll(opts *common.QueryOption, query CustomQueryFn) ([]*T, int64, error)

Retrieves a list of documents with pagination, sorting, and filtering.

  • opts: Contains Limit, Offset, Orders (sort), and Search.
  • query: Optional extra filters.
import "github.com/mbu-id/engine/common"

opts := &common.QueryOption{
    Limit: 20,
    Offset: 0,
    Orders: []string{"-created_at"}, // Descending by created_at
}

users, total, err := repo.WithContext(ctx).FindAll(opts, func(f bson.M) bson.M {
    f["role"] = "admin"
    return f
})
Custom Repository Pattern

For complex logic, extend the base repository:

type UserRepository struct {
    *mongo.BaseRepository[User]
}

func NewUserRepository() *UserRepository {
    return &UserRepository{
        BaseRepository: mongo.NewBaseRepository[User](
            mongo.NewCollection("users"),
            []string{"name", "email"},
            true,
        ),
    }
}

func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*User, error) {
    return r.WithContext(ctx).FindOne(func(f bson.M) bson.M {
        f["email"] = email
        return f
    })
}

Documentation

Index

Constants

View Source
const ID = "_id"

ID is the default MongoDB document ID field name.

Variables

This section is empty.

Functions

func CloseConnection

func CloseConnection() error

func FilterSearch

func FilterSearch(search string, fields ...string) primitive.M

FilterSearch builds a case-insensitive `$or` regex filter for the specified fields.

Example:

FilterSearch("john", "name", "email")
=>
{
  "$or": [
    {"name": {"$regex": "john", "$options": "i"}},
    {"email": {"$regex": "john", "$options": "i"}}
  ]
}

func NewConnection

func NewConnection(c *Config, l *zap.Logger) error

NewConnection sets up the MongoDB client and database.

func RequestSort

func RequestSort(sort []string) primitive.D

RequestSort converts a list of sort keys into a MongoDB sort document.

Prefixing a field with "-" sorts descending. Use "__" to represent nested fields. The special case "id" will be converted to "_id".

Example:

RequestSort([]string{"-created_at", "user__name"})
=>
bson.D{
  {"created_at", -1},
  {"user.name", 1},
}

func StructFilter

func StructFilter(m any, fields ...string) primitive.M

StructFilter returns a BSON map of specific fields from a struct. If no fields are specified, it returns all fields.

Types

type BaseRepository

type BaseRepository[T any] struct {
	Collection *Collection
	Context    context.Context
	// contains filtered or unexported fields
}

func NewBaseRepository

func NewBaseRepository[T any](col *Collection, searchFields []string, enableSoftDelete bool) *BaseRepository[T]

func (*BaseRepository[T]) FindAll

func (r *BaseRepository[T]) FindAll(opts *common.QueryOption, query CustomQueryFn) ([]*T, int64, error)

func (*BaseRepository[T]) FindByID

func (r *BaseRepository[T]) FindByID(id any) (*T, error)

func (*BaseRepository[T]) FindOne

func (r *BaseRepository[T]) FindOne(customQuery CustomQueryFn) (*T, error)

func (*BaseRepository[T]) Insert

func (r *BaseRepository[T]) Insert(entity *T) error

func (*BaseRepository[T]) SoftDelete

func (r *BaseRepository[T]) SoftDelete(id any) error

func (*BaseRepository[T]) Update

func (r *BaseRepository[T]) Update(entity *T, fields ...string) error

func (*BaseRepository[T]) WithContext

func (r *BaseRepository[T]) WithContext(ctx context.Context) common.BaseRepositoryInterface[T]

type Collection

type Collection struct {
	*mongo.Collection
	// contains filtered or unexported fields
}

Collection wraps a MongoDB collection with a default context for convenience.

func NewCollection

func NewCollection(name string, opts ...*options.CollectionOptions) *Collection

NewCollection creates and returns a new Collection from the default DB with the given name and options. The returned Collection uses the global default context, but you can override it with WithContext.

func (*Collection) Count

func (c *Collection) Count(filter any) (int64, error)

Count returns the number of documents matching the given filter. Returns the count and any error encountered.

func (*Collection) Create

func (c *Collection) Create(model Model, opts ...*options.InsertOneOptions) error

Create inserts the given model into the collection. Optionally accepts InsertOneOptions. On success, sets the inserted ID back to the model. Returns error if insertion fails.

func (*Collection) Delete

func (c *Collection) Delete(model Model) error

Delete removes a document matching the model's ID from the collection. Returns error if deletion fails.

func (*Collection) Finds

func (c *Collection) Finds(results any, filter any, opts ...*options.FindOptions) error

Finds executes a find query with the given filter and options, and decodes all results into 'results' (must be a pointer to a slice). Returns error if the find or decoding fails.

func (*Collection) GetOne

func (c *Collection) GetOne(filter any, model Model, opts ...*options.FindOneOptions) error

GetOne finds a single document matching the given filter and decodes it into the model. Returns error if not found.

func (*Collection) Show

func (c *Collection) Show(id any, model Model, opts ...*options.FindOneOptions) error

Show finds a document by its ID (string or ObjectID) and decodes it into 'model'. Optional FindOneOptions can be passed. Returns an error if the document is not found or the ID is invalid.

func (*Collection) Update

func (c *Collection) Update(model Model, fields ...string) error

Update updates only the specified fields of the given model document by ID. Returns error if the update fails.

func (*Collection) WithContext

func (c *Collection) WithContext(ctx context.Context) *Collection

WithContext sets a new context for the Collection and returns itself for chaining.

type Config

type Config struct {
	Server     string
	Username   string
	Password   string
	Database   string
	Datasource string
	CtxTimeout time.Duration
}

func ConfigDefault

func ConfigDefault(db string) *Config

type CustomQueryFn

type CustomQueryFn func(filter bson.M) bson.M

type Model

type Model any

Model is an alias for any struct representing a MongoDB document.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL