Model Hooks
You can set up hook functions for models (structs), and these hook functions will be called before and after MongoDB collection operations. For example, you can process a document before and after inserting it, or handle a document after querying it.
The currently supported hooks are:
Insert Hook
BeforeInsert
: Called before insertingAfterInsert
: Called after inserting
Delete Hook
BeforeDelete
: Called before deletingAfterDelete
: Called after deleting
Update Hook
BeforeUpdate
: Called before updatingAfterUpdate
: Called after updating
Upsert Hook
BeforeUpsert
: Called before upsertingAfterUpsert
: Called after upserting
Find Hook
BeforeFind
: Called before queryingAfterFind
: Called after querying
Note: Model hooks will only be enabled if EnableModelHook
is set to true
during plugin initialization (for details, refer to Enabling Built-in Plugins - Hooks).
Insert Hook
If you want to process a document before and after inserting it, you can implement the following specific hook methods:
BeforeInsert(ctx context.Context) error // Hook before insertion
AfterInsert(ctx context.Context) error // Hook after insertion
Code example:
type User struct {
mongox.Model `bson:",inline"`
Name string `bson:"name"`
Age int `bson:"age"`
}
func (u *User) BeforeInsert(ctx context.Context) error {
fmt.Println("BeforeInsert called")
return nil
}
func (u *User) AfterInsert(ctx context.Context) error {
fmt.Println("AfterInsert called")
return nil
}
mongox.InitPlugin(&mongox.PluginConfig{
EnableModelHook: true,
})
user := &User{Name: "Mingyong Chen", Age: 18}
insertOneResult, err := userColl.Creator().InsertOne(context.Background(), user)
users := []*User{
{Name: "Mingyong Chen", Age: 18},
{Name: "chenmingyong", Age: 18},
}
insertManyResult, err := userColl.Creator().InsertMany(context.Background(), users)
// You can also use the ModelHook method to pass an object that implements the BeforeInsert and AfterInsert methods.
// Note: The object passed via ModelHook takes precedence over the parameters passed in the InsertOne method.
// userColl.Creator().ModelHook(user).InsertOne(context.Background(), user)
By passing an object that implements the BeforeInsert
and AfterInsert
methods via the ModelHook
method, you can trigger these hook methods.
Note: The object passed via ModelHook
takes precedence over the parameters passed in the InsertOne
or InsertMany
methods and will override those parameters.
Find Hook
If you want to perform some actions before querying a document or process the document after querying it, you can implement the following specific hook methods:
BeforeFind(ctx context.Context) error // Hook before querying
AfterFind(ctx context.Context) error // Hook after querying
Code example:
type User struct {
mongox.Model `bson:",inline"`
Name string `bson:"name"`
Age int `bson:"age"`
}
func (u *User) AfterFind(ctx context.Context) error {
fmt.Println("AfterFind called")
return nil
}
type findHook struct{}
func (b *findHook) BeforeFind(ctx context.Context) error {
fmt.Println("BeforeFind called")
return nil
}
func (b *findHook) AfterFind(ctx context.Context) error {
fmt.Println("AfterFind called")
return nil
}
mongox.InitPlugin(&mongox.PluginConfig{
EnableModelHook: true,
})
user, err := userColl.Finder().ModelHook(new(findHook)).Filter(query.Eq("name", "Mingyong Chen")).FindOne(context.Background())
users, err := userColl.Finder().Filter(query.In("name", "Mingyong Chen", "chenmingyong")).Find(context.Background())
By default, enabling EnableModelHook
will only trigger the AfterFind
method and not the BeforeFind
method.
To trigger the BeforeFind
method, pass an object that implements BeforeFind
to the ModelHook
method.
Note: The object passed via ModelHook
takes precedence over the queried User
object and will override the queried User
object.
Delete Hook
If you want to perform some actions before and after deleting a document, you can implement the following specific hook methods:
BeforeDelete(ctx context.Context) error // Hook before deletion
AfterDelete(ctx context.Context) error // Hook after deletion
Code example:
type deleteHook struct{}
func (d *deleteHook) BeforeDelete(ctx context.Context) error {
fmt.Println("BeforeDelete called")
return nil
}
func (d *deleteHook) AfterDelete(ctx context.Context) error {
fmt.Println("AfterDelete called")
return nil
}
mongox.InitPlugin(&mongox.PluginConfig{
EnableModelHook: true,
})
deleteOneResult, err := userColl.Deleter().ModelHook(new(deleteHook)).Filter(query.Eq("name", "Mingyong Chen")).DeleteOne(context.Background())
deleteManyResult, err := userColl.Deleter().ModelHook(new(deleteHook)).Filter(query.Eq("name", "Mingyong Chen")).DeleteMany(context.Background())
By passing an object that implements the BeforeDelete
and AfterDelete
methods via the ModelHook
method, you can trigger these hook methods.
Update Hook
If you want to perform some actions before and after updating a document, you can implement the following specific hook methods:
BeforeUpdate(ctx context.Context) error // Hook before updating
AfterUpdate(ctx context.Context) error // Hook after updating
Code example:
type updateHook struct{}
func (u *updateHook) BeforeUpdate(ctx context.Context) error {
fmt.Println("BeforeUpdate called")
return nil
}
func (u *updateHook) AfterUpdate(ctx context.Context) error {
fmt.Println("AfterUpdate called")
return nil
}
mongox.InitPlugin(&mongox.PluginConfig{
EnableModelHook: true,
})
updateOneResult, err := userColl.Updater().ModelHook(new(updateHook)).Filter(query.Eq("name", "Mingyong Chen")).Updates(update.Set("age", 6)).UpdateOne(context.Background())
updateManyResult, err := userColl.Updater().ModelHook(new(updateHook)).Filter(query.In("name", "Mingyong Chen", "chenmingyong")).Updates(update.Set("age", 6)).UpdateMany(context.Background())
By default, mongox
will decide whether to trigger the BeforeUpdate
and AfterUpdate
methods based on the updates
parameter in the Updates
method.
Since the updates
parameter generally does not implement BeforeUpdate
and AfterUpdate
methods, these methods are usually not triggered.
To trigger BeforeUpdate
and AfterUpdate
, pass an object that implements the corresponding methods to the ModelHook
.
Upsert Hook
If you want to process a document before and after saving it, you can implement the following specific hook methods:
BeforeUpsert(ctx context.Context) error // Hook before upserting
AfterUpsert(ctx context.Context) error // Hook after upserting
Code example:
type upsertHook struct{}
func (u *upsertHook) BeforeUpsert(ctx context.Context) error {
fmt.Println("BeforeUpsert called")
return nil
}
func (u *upsertHook) AfterUpsert(ctx context.Context) error {
fmt.Println("AfterUpsert called")
return nil
}
mongox.InitPlugin(&mongox.PluginConfig{
EnableModelHook: true,
})
updateResult, err := userColl.Updater().ModelHook(new(upsertHook)).Filter(query.Eq("name", "Mingyong Chen")).Updates(update.Set("age", 6)).Upsert(context.Background())
The timing for triggering BeforeUpsert
and AfterUpsert
is the same as with the UpdateOne
or UpdateMany
methods, meaning that if the updates
parameter does not implement the BeforeUpsert
and AfterUpsert
methods, these methods will not be triggered.
To trigger BeforeUpsert
and AfterUpsert
, pass an object that implements the corresponding methods to the ModelHook
.