friendlymongo

package module
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: May 23, 2024 License: MIT Imports: 9 Imported by: 0

README

friendlymongo

MongoDB and Golang made easy (maybe).

Go Report Card

GitHub Release

Installation

go get -u github.com/pmatteo/friendlymongo

Note that friendlymongo is tested on Go 1.18 and 1.22 using different vversion of MongoDB.

Usage

You can find a simple exmaple here.

Client

friendlymongo has a simple way to handle mongo.Client instance as a singelton. You can set the instance using setInstance(url) method and then get it everywhere with GetInstance(). It uses a wrapper class called MongoClient, to access the client instance use GetInstance().Client() or to get a new mongo.Database instance use GetInstance().Database(dbName).

i := friendlymongo.SetInstance("mongodb://username:password@localhost:27017")
c := i.Client()
db := i.Database("user")

or

friendlymongo.SetInstance("mongodb://username:password@localhost:27017")
c := friendlymongo.GetInstance().Client()
db := friendlymongo.GetInstance().Database("user")
Model

Model is an interface that defines a series of method that every struct must implemets to being able to be used by the repository implmenetation.

type Model interface {
    OnCreate()
    OnUpdate()
    OnReplace()
}

The library also comes with a simple BaseModel whcih already handels ObjectID, created and updated timestamp that can be used.

type UserProfile struct {
    *friendlymongo.BaseModel
    // Other fields 
    Name      string
    Surname   string
    Email     string
    BirthDate time.Time
}
Repository

The main goal of the package is allow basic Mongo functionalities access without tons of boilarplate code.

The implementation of the repository pattern using go generics is a way to have some operations mapped and accessible without any effort other than define the data structure you have to deal with.

// retrieve a BaseRepository instance fot the userProfile type
repo := friendlymongo.NewBaseRepository(db, "userProfile", &userProfile{})

...

user := NewUserProfile("John","Doe","john.doe@test.com",birthday)
// Insert the user into the database
err := repo.InsertOne(context.Background(), user)
if err != nil {
    panic(err)
}
Pipeline Stage Builder

BaseRepository offers an Aggregate method for Mongo's aggregation pipelines feature. It requires an instance of mongo.Pipeline as argument.

For some basic (or even not) pipeline, friendlymongo implements a simple stage builder that ìwould help developers create their stages in a more structured way and readable way.

pipeline := friendlymongo.
    NewStageBuilder().
    Match("name_filter", bson.M{"name": "John"}).
    Lookup("roles_lookup", "user_role","_id","fk","role").
    Match("filter_admin", bson.M{"role.name": "admin"}).
    Build()

At the moment the stage builder already implements a method for a subset of possible stages, other can be added using the AddStage method.

Operators

friendlymongo offers a semplification for some mongo operators like $push or $map. More will be added in the future.

fm.NewStageBuilder().
    Lookup("product_lookup", "product", "products", "ean", "products").
    Unwind("unwind_products", "$products").
    Group("category_id_group", bson.M{
        "_id": bson.M{
            "orderId":  "$_id",
            "category": "$products.category",
        },
        "status":   fm.First("$status"),
        "products": fm.Push("$products"),
    }).
    Group("productsByCategory", bson.M{
        "_id":                "$_id.orderId",
        "status":             fm.First("$status"),
        "productsByCategory": fm.Push("category", "$_id.category", "products", "$products"),
    }).
    Project("final_project", bson.M{
        "_id":    1,
        "status": 1,
        "grouped_products": fm.ArrayToObject(
            fm.Map("$productsByCategory", "cat", "$$cat.category", "$$cat.products"),
        ),
    })

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddToSet added in v0.3.0

func AddToSet(exp map[string]interface{}) bson.M

func ArrayToObject added in v0.3.0

func ArrayToObject(exp interface{}) bson.M

func Each added in v0.3.0

func Each(values interface{}) bson.M

func First added in v0.3.0

func First(exp interface{}) bson.M

func IncludeIndex added in v0.2.0

func IncludeIndex(index string) unwindOptsFunc

func Map added in v0.3.0

func Map(input, as, k, v string) bson.M

func PreserveNullEmpty added in v0.2.0

func PreserveNullEmpty(preserve bool) unwindOptsFunc

func Push added in v0.3.0

func Push(exp ...interface{}) bson.M

Types

type BaseModel

type BaseModel struct {
	// ID must have bson tag `omitempty` to allow the document to either have a database generated ID or
	// a custom one, and being elegible for `ReplaceOne`. See method `ReplaceOne` in `BaseRepository` for more info.
	ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`

	CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
}

func NewBaseModel

func NewBaseModel() *BaseModel

func (*BaseModel) OnCreate

func (b *BaseModel) OnCreate()

func (*BaseModel) OnReplace

func (b *BaseModel) OnReplace()

func (*BaseModel) OnUpdate

func (b *BaseModel) OnUpdate()

type BaseRepository

type BaseRepository[T Model] struct {
	// contains filtered or unexported fields
}

BaseRepository is a base implementation of the MongoRepository interface.

func NewBaseRepository

func NewBaseRepository[T Model](db *mongo.Database, collectionName string, t T) *BaseRepository[T]

NewBaseRepository creates a new instance of BaseRepository.

func (*BaseRepository[T]) Aggregate

func (r *BaseRepository[T]) Aggregate(ctx context.Context, pipeline mongo.Pipeline, result interface{}) error

Aggregate runs an aggregation framework pipeline on the collection.

func (*BaseRepository[T]) Delete

func (r *BaseRepository[T]) Delete(ctx context.Context, filter interface{}) (int64, error)

Delete deletes multiple documents from the collection.

func (*BaseRepository[T]) Find

func (r *BaseRepository[T]) Find(ctx context.Context, filter interface{}) ([]T, error)

Find finds multiple documents in the collection.

func (*BaseRepository[T]) FindOne

func (r *BaseRepository[T]) FindOne(ctx context.Context, filter interface{}) (T, error)

FindOne finds a single document in the collection.

func (*BaseRepository[T]) InsertMany

func (r *BaseRepository[T]) InsertMany(ctx context.Context, documents []T) error

InsertMany inserts multiple documents into the collection.

func (*BaseRepository[T]) InsertOne

func (r *BaseRepository[T]) InsertOne(ctx context.Context, document T) error

InsertOne inserts a single document into the collection.

The document parameter must be a pointer to a struct that implements the Model interface.

func (*BaseRepository[Model]) ReplaceOne

func (r *BaseRepository[Model]) ReplaceOne(ctx context.Context, filter interface{}, replacement Model) error

ReplaceOne replaces a single document in the collection. Replaced document must have the same ID as the one being replaced or not have it serializible at all. It is strongly suggested to have the ID field with the `omitempty` bson tag in case of structs.

func (*BaseRepository[T]) UpdateOne

func (r *BaseRepository[T]) UpdateOne(ctx context.Context, filters interface{}, update interface{}) (T, error)

UpdateOne finds a single document and updates it. The update parameter must be a bson.M or a struct that implements the Model interface.

type Model

type Model interface {
	OnCreate()
	OnUpdate()
	OnReplace()
}

type MongoClient

type MongoClient struct {
	// contains filtered or unexported fields
}

MongoClient is a struct to manage the database connection

func GetInstance

func GetInstance() *MongoClient

GetInstance returns the singleton instance of DatabaseConnection

func SetInstance

func SetInstance(uri string) *MongoClient

SetInstance initializes a new database connection

func (*MongoClient) Client

func (c *MongoClient) Client() *mongo.Client

func (*MongoClient) Connect

func (c *MongoClient) Connect() error

Connect opens a connection to the database

func (*MongoClient) Database

func (c *MongoClient) Database(name string) *mongo.Database

func (*MongoClient) Disconnect

func (c *MongoClient) Disconnect() error

type MongoRepository

type MongoRepository[T Model] interface {
	// InsertOne inserts a single document into the collection.
	InsertOne(ctx context.Context, document Model) error

	// InsertMany inserts multiple documents into the collection.
	InsertMany(ctx context.Context, documents []Model) error

	// FindOne finds a single document in the collection.
	FindOne(ctx context.Context, filter interface{}) (Model, error)

	// Find finds multiple documents in the collection.
	Find(ctx context.Context, filter interface{}) ([]Model, error)

	// UpdateOne finds a single document and updates it.
	UpdateOne(ctx context.Context, filters interface{}, update interface{}) (Model, error)

	// Delete deletes multiple documents from the collection.
	Delete(ctx context.Context, filter interface{}) (int64, error)

	// ReplaceOne replaces a single document in the collection.
	ReplaceOne(ctx context.Context, filter interface{}, replacement T) error

	// Aggregate runs an aggregation framework pipeline on the collection.
	Aggregate(ctx context.Context, pipeline mongo.Pipeline, result interface{}) error
}

MongoRepository is an interface that defines the methods for interacting with a MongoDB collection.

type StageBuilder

type StageBuilder struct {
	// contains filtered or unexported fields
}

func NewStageBuilder

func NewStageBuilder() *StageBuilder

func (*StageBuilder) AddStage

func (pb *StageBuilder) AddStage(id string, stageType string, filters interface{}) *StageBuilder

func (*StageBuilder) Append

func (pb *StageBuilder) Append(id string, filters interface{}) *StageBuilder

func (*StageBuilder) Bucket added in v0.2.0

func (pb *StageBuilder) Bucket(id string, groupBy string, boundaries []any, def any, output bson.M) *StageBuilder

Bucket categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries and outputs a document per each bucket. Each output document contains an _id field whose value specifies the inclusive lower bound of the bucket. The output option specifies the fields included in each output document.

$bucket only produces output documents for buckets that contain at least one input document.

func (*StageBuilder) Build

func (pb *StageBuilder) Build() mongo.Pipeline

func (*StageBuilder) Count

func (pb *StageBuilder) Count(id string, filter string) *StageBuilder

func (*StageBuilder) Facet added in v0.2.0

func (pb *StageBuilder) Facet(id string, aggregations map[string]*StageBuilder) *StageBuilder

func (*StageBuilder) Group

func (pb *StageBuilder) Group(id string, filters interface{}) *StageBuilder

func (*StageBuilder) Limit

func (pb *StageBuilder) Limit(id string, filters interface{}) *StageBuilder

func (*StageBuilder) Lookup

func (pb *StageBuilder) Lookup(id, from, localField, foreignField, as string) *StageBuilder

func (*StageBuilder) Match

func (pb *StageBuilder) Match(id string, filters interface{}) *StageBuilder

func (*StageBuilder) Project

func (pb *StageBuilder) Project(id string, filters interface{}) *StageBuilder

func (*StageBuilder) Skip

func (pb *StageBuilder) Skip(id string, filters interface{}) *StageBuilder

func (*StageBuilder) Sort

func (pb *StageBuilder) Sort(id string, filters interface{}) *StageBuilder

func (*StageBuilder) SortByCount added in v0.2.0

func (pb *StageBuilder) SortByCount(id string, expr interface{}) *StageBuilder

func (*StageBuilder) Stages

func (pb *StageBuilder) Stages() []*stage

func (*StageBuilder) Unwind added in v0.2.0

func (pb *StageBuilder) Unwind(id, fieldPath string, opts ...unwindOptsFunc) *StageBuilder

Jump to

Keyboard shortcuts

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