preface
Recently, I learned how to operate mongodb in GO, and learned that there are two libraries, third-party MGO and official Mongo-driver, that are used most. Mgo has stopped maintenance, so mongo-driver is selected. This article records some common code operation notes for easy reference.
The installation
#Initialize the go module, named Mongo-Notes
mkdir goMongo && cd goMongo
go mod init mongo-notes
#Get go Mongo module dependencies
go get go.mongodb.org/mongo-driver/mongo
Copy the code
Client connection
There are two main methods for client connection:
- New a client instance, then Connect;
- Connect directly while obtaining a client instance.
The second method is usually used and the code is more concise.
Any operation on Mongo, including Connect, CURD, Disconnect, etc., is inseparable from the Context Context of an operation, requiring a Context instance as the first parameter of the operation.
Connect using the NewClient instance
package main
import (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main(a) {
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017"))
iferr ! =nil {
fmt.Errorf("client establish failed. err: %v", err)
}
// ctx
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// connect
if err = client.Connect(ctx); err == nil {
fmt.Println("connect to db success.")}// Delay the call to the disconnection function after the client is instantiated
defer func(a) {
iferr = client.Disconnect(ctx); err ! =nil {
panic(err)
}
}()
}
Copy the code
Connect using the mongo.connect () function
A direct connection
package main
import (
"context"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
)
func main(a) {
clientOpts := options.Client().ApplyURI("mongodb://localhost:27017/? connect=direct")
client, err := mongo.Connect(context.TODO(), clientOpts)
iferr ! =nil {
log.Fatal(err)
}
}
Copy the code
User name and password authentication connection
package main
import (
"context"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
)
func main(a) {
credential := options.Credential{
Username: "username",
Password: "password",
}
clientOpts := options.Client().ApplyURI("mongodb://localhost:27017").SetAuth(credential)
// You can connect directly to the URI with the username and password
// clientOpts := options.Client().ApplyURI("mongodb://username:password@localhost:27017")
client, err := mongo.Connect(context.TODO(), clientOpts)
iferr ! =nil {
log.Fatal(err)
}
}
Copy the code
ReplicaSet replicas are connected
package main
import (
"context"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
)
func main(a) {
clientOpts := options.Client().ApplyURI("mongodb://localhost:27017,localhost:27018/? replicaSet=replset")
client, err := mongo.Connect(context.TODO(), clientOpts)
iferr ! =nil {
log.Fatal(err)
}
}
Copy the code
Shard Fragment connection
package main
import (
"context"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
)
func main(a) {
clientOpts := options.Client().ApplyURI("mongodb://localhost:27017,localhost:27018")
client, err := mongo.Connect(context.TODO(), clientOpts)
iferr ! =nil {
log.Fatal(err)
}
}
Copy the code
Module configuration type connection
In real projects, there are usually configuration modules, so the most common way to connect is to write the connection configuration in a special configuration module file:
package config
import (
"time"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
// MONGO SETTINGS
var (
credentials = options.Credential{
AuthMechanism: "SCRAM-SHA-1",
AuthSource: "anquan",
Username: "ysj",
Password: "123456",}// direct = true
connectTimeout = 10 * time.Second
hosts = []string{"localhost:27017"."localhost:27018"}
maxPoolSize uint64 = 20
minPoolSize uint64 = 5
readPreference = readpref.Primary()
replicaSet = "replicaSetDb"
// ClientOpts mongoClient connection client parameters
ClientOpts = &options.ClientOptions{
Auth: &credentials,
ConnectTimeout: &connectTimeout,
//Direct: &direct,
Hosts: hosts,
MaxPoolSize: &maxPoolSize,
MinPoolSize: &minPoolSize,
ReadPreference: readPreference,
ReplicaSet: &replicaSet,
}
)
Copy the code
While the above is correct, it is too bloated and could use a more elegant and concise chain call:
package config
import (
"time"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
// ClientOpts mongoClient connection client parameters
var ClientOpts = options.Client().
SetAuth(options.Credential{
AuthMechanism: "SCRAM-SHA-1",
AuthSource: "anquan",
Username: "ysj",
Password: "123456",
}).
SetConnectTimeout(10 * time.Second).
SetHosts([]string{"localhost:27017"}).
SetMaxPoolSize(20).
SetMinPoolSize(5).
SetReadPreference(readpref.Primary()).
SetReplicaSet("replicaSetDb")
Copy the code
The configuration is then introduced into the main module
package main
import (
"context"
"log"
"mongo-notes/config" // Import the configuration module
"go.mongodb.org/mongo-driver/mongo"
)
func main(a){
client, err := mongo.Connect(context.TODO(), config.ClientOpts)
iferr ! =nil {
log.Fatal(err)
}
}
Copy the code
CURD operation
To understand bson
Using mongo-driver to operate mongodb requires the Bson provided by this module. It is mainly used to write the filter of the query, construct the document record and receive the value of the query decoding, that is, to serialize between GO and Mongo. Basically, only the following three data structures are used:
bson.D{}
: for documentsThe orderlyDescription, key-value separated by commas.bson.M{}
: Map structure. Key-values are separated by colons.A disorderly, the most convenient to use;bson.A{}
: array structure, element requirement isThe orderlyThat is, the element isbson.D{}
Type.
Access to the db
/ / get the db
db := client.Database("test")
collectionNames, err := db.ListCollectionNames(ctx, bson.M{})
fmt.Println("collectionNames:", collectionNames)
Copy the code
Access to the collection
/ / for collecton
collection := db.Collection("person")
fmt.Printf("collection: %s \n", collection.Name())
Copy the code
Create indexes
// Create index
indexView := collection.Indexes()
indexName := "index_by_name"
indexBackground := true
indexUnique := true
indexModel := mongo.IndexModel{
Keys: bson.D{{"name".1}},
Options: &options.IndexOptions{
Name: &indexName,
Background: &indexBackground,
Unique: &indexUnique,
},
}
index, err := indexView.CreateOne(ctx, indexModel)
iferr ! =nil {
log.Fatalf("index created failed. err: %v \n", err)
return
}
fmt.Println("new index name:", index)
Copy the code
View index
// Check the index
indexCursor, err := collection.Indexes().List(ctx)
var indexes []bson.M
iferr = indexCursor.All(ctx, &indexes); err ! =nil {
log.Fatal(err)
}
fmt.Println(indexes)
Copy the code
Insert
InsertOne
collection := client.Database("test").Collection("person")
// InsertOne
insertOneResult, err := collection.InsertOne(ctx, bson.M{"name": "Nothing"."gender": "Male"."level": 1})
iferr ! =nil {
log.Fatal(err)
}
fmt.Println("id:", insertOneResult.InsertedID)
Copy the code
InsertMany
// InsertMany
docs := []interface{}{
bson.M{"name": "5t5"."gender": "Male"."level": 0},
bson.M{"name": "Nanemi"."gender": "Male"."level": 1}},// Ordered set to false indicates that one failed insert does not affect the insertion of other documents. The default value is true, and one failed insert will not be written to other documents
insertManyOpts := options.InsertMany().SetOrdered(false)
insertManyResult, err := collection.InsertMany(ctx, docs, insertManyOpts)
iferr ! =nil {
log.Fatal(err)
}
fmt.Println("ids:", insertManyResult.InsertedIDs)
Copy the code
Find
Find
// Find
findOpts := options.Find().SetSort(bson.D{{"name".1}})
findCursor, err := collection.Find(ctx, bson.M{"level": 0}, findOpts)
var results []bson.M
iferr = findCursor.All(ctx, &results); err ! =nil {
log.Fatal(err)
}
for _, result := range results {
fmt.Println(result)
}
Copy the code
FindOne
// FindOne
// Struct can be used to receive decoded results
// var result struct {
// Name string
// Gender string
// Level int
// }
// Or better yet, use bson.m directly
var result bson.M
// Sort by name and skip the first one, and only return the name and level fields
findOneOpts := options.FindOne().SetSkip(1).SetSort(bson.D{{"name".1}}).SetProjection(bson.D{{"name".1}, {"level".1}})
singleResult := collection.FindOne(ctx, bson.M{"name": "5t5"}, findOneOpts)
if err = singleResult.Decode(&result); err == nil {
fmt.Printf("result: %+v\n", result)
}
Copy the code
FindOneAndDelete
// FindOneAndDelete
findOneAndDeleteOpts := options.FindOneAndDelete().SetProjection(bson.D{{"name".1}, {"level".1}})
var deletedDoc bson.M
singleResult := collection.FindOneAndDelete(ctx, bson.D{{"name"."Nothing"}}, findOneAndDeleteOpts)
iferr = singleResult.Decode(&deletedDoc); err ! =nil {
if err == mongo.ErrNoDocuments {
return
}
log.Fatal(err)
}
fmt.Printf("deleted document: %+v \n", deletedDoc)
Copy the code
FindOneAndReplace
// FindOneAndReplace
// Note: the document is returned before the replaceMent, and docs that meet the criteria will be completely replaced with replaceMent
_id, err := primitive.ObjectIDFromHex("5fde05b9612cb3d19c4b25e8")
findOneAndReplaceOpts := options.FindOneAndReplace().SetUpsert(true)
replaceMent := bson.M{"name": "5t5"."skill": "Six eye"}
var replaceMentDoc bson.M
err = collection.FindOneAndReplace(ctx, bson.M{"_id": _id}, replaceMent , findOneAndReplaceOpts).Decode(&replaceMentDoc)
iferr ! =nil {
if err==mongo.ErrNoDocuments {
return
}
log.Fatal(err)
}
fmt.Printf("document before replacement: %v \n", replaceMentDoc)
Copy the code
FindOneAndUpdate
// FindOneAndUpdate
// Note that the result is still the same as the document before the update
_id, err := primitive.ObjectIDFromHex("5fde05b9612cb3d19c4b25e8")
findOneAndUpdateOpts := options.FindOneAndUpdate().SetUpsert(true)
update := bson.M{"$set": bson.M{"level": 0."gender": "Male"}}
var toUpdateDoc bson.M
err = collection.FindOneAndUpdate(ctx, bson.M{"_id": _id}, update, findOneAndUpdateOpts).Decode(&toUpdateDoc)
iferr ! =nil {
if err == mongo.ErrNoDocuments {
return
}
log.Fatal(err)
}
fmt.Printf("document before updating: %v \n", toUpdateDoc)
}
Copy the code
Update
UpdateOne
//UpdateOne
updateOneOpts := options.Update().SetUpsert(true)
updateOneFilter := bson.M{"name": nanamin}
updateOneSet := bson.M{"$set": bson.M{"skill": "37 cents"}}
updateResult, err := collection.UpdateOne(ctx, updateOneFilter, updateOneSet, updateOneOpts)
fmt.Printf(
"matched: %d modified: %d upserted: %d upsertedID: %v\n",
updateResult.MatchedCount,
updateResult.ModifiedCount,
updateResult.UpsertedCount,
updateResult.UpsertedID,
)
Copy the code
UpdateMany
// UpdateMany
updateManyFilter := bson.M{"name": "Nothing"}
updateManySet := bson.M{"$set": bson.M{"level": 1}}
updateManyResult, err := collection.UpdateMany(ctx,updateManyFilter, updateManySet)
fmt.Printf(
"matched: %d modified: %d upserted: %d upsertedID: %v\n",
updateManyResult.MatchedCount,
updateManyResult.ModifiedCount,
updateManyResult.UpsertedCount,
updateManyResult.UpsertedID,
)
Copy the code
ReplaceOne
// ReplaceOne
// There is no difference between FindOneAndReplace and FindOneAndReplace on the data level
replaceOpts := options.Replace().SetUpsert(true)
replaceMent := bson.M{"name": "Black"."level": 2."gender": "Male"}
updateResult, err := collection.ReplaceOne(ctx, bson.M{"name": "Nothing"}, replaceMent, replaceOpts)
fmt.Printf(
"matched: %d modified: %d upserted: %d upsertedID: %v\n",
updateResult.MatchedCount,
updateResult.ModifiedCount,
updateResult.UpsertedCount,
updateResult.UpsertedID,
)
Copy the code
Delete
DeleteOne
// DeleteOne
deleteOneOpts := options.Delete().SetCollation(&options.Collation{
// Ignore case
CaseLevel: false,
})
deleteResult, err := collection.DeleteOne(ctx, bson.D{{"name"."Nothing"}}, deleteOneOpts)
fmt.Println("deletet count:", deleteResult.DeletedCount)
Copy the code
DeleteMany
// DeleteMany
deleteManyOpts := options.Delete().SetCollation(&options.Collation{
// Ignore case
CaseLevel: false,
})
deleteManyResult, err := collection.DeleteMany(ctx, bson.D{{"name"."Nothing"}}, deleteOneOpts)
fmt.Println("deletet count:", deleteManyResult.DeletedCount)
Copy the code
Batch operation BulkWrite
// BulkWrite
names := []string{"5t5".nanamin."Black"."Rose"."Nothing"}
models := []mongo.WriteModel{}
updateOperation := bson.M{"$set": bson.M{"Animation": "Spell back to war."}}
for _, name := range names {
updateOneModel := mongo.NewUpdateOneModel().SetFilter(bson.M{"name": name}).SetUpdate(updateOperation).SetUpsert(true)
models = append(models, updateOneModel)
}
bulkWriteOpts := options.BulkWrite().SetOrdered(false)
bulkWriteResults, err := collection.BulkWrite(ctx, models, bulkWriteOpts)
iferr ! =nil {
log.Fatal(err)
}
fmt.Printf(
"matched: %d modified: %d upserted: %d upsertedIDs: %v\n",
bulkWriteResults.MatchedCount,
bulkWriteResults.ModifiedCount,
bulkWriteResults.UpsertedCount,
bulkWriteResults.UpsertedIDs,
)
Copy the code
Business transaction
Transactions guarantee that all of our operations will either succeed or fail. The biggest advantage of using transactions is to avoid the impact of a certain operation failure on the existing database environment. I once heard a friend joke that because transactions are not used, after the operation failure, we can only delete data one by one in the production database. So, using transactions is a good habit, even if the code looks bloated.
Mongo-driver transactions need to be started using a session. Any transaction operations need to be in the session context. Here is a comparison of transaction operations using different apis:
Use different apis | Active Session Management | Active sessionContext management | Active transaction abort/commit | convenience |
---|---|---|---|---|
mongo.NewSessionContext | is | is | is | * |
mongo.WithSession | is | no | is | 支那 |
client.UseSessionWithOptions | no | no | is | * * * |
session.WithTransaction | is | no | no | * * * * |
mongo.NewSessionContext
package main
import (
"context"
"fmt"
"log"
"mongo-notes/config"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
func main(a) {
// ctx
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// client
client, err := mongo.Connect(ctx, config.ClientOpts)
iferr ! =nil {
log.Fatal(err)
}
// collection
collection := client.Database("test").Collection("person")
// session
session, err := client.StartSession()
iferr ! =nil {
panic(err)
}
defer session.EndSession(context.TODO())
// session context
sessionCtx := mongo.NewSessionContext(ctx, session)
// session Starts transaction
iferr = session.StartTransaction(); err ! =nil {
panic(err)
}
// transaction: insertOne in sessionCtx
insertOneResult, err := collection.InsertOne(sessionCtx, bson.D{{"name"."Big boss"}})
iferr ! =nil {
// Use context.background () to ensure abort succeeds, even if mongo's CTX has timed out
_ = session.AbortTransaction(context.Background())
panic(err)
}
// transaction: findOne in sessionCtx
var result bson.M
if err = collection.FindOne(sessionCtx, bson.D{{"_id", insertOneResult.InsertedID}}).Decode(&result); err ! =nil {
// Use context.background () to ensure abort succeeds, even if mongo's CTX has timed out
_ = session.AbortTransaction(context.Background())
panic(err)
}
fmt.Printf("result: %v\n", result)
// Using context.background () ensures that the commit succeeds, even if mongo's CTX has timed out
iferr = session.CommitTransaction(context.Background()); err ! =nil {
panic(err)
}
}
Copy the code
mongo.WithSession
package main
import (
"context"
"fmt"
"log"
"mongo-notes/config"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readconcern"
)
func main(a) {
// ctx
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// client
client, err := mongo.Connect(ctx, config.ClientOpts)
iferr ! =nil {
log.Fatal(err)
}
// collection
collection := client.Database("test").Collection("person")
// session
sessionOpts := options.Session().SetDefaultReadConcern(readconcern.Majority())
session, err := client.StartSession(sessionOpts)
iferr ! =nil {
log.Fatal(err)
}
defer session.EndSession(context.TODO())
// transaction
err = mongo.WithSession(ctx, session, func(sessionCtx mongo.SessionContext) error {
iferr := session.StartTransaction(); err ! =nil {
return err
}
insertOneResult, err := collection.InsertOne(sessionCtx, bson.D{{"name"."Little boss"}})
iferr ! =nil {
// Use context.background () to ensure abort succeeds, even if mongo's CTX has timed out
_ = session.AbortTransaction(context.Background())
return err
}
var result bson.M
if err = collection.FindOne(sessionCtx, bson.D{{"_id", insertOneResult.InsertedID}}).Decode(&result); err ! =nil {
// Use context.background () to ensure abort succeeds, even if mongo's CTX has timed out
_ = session.AbortTransaction(context.Background())
return err
}
fmt.Println(result)
// Using context.background () ensures that the commit succeeds, even if mongo's CTX has timed out
return session.CommitTransaction(context.Background())
})
}
Copy the code
client.UseSessionWithOptions
package main
import (
"context"
"fmt"
"log"
"mongo-notes/config"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readconcern"
)
func main(a) {
// ctx
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// client
client, err := mongo.Connect(ctx, config.ClientOpts)
iferr ! =nil {
log.Fatal(err)
}
// collection
collection := client.Database("test").Collection("person")
// session
sessionOpts := options.Session().SetDefaultReadConcern(readconcern.Majority())
// transaction
err = client.UseSessionWithOptions(ctx, sessionOpts, func(sessionCtx mongo.SessionContext) error {
iferr := sessionCtx.StartTransaction(); err ! =nil {
return err
}
insertOneResult, err := collection.InsertOne(sessionCtx, bson.D{{"name"."Scum Five."}})
iferr ! =nil {
// Use context.background () to ensure abort succeeds, even if mongo's CTX has timed out
_ = sessionCtx.AbortTransaction(context.Background())
return err
}
var result bson.M
if err = collection.FindOne(sessionCtx, bson.D{{"_id", insertOneResult.InsertedID}}).Decode(&result); err ! =nil {
_ = sessionCtx.AbortTransaction(context.Background())
return err
}
fmt.Println(result)
// Using context.background () ensures that the commit succeeds, even if mongo's CTX has timed out
return sessionCtx.CommitTransaction(context.Background())
})
iferr ! =nil {
log.Fatal(err)
}
}
Copy the code
session.WithTransaction
package main
import (
"context"
"fmt"
"log"
"mongo-notes/config"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readconcern"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
func main(a) {
// ctx
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, config.ClientOpts)
iferr ! =nil {
log.Fatal(err)
}
// collection
collection := client.Database("test").Collection("person")
// session read policy
sessOpts := options.Session().SetDefaultReadConcern(readconcern.Majority())
session, err := client.StartSession(sessOpts)
iferr ! =nil {
log.Fatal(err)
}
defer session.EndSession(context.TODO())
// Transaction read priority
transacOpts := options.Transaction().SetReadPreference(readpref.Primary())
// Insert a record, find a record in the same transaction
result, err := session.WithTransaction(ctx, func(sessionCtx mongo.SessionContext) (interface{}, error) {
// insert one
insertOneResult, err := collection.InsertOne(sessionCtx, bson.M{"name": "Nobody's Part."."level": 5})
iferr ! =nil {
log.Fatal(err)
}
fmt.Println("inserted id:", insertOneResult.InsertedID)
// find one
var result struct {
Name string `bson:"name,omitempty"`
Level int `bson:"level,omitempty"`
}
singleResult := collection.FindOne(sessionCtx, bson.M{"name": "Nobody's Part."})
iferr = singleResult.Decode(&result); err ! =nil {
return nil, err
}
return result, err
}, transacOpts)
iferr ! =nil {
log.Fatal(err)
}
fmt.Printf("find one result: %+v \n", result)
}
Copy the code
Note: this operation will fail if there is no record with the same name in the database. Although a transaction is inserted first, the transaction is a whole and the search is performed before the transaction starts, so the search will fail and the insert will also fail.
Distinct and Count
Distinct
// Distinct
distinctOpts := options.Distinct().SetMaxTime(2 * time.Second)
// Return all the different names
distinctValues, err := collection.Distinct(ctx, "name", bson.M{}, distinctOpts)
iferr ! =nil {
log.Fatal(err)
}
for _, value := range distinctValues {
fmt.Println(value)
}
Copy the code
Count
// EstimatedDocumentCount
totalCount, err := collection.EstimatedDocumentCount(ctx)
iferr ! =nil {
log.Fatal(err)
}
fmt.Println("totalCount:", totalCount)
// CountDocuments
count, err := collection.CountDocuments(ctx, bson.M{"name": "5t5"})
iferr ! =nil {
log.Fatal(err)
}
fmt.Println("count:", count)
Copy the code
Polymerization of Aggregate
// Aggregate
// Count the number of occurrences by gender
groupStage := bson.D{
{"$group", bson.D{
{"_id"."$gender"},
{"numTimes", bson.D{
{"$sum".1},
}},
}},
}
opts := options.Aggregate().SetMaxTime(2 * time.Second)
aggCursor, err := collection.Aggregate(ctx, mongo.Pipeline{groupStage}, opts)
iferr ! =nil {
log.Fatal(err)
}
var results []bson.M
iferr = aggCursor.All(ctx, &results); err ! =nil {
log.Fatal(err)
}
for _, result := range results {
fmt.Printf("gender %v appears %v times\n", result["_id"], result["numTimes"])}Copy the code
Event Monitoring Watch
The client to monitor
// Monitor all collection inserts in all db
matchStage := bson.D{{"$match", bson.D{{"operationType"."insert"}}}}
opts := options.ChangeStream().SetMaxAwaitTime(2 * time.Second)
changeStream, err := client.Watch(ctx, mongo.Pipeline{matchStage}, opts)
iferr ! =nil {
log.Fatal(err)
}
for changeStream.Next(ctx) {
fmt.Println(changeStream.Current)
}
// Insert a document into test.person
{"_id": {"_data": "825FDE28AE000000022B022C0100296E5A10046470407E872C47AFB61ECB12299F90D646645F69640
0645FDE28AE4D0D028CFA4B6B140004"},"operationType": "insert"."clusterTime":
{"$timestamp": {"t":"1608394926"."i":"2"}},"fullDocument": {"_id":
{"$oid":"5fde28ae4d0d028cfa4b6b14"},"name": "Rose"."level":
{"$numberInt":"2"},"gender": "Female"},"ns": {"db": "test"."coll":
"person"},"documentKey": {"_id": {"$oid":"5fde28ae4d0d028cfa4b6b14"}}}
Copy the code
The database monitor
// db monitors all collection inserts
matchStage := bson.D{{"$match", bson.D{{"operationType"."insert"}}}}
opts := options.ChangeStream().SetMaxAwaitTime(2 * time.Second)
changeStream, err := db.Watch(context.TODO(), mongo.Pipeline{matchStage}, opts)
iferr ! =nil {
log.Fatal(err)
}
for changeStream.Next(ctx) {
fmt.Println(changeStream.Current)
}
Copy the code
The collection monitoring
// Only the insertion of the current collection is monitored
matchStage := bson.D{{"$match", bson.D{{"operationType"."insert"}}}}
opts := options.ChangeStream().SetMaxAwaitTime(2 * time.Second)
changeStream, err := collection.Watch(context.TODO(), mongo.Pipeline{matchStage}, opts)
iferr ! =nil {
log.Fatal(err)
}
for changeStream.Next(ctx) {
fmt.Println(changeStream.Current)
}
Copy the code
conclusion
In terms of usage, it is true that Python’s Pymongo is more convenient to use.
The resources
- Github.com/mongodb/mon…
- PKG. Go. Dev/go. Mongo….