packagemainimport("context""fmt""log""github.com/mongodb/mongo-go-driver/mongo""go.mongodb.org/mongo-driver/mongo/options")funcmain(){client,err:=mongo.Connect(context.Background(),options.Client().ApplyURI("mongodb://localhost:27017"))iferr!=nil{log.Fatal(err)}// Check the connectionerr=client.Ping(context.Background(),nil)iferr!=nil{log.Fatal(err)}fmt.Println("Connected to MongoDB!")// handle for the trainers collection in the test database// collection := client.Database("test").Collection("trainers")// Close the connectionerr=client.Disconnect(context.TODO())iferr!=nil{log.Fatal(err)}fmt.Println("Connection to MongoDB closed.")}
mongo.Connect Connect
client.Ping Check the connection
client.Disconnect Close the connection
BSON (Binary Serialized Document Format, Binary-encoded JSON)
一種二進制形式的存儲格式,採用了類似於 C 語言結構體的名稱
對表示方法支援內嵌的文件物件和陣列物件
具有輕量性、可遍歷性、高效性的特點,可以有效描述非結構化數據和結構化數據
schema-less的存儲形式
優點是靈活性高,但它的缺點是空間利用率不是很理想
不像一般 json 用簡單的 string 和 number,而是可以給予 type (int, long, date, floating point, and decimal128),可以更方便的去做比較排許等等的
在 Go 中提供了兩種 BSON 的資料格式 D types the Raw types
D type
The D family of types is used to concisely build BSON objects using native Go types. This can be particularly useful for constructing commands passed to MongoDB. The D family consists of four types:
D: A BSON document. This type should be used in situations where order matters, such as MongoDB commands.
M: An unordered map. It is the same as D, except it does not preserve order.
A: A BSON array.
E: A single element inside a D.
Example
12345678
// D type filter to find where the name field matches either Alice or Bob bson.D\{\{"name",bson.D\{\{"$in",bson.A{"Alice","Bob"}}}}}
Raw
The Raw family of types is used for validating a slice of bytes. You can also retrieve single elements from Raw types using a Lookup. This is useful if you don’t want the overhead of having to unmarshall the BSON into another type. This tutorial will just use the D family of types.
CRUD Operations
12345
typeTrainerstruct{NamestringAgeintCitystring}
C - Insert documents
123456789101112131415161718
ash:=Trainer{"Ash",10,"Pallet Town"}misty:=Trainer{"Misty",10,"Cerulean City"}brock:=Trainer{"Brock",15,"Pewter City"}// insert oneinsertResult,err:=collection.InsertOne(context.TODO(),ash)iferr!=nil{log.Fatal(err)}fmt.Println("Inserted a single document: ",insertResult.InsertedID)// insert manytrainers:=[]interface{}{misty,brock}insertManyResult,err:=collection.InsertMany(context.TODO(),trainers)iferr!=nil{log.Fatal(err)}fmt.Println("Inserted multiple documents: ",insertManyResult.InsertedIDs)
// 找出 name = "Ash"filter:=bson.D// 將 age - 1update:=bson.D{{"$inc",bson.D{{"age",1},}},}updateResult,err:=collection.UpdateOne(context.TODO(),filter,update)iferr!=nil{log.Fatal(err)}fmt.Printf("Matched %v documents and updated %v documents.\n",updateResult.MatchedCount,updateResult.ModifiedCount)
$inc - Increments the value of the field by the specified amount.
updateResult.MatchedCount - The number of documents that matched the filter.
updateResult.ModifiedCount - The number of documents that were modified.
R - Find documents
Find a document use collection.FindOne()
To find a document, you will need a filter document as well as a pointer to a value into which the result can be decoded
12345678910
// create a value into which the result can be decodedvarresultTrainer// 取出的值必須要 Decodeerr=collection.FindOne(context.TODO(),filter).Decode(&result)iferr!=nil{log.Fatal(err)}fmt.Printf("Found a single document: %+v\n",result)
Find multiple documents use collection.Find()
This method returns a Cursor. A Cursor provides a stream of documents through which you can iterate and decode one at a time. Once a Cursor has been exhausted, you should close the Cursor.
Here you’ll also set some options on the operation using the options package. Specifically, you’ll set a limit so only 2 documents are returned.
// Pass these options to the Find methodfindOptions:=options.Find()findOptions.SetLimit(2)// Here's an array in which you can store the decoded documentsvarresults[]*Trainer// Passing nil as the filter matches all documents in the collection// 範例原本寫 nil 但是有問題所以改成 bson.D{}cur,err:=collection.Find(context.TODO(),bson.D{},findOptions)iferr!=nil{log.Fatal(err)}// Finding multiple documents returns a cursor// Iterating through the cursor allows us to decode documents one at a timeforcur.Next(context.TODO()){// create a value into which the single document can be decodedvarelemTrainererr:=cur.Decode(&elem)iferr!=nil{log.Fatal(err)}results=append(results,&elem)}iferr:=cur.Err();err!=nil{log.Fatal(err)}// Close the cursor once finishedcur.Close(context.TODO())fmt.Printf("Found multiple documents (array of pointers): %+v\n",results)forindex,result:=rangeresults{fmt.Printf("%d: %+v \n",index,result)}
D - Delete Documents
delete documents using collection.DeleteOne() or collection.DeleteMany().
Here you pass nil as the filter argument, which will match all documents in the collection. You could also use collection.Drop() to delete an entire collection.
12345678910111213141516
// DeleteOnedeleteOneResult,err:=collection.DeleteOne(context.TODO(),bson.M{})iferr!=nil{log.Fatal(err)}fmt.Printf("Deleted %v documents in the trainers collection\n",deleteOneResult.DeletedCount)// DeleteManydeleteResult,err:=collection.DeleteMany(context.TODO(),bson.M{})// DELETA name = Misty && age > 10// deleteResult, err := collection.DeleteMany(context.TODO(), bson.M{"name": "Misty", "age": bson.M{"$gte": 10}})// deleteResult, err := collection.DeleteMany(context.TODO(), bson.D\{\{"name", "Misty"}, {"age", bson.M{"$gte": 10}}})iferr!=nil{log.Fatal(err)}fmt.Printf("Deleted %v documents in the trainers collection\n",deleteResult.DeletedCount)