Go操作MongoDB數據庫


MongoDB的Go驅動包

"go.mongodb.org/mongo-driver/bson"    //BOSN解析包
"go.mongodb.org/mongo-driver/mongo"    //MongoDB的Go驅動包
"go.mongodb.org/mongo-driver/mongo/options"
BSON簡介

BSON是一種類json的一種二進制形式的存儲格式,簡稱Binary JSON。MongoDB使用了BSON這種結構來存儲數據和網絡數據交換。

BSON對應Document這個概念,因為BSON是schema-free的,所以在MongoDB中所對應的Document也有這個特征,這里的一個Document也可以理解成關系數據庫中的一條Record,只是Document的變化更豐富一些,Document可以嵌套。

MongoDB以BSON做為其存儲結構的一個重要原因是它的可遍歷性

BSON編碼擴展了JSON表示,使其包含額外的類型,如int、long、date、浮點數和decimal128。

BSON類型

BSON數據的主要類型有:ADEMRaw。其中,A是數組,D是切片,M是映射,DM是Go原生類型。

  • A類型表示有序的BSON數組。

    bson.A{"bar", "world", 3.14159, bson.D{{"qux", 12345}}}
    
  • D類型表示包含有序元素的BSON文檔。這種類型應該在順序重要的情況下使用。如果元素的順序無關緊要,則應使用M代替。

    bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}}
    
  • M類型表示無序的映射。

    bson.M{"foo": "bar", "hello": "world", "pi": 3.14159}
    
  • E類型表示D里面的一個BSON元素。

  • Raw類型代表未處理的原始BSON文檔和元素,Raw系列類型用於驗證和檢索字節切片中的元素。當要查找BSON字節而不將其解編為另一種類型時,此類型最有用。

連接到mongoDB

// 設置mongoDB客戶端連接信息
param := fmt.Sprintf("mongodb://XXX.XXX.XXX.XXX:27017")
clientOptions := options.Client().ApplyURI(param)

// 建立客戶端連接
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
fmt.Println(err)
}

// 檢查連接情況
err = client.Ping(context.TODO(), nil)
if err != nil {
log.Fatal(err)
fmt.Println(err)
}
fmt.Println("Connected to MongoDB!")

//指定要操作的數據集
collection := client.Database("ccmsensor").Collection("mtr")

//執行增刪改查操作

// 斷開客戶端連接
err = client.Disconnect(context.TODO())
if err != nil {
log.Fatal(err)
}
fmt.Println("Connection to MongoDB closed.")

增查改刪

假如數據庫中有一些網絡連接數據,來自不同的APP,來自不同的ISP(運營商),類型如下:

type CurlInfo struct {
	DNS float64 `json:"NAMELOOKUP_TIME"` //NAMELOOKUP_TIME
	TCP float64 `json:"CONNECT_TIME"`    //CONNECT_TIME - DNS
	SSL float64 `json:"APPCONNECT_TIME"` //APPCONNECT_TIME - CONNECT_TIME
}

type ConnectData struct {
	Latency  float64  `json:"latency"`
	RespCode int      `json:"respCode"`
	Url      string   `json:"url"`
	Detail   CurlInfo `json:"details"`
}

type Sensor struct {
	ISP       string
	Clientutc int64
	DataByAPP map[string]ConnectData
}
增加

使用collection.InsertOne()來插入一條Document記錄:

func insertSensor(client *mongo.Client, collection *mongo.Collection) (insertID primitive.ObjectID) {
	apps := make(map[string]ConnectData, 0)
	apps["app1"] = ConnectData{
		Latency:  30.983999967575,
		RespCode: 200,
		Url:      "",
		Detail: CurlInfo{
			DNS: 5.983999967575,
			TCP: 10.983999967575,
			SSL: 15.983999967575,
		},
	}
	
	record := &Sensor{
		Clientutc: time.Now().UTC().Unix(),
		ISP:       "China Mobile",
		DataByAPP: apps,
	}

	insertRest, err := collection.InsertOne(context.TODO(), record)
	if err != nil {
		fmt.Println(err)
		return
	}
	insertID = insertRest.InsertedID.(primitive.ObjectID)
	return insertID
}
查詢

這里引入一個filter來匹配MongoDB數據庫中的Document記錄,使用bson.D類型來構建filter

timestamp := time.Now().UTC().Unix()
start := timestamp - 180
end := timestamp

filter := bson.D{
{"isp", isp},
{"$and", bson.A{
bson.D{{"clientutc", bson.M{"$gte": start}}},
bson.D{{"clientutc", bson.M{"$lte": end}}},
}},
}

使用collection.FindOne()來查詢單個Document記錄。這個方法返回一個可以解碼為值的結果。

func querySensor(collection *mongo.Collection, isp string) {
	//查詢一條記錄

	//篩選數據
	timestamp := time.Now().UTC().Unix()
	start := timestamp - 1800
	end := timestamp

	filter := bson.D{
		{"isp", isp},
		{"$and", bson.A{
			bson.D{{"clientutc", bson.M{"$gte": start}}},
			bson.D{{"clientutc", bson.M{"$lte": end}}},
		}},
	}

	var original Sensor
	err := collection.FindOne(context.TODO(), filter).Decode(&original)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
	}
	fmt.Printf("Found a single document: %+v\n", original)
}

結果為剛剛插入的那一條數據,

Connected to MongoDB!
Found a single document: {ISP:China Mobile Clientutc:1598867346 DataByAPP:map[app1:{Latency:30.983999967575 RespCode:200 Url: Detail:{DNS:5.983999967575 TCP:10.983999967575 SSL:15.983999967575}}]}
Connection to MongoDB closed.

若要提取其中的數據,在querySensor()方法中略作改動,

original := make(map[string]interface{})
var sensorData Sensor
err := collection.FindOne(context.TODO(), filter).Decode(&original)
if err != nil {
	fmt.Printf("%s\n", err.Error())
} else {
	vstr, okstr := original["isp"].(string)
	if okstr {
	sensorData.ISP = vstr
	}
}
更新

這里仍然使用剛才的filter,並額外需要一個update

update := bson.M{
"$set": bson.M{
"isp": ispAfter,
},
}

使用collection.UpdateOne()更新單個Document記錄。

func UpdateSensor(collection *mongo.Collection, ispBefore string, ispAfter string) {
	//修改一條數據

	//篩選數據
	timestamp := time.Now().UTC().Unix()
	start := timestamp - 1800
	end := timestamp

	filter := bson.D{
		{"isp", ispBefore},
		{"$and", bson.A{
			bson.D{{"clientutc", bson.M{"$gte": start}}},
			bson.D{{"clientutc", bson.M{"$lte": end}}},
		}},
	}

	//更新內容
	update := bson.M{
		"$set": bson.M{
			"isp": ispAfter,
		},
	}

	updateResult, err := collection.UpdateOne(context.TODO(), filter, update)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Matched %v documents and updated %v documents.\n", updateResult.MatchedCount, updateResult.ModifiedCount)
}
刪除

使用collection.DeleteOne()來刪除一條記錄,仍然使用剛才的filter。

deleteResult, err := collection.DeleteOne(context.TODO(), filter)
if err != nil {
	fmt.Printf("%s\n", err.Error())
}

更多操作請見官方文檔。

參考鏈接

Mongo-Driver驅動包官方文檔
BSON包官方文檔
mongo包官方文檔
options包官方文檔


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM