MongORM provides a lifecycle hook system for every CRUD operation. Hooks are implemented as methods on your model struct that satisfy Go interfaces. MongORM detects them automatically using interface assertions — no registration required.
| Hook Interface | Method Signature | Called |
|---|---|---|
BeforeCreateHook[T] |
BeforeCreate(*MongORM[T]) error |
Before inserting a new document |
AfterCreateHook[T] |
AfterCreate(*MongORM[T]) error |
After inserting a new document |
BeforeSaveHook[T] |
BeforeSave(*MongORM[T], *bson.M) error |
Before save (second arg is filter, or nil for insert) |
AfterSaveHook[T] |
AfterSave(*MongORM[T]) error |
After save (insert or update) |
BeforeUpdateHook[T] |
BeforeUpdate(*MongORM[T], *bson.M, *bson.M) error |
Before updating (filter, update doc) |
AfterUpdateHook[T] |
AfterUpdate(*MongORM[T]) error |
After updating |
BeforeFindHook[T] |
BeforeFind(*MongORM[T], *bson.M) error |
Before finding a document |
AfterFindHook[T] |
AfterFind(*MongORM[T]) error |
After finding a document |
BeforeDeleteHook[T] |
BeforeDelete(*MongORM[T], *bson.M) error |
Before deleting (filter doc) |
AfterDeleteHook[T] |
AfterDelete(*MongORM[T]) error |
After deleting |
BeforeFinalizeHook[T] |
BeforeFinalize(*MongORM[T]) error |
Before applying a fetched document to the schema |
AfterFinalizeHook[T] |
AfterFinalize(*MongORM[T]) error |
After applying a fetched document to the schema |
Implement any combination of hooks by adding the corresponding methods to your model struct. You only need to implement the hooks you care about.
package main
import (
"fmt"
"github.com/azayn-labs/mongorm"
"go.mongodb.org/mongo-driver/v2/bson"
)
type ToDo struct {
ID *bson.ObjectID `bson:"_id,omitempty" mongorm:"primary"`
Text *string `bson:"text,omitempty"`
connectionString *string `mongorm:"mongodb://localhost:27017,connection:url"`
database *string `mongorm:"mydb,connection:database"`
collection *string `mongorm:"todos,connection:collection"`
}
// --- Find hooks ---
func (t *ToDo) BeforeFind(m *mongorm.MongORM[ToDo], query *bson.M) error {
fmt.Printf("[HOOK] BeforeFind — query: %+v\n", *query)
return nil
}
func (t *ToDo) AfterFind(m *mongorm.MongORM[ToDo]) error {
fmt.Println("[HOOK] AfterFind")
return nil
}
// --- Create hooks ---
func (t *ToDo) BeforeCreate(m *mongorm.MongORM[ToDo]) error {
fmt.Println("[HOOK] BeforeCreate")
return nil
}
func (t *ToDo) AfterCreate(m *mongorm.MongORM[ToDo]) error {
fmt.Println("[HOOK] AfterCreate")
return nil
}
// --- Save hooks (covers both insert and update) ---
func (t *ToDo) BeforeSave(m *mongorm.MongORM[ToDo], filter *bson.M) error {
if filter != nil {
fmt.Printf("[HOOK] BeforeSave (update) — filter: %+v\n", *filter)
} else {
fmt.Println("[HOOK] BeforeSave (insert)")
}
return nil
}
func (t *ToDo) AfterSave(m *mongorm.MongORM[ToDo]) error {
fmt.Println("[HOOK] AfterSave")
return nil
}
// --- Update hooks ---
func (t *ToDo) BeforeUpdate(m *mongorm.MongORM[ToDo], filter *bson.M, update *bson.M) error {
fmt.Printf("[HOOK] BeforeUpdate — filter: %+v, update: %+v\n", *filter, *update)
return nil
}
func (t *ToDo) AfterUpdate(m *mongorm.MongORM[ToDo]) error {
fmt.Println("[HOOK] AfterUpdate")
return nil
}
// --- Delete hooks ---
func (t *ToDo) BeforeDelete(m *mongorm.MongORM[ToDo], filter *bson.M) error {
fmt.Printf("[HOOK] BeforeDelete — filter: %+v\n", *filter)
return nil
}
func (t *ToDo) AfterDelete(m *mongorm.MongORM[ToDo]) error {
fmt.Println("[HOOK] AfterDelete")
return nil
}
// --- Finalize hooks (called when a document is decoded from the DB) ---
func (t *ToDo) BeforeFinalize(m *mongorm.MongORM[ToDo]) error {
fmt.Println("[HOOK] BeforeFinalize")
return nil
}
func (t *ToDo) AfterFinalize(m *mongorm.MongORM[ToDo]) error {
fmt.Println("[HOOK] AfterFinalize")
return nil
}
BeforeSave (filter is nil)BeforeCreateAfterCreateAfterSaveBeforeSave (filter is the query document)BeforeUpdate (filter + update documents)AfterUpdateAfterSaveBeforeFind (query document)BeforeFinalizeAfterFinalizeAfterFindBeforeDelete (filter document)AfterDeleteIf a hook returns a non-nil error, the operation is aborted and the error is propagated to the caller:
func (t *ToDo) BeforeCreate(m *mongorm.MongORM[ToDo]) error {
if t.Text == nil || *t.Text == "" {
return fmt.Errorf("text field is required")
}
return nil
}
| Back to Documentation Index | README |