Documentation ¶
Overview ¶
Package mongodb wraps the go mongodb driver by providing a so-called "Connector", this makes the mongodb connection testable/mockable. The original driver is not really testable, it is hard/impossible to mock the package. Usually in go the interfaces are defined at the consumer side, but in this case an interface is provided to keep the codebase small.
The provided connector interface can easily be mocked using mockery.
Additionaly this package provides some datatypes, like UUID, ObjectId, NullString, nullable numbers and a datatype for storing binary data.
Example ¶
Example demonstrates the process of creating, reading, updating, and deleting a user in a MongoDB database.
package main import ( "errors" "github.com/mbretter/go-mongodb" "github.com/mbretter/go-mongodb/types" "github.com/stretchr/testify/assert" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "log" "os" "testing" ) // User represents a user entity with an ID, username, and personal details such as firstname and lastname. type User struct { Id types.ObjectId `bson:"_id"` Username string `bson:"username,omitempty"` Firstname string `bson:"firstname,omitempty"` Lastname string `bson:"lastname,omitempty"` } // UserDbInterface defines the methods required to interact with the User entity in the database. // Insert adds a new User to the database and returns an error if the operation fails. // Update modifies an existing User in the database and returns an UpdateResult and an error if the operation fails. // Read retrieves a User by their ObjectId and returns the User and an error if the operation fails. // Delete removes a User by their ObjectId and returns a DeleteResult and an error if the operation fails. type UserDbInterface interface { Insert(*User) error Update(user *User) (*mongo.UpdateResult, error) Read(id types.ObjectId) (*User, error) Delete(id types.ObjectId) (*mongo.DeleteResult, error) } // UserModel provides methods for managing user data by integrating with the UserDbInterface. type UserModel struct { db UserDbInterface } // ProvideModel initializes a User instance with the provided UserDbInterface. func ProvideModel(db UserDbInterface) UserModel { return UserModel{db: db} } func (m UserModel) Create(user User) (User, error) { user.Id = types.NewObjectId() err := m.db.Insert(&user) if err != nil { return user, err } return user, nil } func (m UserModel) ReadById(id types.ObjectId) (*User, error) { return m.db.Read(id) } func (m UserModel) Update(user User) error { _, err := m.db.Update(&user) return err } func (m UserModel) DeleteById(id types.ObjectId) error { _, err := m.db.Delete(id) return err } // UserDb provides methods to interact with the user collection in the database using a Connector interface. type UserDb struct { conn mongodb.Connector } func (d *UserDb) Insert(user *User) error { _, err := d.conn.InsertOne(user) if err != nil { return err } return nil } func (d *UserDb) Update(user *User) (*mongo.UpdateResult, error) { res, err := d.conn.UpdateById(user.Id, bson.D{{"$set", user}}) return res, err } func (d *UserDb) Read(id types.ObjectId) (*User, error) { var ret User err := d.conn.FindOne(bson.D{{"_id", id}}).Decode(&ret) if err != nil { if errors.Is(err, mongo.ErrNoDocuments) { return nil, nil } return nil, err } return &ret, nil } func (d *UserDb) Delete(id types.ObjectId) (*mongo.DeleteResult, error) { return d.conn.DeleteOne(bson.D{{"_id", id}}) } func ProviderUserDb(conn mongodb.Connector) *UserDb { return &UserDb{ conn: conn.WithCollection("user"), } } // Example demonstrates the process of creating, reading, updating, and deleting a user in a MongoDB database. func main() { conn, err := mongodb.NewConnector(mongodb.NewParams{ Uri: os.Getenv("MONGODB_URI"), Database: os.Getenv("MONGODB_DB"), }) if err != nil { log.Fatalf("failed to connect to db: %v\n", err) } userDb := ProviderUserDb(conn) userModel := ProvideModel(userDb) user := User{ Username: "foo@bar.com", Firstname: "John", Lastname: "Doe", } user, err = userModel.Create(user) if err != nil { log.Fatalf("failed to create user: %v", err) } log.Printf("created user: %v", user) existingUser, err := userModel.ReadById(user.Id) if err != nil { log.Fatalf("failed to read user: %v", err) } if existingUser == nil { log.Fatalf("user not found") } updateUser := User{ Id: existingUser.Id, Firstname: "Jane", } err = userModel.Update(updateUser) if err != nil { log.Fatalf("failed to update user: %v", err) } err = userModel.DeleteById(user.Id) if err != nil { log.Fatalf("failed to delete user: %v", err) } } // Example_Test tests the scenario for user creation, ensuring correct insertion and data consistency. // The Connector is mocked using the auto-generated mock by mockery. // The ObjectId generator function is stubbed, to get reproducable results. func main(t *testing.T) { newUserId := "66cc9ca8c042f7a732b7fc2a" types.SetObjectIdGenerator(func() string { return newUserId }) user := User{ Id: types.ObjectId(newUserId), Username: "foo@bar.com", Firstname: "John", Lastname: "Doe", } tests := []struct { name string err error }{ { "Success", nil, }, { "Failed", errors.New("some database error occurred"), }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { conn := NewConnectorMock(t) conn.EXPECT().WithCollection("user").Return(conn) userDb := ProviderUserDb(conn) userModel := ProvideModel(userDb) res := mongo.InsertOneResult{} conn.EXPECT().InsertOne(&user).Return(&res, test.err) user, err := userModel.Create(user) if test.err == nil { assert.Nil(t, err) assert.Equal(t, user.Id, types.ObjectId(newUserId)) assert.Equal(t, user.Username, "foo@bar.com") assert.Equal(t, user.Firstname, "John") assert.Equal(t, user.Lastname, "Doe") } else { assert.NotNil(t, err) } }) } }
Output:
Index ¶
- type Connector
- type NewParams
- type StdConnector
- func (conn *StdConnector) Aggregate(pipeline interface{}, opts ...*options.AggregateOptions) (cur *mongo.Cursor, err error)
- func (conn *StdConnector) Collection(coll string, opts ...*options.CollectionOptions) *mongo.Collection
- func (conn *StdConnector) Count(filter interface{}, opts ...*options.CountOptions) (cnt int64, err error)
- func (conn *StdConnector) Database() *mongo.Database
- func (conn *StdConnector) Decode(cur *mongo.Cursor, val interface{}) error
- func (conn *StdConnector) DeleteMany(filter interface{}, opts ...*options.DeleteOptions) (res *mongo.DeleteResult, err error)
- func (conn *StdConnector) DeleteOne(filter interface{}, opts ...*options.DeleteOptions) (res *mongo.DeleteResult, err error)
- func (conn *StdConnector) Distinct(fieldName string, filter interface{}, opts ...*options.DistinctOptions) (res []interface{}, err error)
- func (conn *StdConnector) Drop() (err error)
- func (conn *StdConnector) FetchAll(cur *mongo.Cursor, results interface{}) (err error)
- func (conn *StdConnector) Find(filter interface{}, opts ...*options.FindOptions) (cur *mongo.Cursor, err error)
- func (conn *StdConnector) FindOne(filter interface{}, opts ...*options.FindOneOptions) (res *mongo.SingleResult)
- func (conn *StdConnector) FindOneAndDelete(filter interface{}, opts ...*options.FindOneAndDeleteOptions) (cur *mongo.SingleResult)
- func (conn *StdConnector) FindOneAndReplace(filter interface{}, replacement interface{}, ...) (cur *mongo.SingleResult)
- func (conn *StdConnector) FindOneAndUpdate(filter interface{}, update interface{}, ...) (cur *mongo.SingleResult)
- func (conn *StdConnector) GetNextSeq(name string, opts ...string) (seq int64, err error)
- func (conn *StdConnector) InsertMany(document []interface{}, opts ...*options.InsertManyOptions) (res *mongo.InsertManyResult, err error)
- func (conn *StdConnector) InsertOne(document interface{}, opts ...*options.InsertOneOptions) (res *mongo.InsertOneResult, err error)
- func (conn *StdConnector) NewGridfsBucket() (*gridfs.Bucket, error)
- func (conn *StdConnector) Next(cur *mongo.Cursor) bool
- func (conn *StdConnector) ReplaceOne(filter interface{}, update interface{}, opts ...*options.ReplaceOptions) (res *mongo.UpdateResult, err error)
- func (conn *StdConnector) UpdateById(id interface{}, update interface{}, opts ...*options.UpdateOptions) (res *mongo.UpdateResult, err error)
- func (conn *StdConnector) UpdateMany(filter interface{}, update interface{}, opts ...*options.UpdateOptions) (res *mongo.UpdateResult, err error)
- func (conn *StdConnector) UpdateOne(filter interface{}, update interface{}, opts ...*options.UpdateOptions) (res *mongo.UpdateResult, err error)
- func (conn *StdConnector) Watch(pipeline interface{}, opts ...*options.ChangeStreamOptions) (stream *mongo.ChangeStream, err error)
- func (conn *StdConnector) WithCollection(coll string, opts ...*options.CollectionOptions) Connector
- func (conn *StdConnector) WithContext(ctx context.Context) Connector
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Connector ¶
type Connector interface { Database() *mongo.Database Collection(coll string, opts ...*options.CollectionOptions) *mongo.Collection NewGridfsBucket() (*gridfs.Bucket, error) WithContext(context.Context) Connector WithCollection(coll string, opts ...*options.CollectionOptions) Connector Find(filter interface{}, opts ...*options.FindOptions) (*mongo.Cursor, error) FindOne(filter interface{}, opts ...*options.FindOneOptions) *mongo.SingleResult FetchAll(cur *mongo.Cursor, results interface{}) error Decode(cur *mongo.Cursor, val interface{}) error Next(cur *mongo.Cursor) bool Count(filter interface{}, opts ...*options.CountOptions) (cnt int64, err error) Distinct(fieldName string, filter interface{}, opts ...*options.DistinctOptions) (res []interface{}, err error) FindOneAndDelete(filter interface{}, opts ...*options.FindOneAndDeleteOptions) *mongo.SingleResult FindOneAndReplace(filter interface{}, replacement interface{}, opts ...*options.FindOneAndReplaceOptions) *mongo.SingleResult FindOneAndUpdate(filter interface{}, update interface{}, opts ...*options.FindOneAndUpdateOptions) *mongo.SingleResult UpdateOne(filter interface{}, update interface{}, opts ...*options.UpdateOptions) (res *mongo.UpdateResult, err error) UpdateMany(filter interface{}, update interface{}, opts ...*options.UpdateOptions) (res *mongo.UpdateResult, err error) UpdateById(id interface{}, update interface{}, opts ...*options.UpdateOptions) (res *mongo.UpdateResult, err error) ReplaceOne(filter interface{}, update interface{}, opts ...*options.ReplaceOptions) (res *mongo.UpdateResult, err error) InsertOne(document interface{}, opts ...*options.InsertOneOptions) (res *mongo.InsertOneResult, err error) InsertMany(document []interface{}, opts ...*options.InsertManyOptions) (res *mongo.InsertManyResult, err error) DeleteOne(filter interface{}, opts ...*options.DeleteOptions) (res *mongo.DeleteResult, err error) DeleteMany(filter interface{}, opts ...*options.DeleteOptions) (res *mongo.DeleteResult, err error) Aggregate(pipeline interface{}, opts ...*options.AggregateOptions) (cur *mongo.Cursor, err error) Drop() error Watch(pipeline interface{}, opts ...*options.ChangeStreamOptions) (stream *mongo.ChangeStream, err error) GetNextSeq(name string, opts ...string) (res int64, err error) }
Connector provides methods for database and collection operations.
type NewParams ¶
NewParams holds the parameters required to establish a new connection to a database.
type StdConnector ¶
type StdConnector struct {
// contains filtered or unexported fields
}
StdConnector handles connections and interactions with the MongoDB client, database, and collections.
func NewConnector ¶
func NewConnector(params NewParams) (*StdConnector, error)
NewConnector establishes a new connection to the mongo database using the provided parameters. It returns a StdConnector
func (*StdConnector) Aggregate ¶
func (conn *StdConnector) Aggregate(pipeline interface{}, opts ...*options.AggregateOptions) (cur *mongo.Cursor, err error)
Aggregate executes an aggregation framework pipeline on the collection. The 'pipeline' parameter specifies an array of aggregation stages. The 'opts' parameters specify optional settings for the aggregate operation. It returns a cursor that iterates over the resulting documents.
func (*StdConnector) Collection ¶
func (conn *StdConnector) Collection(coll string, opts ...*options.CollectionOptions) *mongo.Collection
Collection returns a mongo.Collection object for the specified collection name with additional options if provided.
func (*StdConnector) Count ¶
func (conn *StdConnector) Count(filter interface{}, opts ...*options.CountOptions) (cnt int64, err error)
Count returns the count of documents matching the given filter and options or an error if the collection is not set.
func (*StdConnector) Database ¶
func (conn *StdConnector) Database() *mongo.Database
Database returns the current mongo.Database instance associated with the StdConnector.
func (*StdConnector) Decode ¶
func (conn *StdConnector) Decode(cur *mongo.Cursor, val interface{}) error
Decode decodes the current document pointed to by the cursor into the provided value. Returns an error if decoding fails.
func (*StdConnector) DeleteMany ¶
func (conn *StdConnector) DeleteMany(filter interface{}, opts ...*options.DeleteOptions) (res *mongo.DeleteResult, err error)
DeleteMany deletes multiple documents from the collection that match the provided filter. Parameters: - filter: A document describing the documents to be deleted. - opts: Optional. Additional options to apply to the delete operation. Returns: - res: A DeleteResult containing the outcome of the delete operation. - err: An error if the operation fails.
func (*StdConnector) DeleteOne ¶
func (conn *StdConnector) DeleteOne(filter interface{}, opts ...*options.DeleteOptions) (res *mongo.DeleteResult, err error)
DeleteOne deletes a single document from the collection that matches the provided filter.
func (*StdConnector) Distinct ¶
func (conn *StdConnector) Distinct(fieldName string, filter interface{}, opts ...*options.DistinctOptions) (res []interface{}, err error)
Distinct retrieves distinct values for a specified field in the collection that matches the given filter and options. Returns a slice of distinct values or an error if the collection is not set or the operation fails.
func (*StdConnector) Drop ¶
func (conn *StdConnector) Drop() (err error)
Drop removes the current collection from the database and returns an error if unsuccessful.
func (*StdConnector) FetchAll ¶
func (conn *StdConnector) FetchAll(cur *mongo.Cursor, results interface{}) (err error)
FetchAll retrieves all the documents from the provided MongoDB cursor and stores them in the results interface.
func (*StdConnector) Find ¶
func (conn *StdConnector) Find(filter interface{}, opts ...*options.FindOptions) (cur *mongo.Cursor, err error)
Find executes a find query in the collection with the given filter and options. Returns a cursor to the found documents or an error if the collection is not set or if the query fails.
func (*StdConnector) FindOne ¶
func (conn *StdConnector) FindOne(filter interface{}, opts ...*options.FindOneOptions) (res *mongo.SingleResult)
FindOne retrieves a single document from the collection based on the provided filter and options. Returns a SingleResult containing the document or an error if the collection is not set.
func (*StdConnector) FindOneAndDelete ¶
func (conn *StdConnector) FindOneAndDelete(filter interface{}, opts ...*options.FindOneAndDeleteOptions) (cur *mongo.SingleResult)
FindOneAndDelete deletes a single document from the collection that matches the provided filter and returns the deleted document.
func (*StdConnector) FindOneAndReplace ¶
func (conn *StdConnector) FindOneAndReplace(filter interface{}, replacement interface{}, opts ...*options.FindOneAndReplaceOptions) (cur *mongo.SingleResult)
FindOneAndReplace replaces a single document in the collection matching the given filter with the provided replacement.
func (*StdConnector) FindOneAndUpdate ¶
func (conn *StdConnector) FindOneAndUpdate(filter interface{}, update interface{}, opts ...*options.FindOneAndUpdateOptions) (cur *mongo.SingleResult)
FindOneAndUpdate updates a single document matching the filter and returns the updated document.
func (*StdConnector) GetNextSeq ¶
func (conn *StdConnector) GetNextSeq(name string, opts ...string) (seq int64, err error)
GetNextSeq increments and retrieves the next sequence number for a given name within the specified collection.
func (*StdConnector) InsertMany ¶
func (conn *StdConnector) InsertMany(document []interface{}, opts ...*options.InsertManyOptions) (res *mongo.InsertManyResult, err error)
InsertMany inserts multiple documents into the collection. It returns an InsertManyResult containing the IDs of the inserted documents or an error if the insertion fails.
func (*StdConnector) InsertOne ¶
func (conn *StdConnector) InsertOne(document interface{}, opts ...*options.InsertOneOptions) (res *mongo.InsertOneResult, err error)
InsertOne inserts a single document into the collection. It returns the result of the insertion and any error encountered. The method takes a document to be inserted and optional insertion options.
func (*StdConnector) NewGridfsBucket ¶
func (conn *StdConnector) NewGridfsBucket() (*gridfs.Bucket, error)
NewGridfsBucket creates a new GridFS bucket for the current database.
func (*StdConnector) Next ¶
func (conn *StdConnector) Next(cur *mongo.Cursor) bool
Next progresses the given MongoDB cursor to the next document and returns true if a next document is available.
func (*StdConnector) ReplaceOne ¶
func (conn *StdConnector) ReplaceOne(filter interface{}, update interface{}, opts ...*options.ReplaceOptions) (res *mongo.UpdateResult, err error)
ReplaceOne replaces a single document in the collection that matches the specified filter with the provided update.
func (*StdConnector) UpdateById ¶
func (conn *StdConnector) UpdateById(id interface{}, update interface{}, opts ...*options.UpdateOptions) (res *mongo.UpdateResult, err error)
UpdateById updates a single document in the collection based on its ID.
func (*StdConnector) UpdateMany ¶
func (conn *StdConnector) UpdateMany(filter interface{}, update interface{}, opts ...*options.UpdateOptions) (res *mongo.UpdateResult, err error)
UpdateMany updates multiple documents in the collection based on the provided filter and update parameters. It returns a mongo.UpdateResult containing details about the operation or an error if one occurred.
func (*StdConnector) UpdateOne ¶
func (conn *StdConnector) UpdateOne(filter interface{}, update interface{}, opts ...*options.UpdateOptions) (res *mongo.UpdateResult, err error)
UpdateOne executes an update operation on a single document in the collection. Parameters are a filter to select the document, an update to apply, and optional update options. Returns the result of the update operation or an error if the operation fails.
func (*StdConnector) Watch ¶
func (conn *StdConnector) Watch(pipeline interface{}, opts ...*options.ChangeStreamOptions) (stream *mongo.ChangeStream, err error)
Watch starts a change stream against the collection of the StdConnector, based on the given pipeline and options. It returns a pointer to a mongo.ChangeStream for iterating the changes, or an error if the collection is not set.
func (*StdConnector) WithCollection ¶
func (conn *StdConnector) WithCollection(coll string, opts ...*options.CollectionOptions) Connector
WithCollection returns a copy of StdConnector with the specified collection and optional collection options.
func (*StdConnector) WithContext ¶
func (conn *StdConnector) WithContext(ctx context.Context) Connector
WithContext returns a copy of the StdConnector with the specified context.