-
Notifications
You must be signed in to change notification settings - Fork 152
Hooks
This is the first version of Hook of Qmgo. The Usage may change.
Generally, User use Hook will implement the callback method through the operated document. But many operations of Qmgo don't have documents as parameter(like Update method), which we think it's a very concise way.
So the Hook v1 of Qmgo will be different from the "general" Hook implementation:
-The user implements the struct method of Hook, and passes it to Qmgo through options of a specific operation, and Qmgo automatically do callback.
-If the Hook operation fails, there is no function to roll back the database operation in this version.
User need to implement struct methods to use Insert Hook:
BeforeInsert() error
AfterInsert() errorIn the InsertOne process
-
Implement the
Hookmethod ofInsertthrough a custom struct (Userin the following example) -
Pass in
options.InsertOneOptionsto makeHookwork. -
If you use the document
Userto directly implement the method and modify the document inBeforeInsert(), the modified document will be inserted into the database
type User struct {
Name string `bson:"name"`
Age int `bson:"age"`
}
func (u *User) BeforeInsert() error {
fmt.Println("before insert called")
return nil
}
func (u *User) AfterInsert() error {
fmt.Println("before insert called")
return nil
}
// --- running codes:
u := &User{Name: "Alice", Age: 7}
_, err := cli.InsertOne(context.Background(), u, options.InsertOneOptions{
InsertHook: u,
})In the InsertMany process
-
Implement the
Hookmethod ofInsertthrough a custom structure (Userin the following example), -
Pass in
options.InsertManyOptionsto makeHookwork. -
If you use the document
Userto implement method and modify the document inBeforeInsert(), the modified document will be inserted into the database -
Because multiple documents are inserted, and
Hookhappens for each document, soHookwill be called back multiple times according to the number of inserted documents
type User struct {
Name string `bson:"name"`
Age int `bson:"age"`
}
func (u *User) BeforeInsert() error {
fmt.Println("before insert called")
return nil
}
func (u *User) AfterInsert() error {
fmt.Println("before insert called")
return nil
}
// --- running codes:
u1 := &User{Name: "jz", Age: 7}
u2 := &User{Name: "xm", Age: 7}
us := []*User{u1, u2}
_, err := cli.InsertMany(ctx, us, options.InsertManyOptions{
InsertHook: us,
})User need to implement struct methods to use Update Hook:
BeforeUpdate() error
AfterUpdate() errorIn the UpdateOne/UpdateAll process
-
Implement the
Hookmethod ofInsertthrough a custom struct (MyUpdateHookin the following example) -
Pass in
options.UpdateOptionsto makeHookwork. -
If you use the document
Userto directly implement methods and modify the document in theBeforeUpdate(), will not affect the document written in the database.
type MyUpdateHook struct {
beforeUpdateCount int
afterUpdateCount int
}
func (u *MyUpdateHook) BeforeUpdate() error {
u.beforeUpdateCount++
return nil
}
func (u *MyUpdateHook) AfterUpdate() error {
u.afterUpdateCount++
return nil
}
u := User{Name: "jz", Age: 7}
uh := &MyUpdateHook{}
_, err := cli.InsertOne(context.Background(), u)
ast.NoError(err)
err = cli.UpdateOne(ctx, bson.M{"name": "jz"}, bson.M{operator.Set: bson.M{"age": 27}}, options.UpdateOptions{
UpdateHook: uh,
})
cli.UpdateAll(ctx, bson.M{"name": "jz"}, bson.M{operator.Set: bson.M{"age": 27}}, options.UpdateOptions{
UpdateHook: uh,
})User need to implement struct methods to use Remove Hook:
BeforeRemove() error
AfterRemove() errorIn the Remove/RemoveAll process
-
A custom structure (
MyRemoveHookin the following example) implements theHookmethod ofRemove -
Pass in
options.RemoveOptionsto makeHookwork.
type MyRemoveHook struct {
beforeCount int
afterCount int
}
func (m *MyRemoveHook) BeforeRemove() error {
m.beforeCount++
return nil
}
func (m *MyRemoveHook) AfterRemove() error {
m.afterCount++
return nil
}
rh := &MyRemoveHook{}
err = cli.Remove(ctx, bson.M{"age": 17}, options.RemoveOptions{
RemoveHook: rh,
})
rh = &MyRemoveHook{}
_, err = cli.RemoveAll(ctx, bson.M{"age": "7"}, options.RemoveOptions{
RemoveHook: rh,
})User need to implement struct methods to use Query Hook:
BeforeQuery() error
AfterQuery() errorIn the Find().One/Find().All() process,
- A custom struct (
MyQueryHookin the following example) implements theHookmethod ofQuery - Pass in
options.FindOptionsto makeHookwork.
type MyQueryHook struct {
beforeCount int
afterCount int
}
func (q *MyQueryHook) BeforeQuery() error {
q.beforeCount++
return nil
}
func (q *MyQueryHook) AfterQuery() error {
q.afterCount++
return nil
}
qk := &MyQueryHook{}
err = cli.Find(ctx, bson.M{"age": 17}, options.FindOptions{
QueryHook: qk,
}).One(ur)
err = cli.Find(ctx, bson.M{"age": 17}, options.FindOptions{
QueryHook: qh,
}).All(&ur)