Skip to content
jiangz222 edited this page Aug 30, 2020 · 18 revisions

About Hooks v1:

This is the version 1 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, then Qmgo automatically do callback.

  • If the Hook operation fails, there is no rollback operation in current version.

Insert Hook

User need to implement struct methods to use Insert Hook

BeforeInsert() error 
AfterInsert() error

InsertOne Hook

In the InsertOne process

  • Implement the Hook method of Insert through a custom struct (User in the following example)

  • Pass in options.InsertOneOptions to make Hook work.

  • If you use the document User to implement the method and modify the document in BeforeInsert(), 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
}

u := &User{Name: "Alice", Age: 7}
_, err := cli.InsertOne(context.Background(), u, options.InsertOneOptions{
  InsertHook: u,
})

InsertMany Hook

In the InsertMany process

  • Implement the Hook method of Insert through a custom structure (User in the following example),

  • Pass in options.InsertManyOptions to make Hook work.

  • If you use the document User to implement method and modify the document in BeforeInsert(), the modified document will be inserted into the database

  • Because multiple documents are inserted, and Hook happens for each document, so Hook will 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
}

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,
})

Update Hook

User need to implement struct methods to use Update Hook

BeforeUpdate() error
AfterUpdate() error

In the UpdateOne/UpdateAll process

  • Implement the Hook method of Insert through a custom struct (MyUpdateHook in the following example)

  • Pass in options.UpdateOptions to make Hook work.

  • If you use the document User to directly implement methods and modify the document in the BeforeUpdate(), 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,
})

Remove Hook

User need to implement struct methods to use Remove Hook

BeforeRemove() error
AfterRemove() error

In the Remove/RemoveAll process

  • A custom structure (MyRemoveHook in the following example) implements the Hook method of Remove

  • Pass in options.RemoveOptions to make Hook work.

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,
})

QueryHook

User need to implement struct methods to use Query Hook

BeforeQuery() error
AfterQuery() error

In the Find().One/Find().All() process,

  • A custom struct (MyQueryHook in the following example) implements the Hook method of Query
  • Pass in options.FindOptions to make Hook work.
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)
Clone this wiki locally