mgorepo

package module
v0.7.3 Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2024 License: MIT Imports: 13 Imported by: 0

README

mgorepo

An extensible and generic mongo repository pattern implementation

Requirements

  • Golang >= 1.20
  • Docker (for testing only)

CLI

Pending to add

Installation

go get github.com/Drafteame/mgorepo

Usage

This package was made with the purpose of having a way to generify mongo actions using the repository pattern on a DDD environment. It's not an ORM, it's just a way to have a generic way to interact with mongo.

Main concepts
Repository

A repository is a struct that will be used to interact with the database, it should be created using the NewRepository generic function and can be configured to be extended with custom methods using struct embedding.

The sign of the NewRepository function is:

func NewRepository[
	M    Model,
	D    Dao,
	SF   SearchFilters,
	UF   UpdateFields,
](
	db             Driver,
	collectionName string,
	filterBuilders []func(SF) (*bson.E, error),
	updateBuilders []func(UF) (*bson.E, error),
) Repository[M, D, SF, SORD, SO, UF] {}
Generic constraints
  • M Model: Is a struct that will be used to interact with the repository, it should be created using just native go types and should contain all document fields of a collection. Fields should be public.
  • D Dao: Is a struct that will be used to interact with the database, it should be created using mongo data types, should contain all document fields of a collection and be compliant with the generic interface DaoFiller[M Model]. Fields should be public. ID field of a Dao should be defined as primitive.ObjectID or *primitive.ObjectID using tag bson:"_id,omitempty".
  • SF SearchFilters: Is a struct that will be used to filter the results of a search, it should be created using just pointers of native go types and each field should represent a type of filter that can be applied to the collection. Fields should be public.
  • UF UpdateFields: Is a struct that will be used to update a document, it should be created using just native go types and each field should represent a possible updated fields of a document. Fields should be public.
Parameters
  • db Driver: Is an interface that implements 2 methods:
    • Client() *mongo.Client: Should return a mongo client that will be used to interact with the database (package used to interact with mongo is go.mongodb.org/mongo-driver/mongo).
    • DbName() string: Should return a string with the name of the database that will be used on the operations.
  • collectionName string: Is a string with the name of the collection that will be used by the repository.
  • filterBuilders []func(SF) (*bson.E, error): Is a slice of functions that will be used to build the filters that will be applied to the search. Each function should receive a SF struct and return a *bson.E with the filter that will be applied to the search. If an error is returned, the operation will be aborted. Each function should build a filter based in just one field of the SF struct, making as result that the slice of functions should have the same length as the number of fields of the SF struct.
  • updateBuilders []func(UF) (*bson.E, error): Is a slice of functions that will be used to build the updates that will be applied to the document. Each function should receive a UF struct and return a *bson.E with the update that will be applied to the document. If an error is returned, the operation will be aborted. Each function should build an update based in just one field of the UF struct, making as result that the slice of functions should have the same length as the number of fields of the UF struct.

Documentation

Index

Constants

View Source
const (
	DefaultCreatedAtField = "createdAt"
	DefaultUpdatedAtField = "updatedAt"
	DefaultDeletedAtField = "deletedAt"
	DefaultSearchLimit    = 10
	MaxSearchLimit        = 5000
)
View Source
const (
	FieldAdd    = 1
	FieldRemove = 0
)
View Source
const (
	OrderAsc  = 1
	OrderDesc = -1
)

Variables

View Source
var (
	ErrNotFound         = errors.New("mongo-repository: model not found")
	ErrInvalidIDFilter  = errors.New("mongo-repository: invalid id filter")
	ErrEmptyFilters     = errors.New("mongo-repository: empty filters")
	ErrCreatingDAO      = errors.New("mongo-repository: error creating dao")
	ErrCreatingModel    = errors.New("mongo-repository: error creating model")
	ErrEmptyUpdate      = errors.New("mongo-repository: empty update")
	ErrInvalidDaoFiller = errors.New("mongo-repository: invalid dao does not implement DaoFiller")
)

Functions

This section is empty.

Types

type Clock

type Clock interface {
	Now() time.Time
}

type Dao

type Dao any

type DaoFiller

type DaoFiller[M Model] interface {
	FromModel(M) error
	ToModel() M
}

type Driver

type Driver interface {
	Client() *mongo.Client
	DbName() string
}

type Logger

type Logger interface {
	Debugf(action, message string, args ...any)
	Errorf(err error, action, message string, args ...any)
}

type Model

type Model any

type Repository

type Repository[M Model, D Dao, SF SearchFilters, SORD SearchOrderer, SO SearchOptioner[SF, SORD], UF UpdateFields] struct {
	// contains filtered or unexported fields
}

func NewRepository

func NewRepository[
	M Model,
	D Dao,
	SF SearchFilters,
	SORD SearchOrderer,
	SO SearchOptioner[SF, SORD],
	UF UpdateFields,
](
	db Driver,
	collectionName string,
	filterBuilders []func(SF) (*bson.E, error),
	updateBuilders []func(UF) (*bson.E, error),
) Repository[M, D, SF, SORD, SO, UF]

func (Repository[M, D, SF, SORD, SO, UF]) BuildSearchFilters

func (r Repository[M, D, SF, SORD, SO, UF]) BuildSearchFilters(opts SF) (bson.D, error)

BuildSearchFilters builds filters from a SearchFilters struct. It will return bson.D with the filters, or an error if one occurs. If no filters are given, it will return nil. If the deletedAtField is not explicitly set, it will filter out deleted instances if withTimestamps is set to true.

func (Repository[M, D, SF, SORD, SO, UF]) BuildSearchOptions

func (r Repository[M, D, SF, SORD, SO, UF]) BuildSearchOptions(opts SO) (bson.D, *options.FindOptions, error)

BuildSearchOptions builds filters, and mongo.FindOptions from a SearchOptions struct. If no limit is given, it will default to the repository's search limit. If no orders are given, it will default to ascending order by id.

func (Repository[M, D, SF, SORD, SO, UF]) BuildSearchOrders

func (r Repository[M, D, SF, SORD, SO, UF]) BuildSearchOrders(so SearchOrderer) (bson.D, error)

func (Repository[M, D, SF, SORD, SO, UF]) BuildUpdateFields

func (r Repository[M, D, SF, SORD, SO, UF]) BuildUpdateFields(fields UF) (bson.D, error)

BuildUpdateFields builds the update fields from the given options and returns a bson.D that can be used to update the document. If repository is configured with timestamps, it will automatically add the updatedAtField to the update fields.

func (Repository[M, D, SF, SORD, SO, UF]) Clock

func (r Repository[M, D, SF, SORD, SO, UF]) Clock() Clock

func (Repository[M, D, SF, SORD, SO, UF]) Collection

func (r Repository[M, D, SF, SORD, SO, UF]) Collection() *mongo.Collection

func (Repository[M, D, SF, SORD, SO, UF]) CollectionName

func (r Repository[M, D, SF, SORD, SO, UF]) CollectionName() string

func (Repository[M, D, SF, SORD, SO, UF]) Count

func (r Repository[M, D, SF, SORD, SO, UF]) Count(ctx context.Context, opts SF) (int64, error)

Count returns the number of documents in the collection that match the given search options.

func (Repository[M, D, SF, SORD, SO, UF]) Create

func (r Repository[M, D, SF, SORD, SO, UF]) Create(ctx context.Context, model M) (M, error)

Create creates a new record on the collection based on the model.

func (Repository[M, D, SF, SORD, SO, UF]) Db

func (r Repository[M, D, SF, SORD, SO, UF]) Db() Driver

func (Repository[M, D, SF, SORD, SO, UF]) Delete

func (r Repository[M, D, SF, SORD, SO, UF]) Delete(ctx context.Context, id string) (int64, error)

Delete deletes a document by id. If the repository is configured to not use timestamps, this operation will be applied as a hard delete.

func (Repository[M, D, SF, SORD, SO, UF]) DeleteMany

func (r Repository[M, D, SF, SORD, SO, UF]) DeleteMany(ctx context.Context, filters SF) (int64, error)

DeleteMany deletes many documents from the collection. It returns the number of deleted documents and an error. If the repository has timestamps enabled, it will soft delete the documents. Otherwise, it will hard delete them.

func (Repository[M, D, SF, SORD, SO, UF]) Get

func (r Repository[M, D, SF, SORD, SO, UF]) Get(ctx context.Context, id string) (M, error)

func (Repository[M, D, SF, SORD, SO, UF]) HardDelete

func (r Repository[M, D, SF, SORD, SO, UF]) HardDelete(ctx context.Context, id string) (int64, error)

func (Repository[M, D, SF, SORD, SO, UF]) HardDeleteMany

func (r Repository[M, D, SF, SORD, SO, UF]) HardDeleteMany(ctx context.Context, filters SF) (int64, error)

func (Repository[M, D, SF, SORD, SO, UF]) IsSearchFiltersEmpty

func (r Repository[M, D, SF, SORD, SO, UF]) IsSearchFiltersEmpty(opts SF) bool

func (Repository[M, D, SF, SORD, SO, UF]) IsSearchOptionsEmpty

func (r Repository[M, D, SF, SORD, SO, UF]) IsSearchOptionsEmpty(opt SO) bool

func (Repository[M, D, SF, SORD, SO, UF]) IsSortOptionsEmpty

func (r Repository[M, D, SF, SORD, SO, UF]) IsSortOptionsEmpty(opts SearchOrders) bool

func (Repository[M, D, SF, SORD, SO, UF]) IsUpdateFieldsEmpty

func (r Repository[M, D, SF, SORD, SO, UF]) IsUpdateFieldsEmpty(fields UF) bool

func (Repository[M, D, SF, SORD, SO, UF]) Logger

func (r Repository[M, D, SF, SORD, SO, UF]) Logger() Logger

func (Repository[M, D, SF, SORD, SO, UF]) Now

func (r Repository[M, D, SF, SORD, SO, UF]) Now() primitive.DateTime

func (Repository[M, D, SF, SORD, SO, UF]) Search

func (r Repository[M, D, SF, SORD, SO, UF]) Search(ctx context.Context, opts SO) ([]M, error)

func (Repository[M, D, SF, SORD, SO, UF]) SetClock

func (r Repository[M, D, SF, SORD, SO, UF]) SetClock(clock Clock) Repository[M, D, SF, SORD, SO, UF]

func (Repository[M, D, SF, SORD, SO, UF]) SetCreatedAtField

func (r Repository[M, D, SF, SORD, SO, UF]) SetCreatedAtField(createdAtField string) Repository[M, D, SF, SORD, SO, UF]

func (Repository[M, D, SF, SORD, SO, UF]) SetDefaultSearchLimit

func (r Repository[M, D, SF, SORD, SO, UF]) SetDefaultSearchLimit(searchLimit int) Repository[M, D, SF, SORD, SO, UF]

func (Repository[M, D, SF, SORD, SO, UF]) SetDeletedAtField

func (r Repository[M, D, SF, SORD, SO, UF]) SetDeletedAtField(deletedAtField string) Repository[M, D, SF, SORD, SO, UF]

func (Repository[M, D, SF, SORD, SO, UF]) SetLogLevel

func (r Repository[M, D, SF, SORD, SO, UF]) SetLogLevel(logLevel string) Repository[M, D, SF, SORD, SO, UF]

func (Repository[M, D, SF, SORD, SO, UF]) SetLogger

func (r Repository[M, D, SF, SORD, SO, UF]) SetLogger(log Logger) Repository[M, D, SF, SORD, SO, UF]

func (Repository[M, D, SF, SORD, SO, UF]) SetUpdatedAtField

func (r Repository[M, D, SF, SORD, SO, UF]) SetUpdatedAtField(updatedAtField string) Repository[M, D, SF, SORD, SO, UF]

func (Repository[M, D, SF, SORD, SO, UF]) Update

func (r Repository[M, D, SF, SORD, SO, UF]) Update(ctx context.Context, id string, fields UF) (int64, error)

func (Repository[M, D, SF, SORD, SO, UF]) UpdateMany

func (r Repository[M, D, SF, SORD, SO, UF]) UpdateMany(ctx context.Context, opts SF, data UF) (int64, error)

func (Repository[M, D, SF, SORD, SO, UF]) WithTimestamps

func (r Repository[M, D, SF, SORD, SO, UF]) WithTimestamps(withTimestamps bool) Repository[M, D, SF, SORD, SO, UF]

type SearchFilters

type SearchFilters any

type SearchOptioner added in v0.4.0

type SearchOptioner[SF SearchFilters, O SearchOrderer] interface {
	Filters() SF
	Orders() O
	Limit() int64
	Skip() int64
	Projection() map[string]int
}

type SearchOptions

type SearchOptions[SF SearchFilters, SO SearchOrderer] struct {
	// contains filtered or unexported fields
}

func NewSearchOptions

func NewSearchOptions[SF SearchFilters, SO SearchOrderer](filters SF, orders SO) SearchOptions[SF, SO]

func (SearchOptions[SF, SO]) Filters

func (so SearchOptions[SF, SO]) Filters() SF

func (SearchOptions[SF, SO]) Limit

func (so SearchOptions[SF, SO]) Limit() int64

func (SearchOptions[SF, SO]) Orders

func (so SearchOptions[SF, SO]) Orders() SO

func (SearchOptions[SF, SO]) Projection

func (so SearchOptions[SF, SO]) Projection() map[string]int

func (SearchOptions[SF, SO]) Skip

func (so SearchOptions[SF, SO]) Skip() int64

func (SearchOptions[SF, SO]) WithLimit

func (so SearchOptions[SF, SO]) WithLimit(limit int64) SearchOptions[SF, SO]

func (SearchOptions[SF, SO]) WithProject added in v0.4.1

func (so SearchOptions[SF, SO]) WithProject(field string, project int) SearchOptions[SF, SO]

func (SearchOptions[SF, SO]) WithProjectFields added in v0.4.1

func (so SearchOptions[SF, SO]) WithProjectFields(project map[string]int) SearchOptions[SF, SO]

func (SearchOptions[SF, SO]) WithSkip

func (so SearchOptions[SF, SO]) WithSkip(skip int64) SearchOptions[SF, SO]

type SearchOrderer added in v0.4.0

type SearchOrderer interface {
	ToMap() map[string]int
}

type SearchOrders

type SearchOrders []orderField

func NewSearchOrders

func NewSearchOrders() SearchOrders

func (SearchOrders) Add

func (so SearchOrders) Add(name string, order int) SearchOrders

func (SearchOrders) ToMap added in v0.4.0

func (so SearchOrders) ToMap() map[string]int

type UpdateFields

type UpdateFields any

Directories

Path Synopsis
example
internal
env

Jump to

Keyboard shortcuts

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