Skip to content

CRUD Operations

The Model[T] interface provides standard Create, Read, Update, and Delete operations. All methods expect a context.Context as the first parameter.

Create

Insert a new document into the database using Create. The model will update the document with its new _id if it implements an ID setter.

user := &User{Name: "Alice", Email: "alice@example.com"}
createdUser, err := userModel.Create(ctx, user)

To insert multiple documents, use InsertMany:

docs := []*User{
    {Name: "Bob", Email: "bob@example.com"},
    {Name: "Charlie", Email: "charlie@example.com"},
}
insertedDocs, err := userModel.InsertMany(ctx, docs)

Read (Find)

Find and FindOne return a Query[T] builder. To execute the query, chain the .Exec() or .All() method.

// Find all users
var users []*User
users, err := userModel.Find(ctx, bson.M{"age": bson.M{"$gte": 18}}).All()

// Find one user
user, err := userModel.FindOne(ctx, bson.M{"email": "alice@example.com"}).Exec()

// Find by ID
user, err := userModel.FindByID(ctx, id).Exec()

Exec vs All

Use .Exec() on a FindOne or FindByID query to return a single *T. Use .All() on a Find query to return a slice []*T.

Update

Update operations modify existing documents. goose automatically injects updatedAt timestamps if configured.

// Update a single document
res, err := userModel.UpdateOne(ctx, bson.M{"email": "alice@example.com"}, bson.M{"$set": bson.M{"age": 30}})

// Update many documents
res, err := userModel.UpdateMany(ctx, bson.M{"status": "inactive"}, bson.M{"$set": bson.M{"status": "active"}})

You can also find and update a document in one step:

updatedUser, err := userModel.FindOneAndUpdate(ctx, filter, update)

Delete

Remove documents from the collection:

// Delete one
res, err := userModel.DeleteOne(ctx, bson.M{"email": "alice@example.com"})

// Delete many
res, err := userModel.DeleteMany(ctx, bson.M{"status": "banned"})

To find and delete returning the deleted document:

deletedUser, err := userModel.FindOneAndDelete(ctx, filter)