banner
biuaxia

biuaxia

"万物皆有裂痕,那是光进来的地方。"
github
bilibili
tg_channel

【轉載】Go語言操作mongoDB

title: 【轉載】Go 語言操作 mongoDB
date: 2021-08-09 16:38:33
comment: false
toc: true
category:

  • Golang
    tags:
  • 轉載
  • Go
  • MongoDB
  • Mongo
  • 操作

本文轉載自:Go 語言操作 mongoDB | 李文周的博客


mongoDB 是目前比較流行的一個基於分佈式文件存儲的數據庫,它是一個介於關係數據庫和非關係數據庫 (NoSQL) 之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。

mongoDB 介紹#

mongoDB是目前比較流行的一個基於分佈式文件存儲的數據庫,它是一個介於關係數據庫和非關係數據庫 (NoSQL) 之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。

mongoDB 中將一條數據存儲為一個文檔(document),數據結構由鍵值(key-value)對組成。 其中文檔類似於我們平常編程中用到的 JSON 對象。 文檔中的字段值可以包含其他文檔,數組及文檔數組。

mongoDB 相關概念#

mongoDB 中相關概念與我們熟悉的 SQL 概念對比如下:

MongoDB 術語 / 概念說明對比 SQL 術語 / 概念
database數據庫database
collection集合table
document文檔row
field字段column
indexindex索引
primary key主鍵 MongoDB 自動將_id 字段設置為主鍵primary key

mongoDB 安裝#

我們這裡下載和安裝社區版,官方下載地址。 打開上述連接後,選擇對應的版本、操作系統平台(常見的平台均支持)和包類型,點擊 Download 按鈕下載即可。

這裡補充說明下,Windows 平台有ZIPMSI兩種包類型: * ZIP:壓縮文件版本 * MSI:可執行文件版本,點擊” 下一步” 安裝即可。

macOS 平台除了在該網頁下載TGZ文件外,還可以使用Homebrew安裝。

更多安裝細節可以參考官方安裝教程,裡面有LinuxmacOSWindows三大主流平台的安裝教程。

mongoDB 基本使用#

啟動 mongoDB 數據庫#

Windows#

"C:\Program Files\MongoDB\Server\4.2\bin\mongod.exe" --dbpath="c:\data\db"

Mac#

mongod --config /usr/local/etc/mongod.conf

brew services start [email protected]

啟動 client#

Windows#

"C:\Program Files\MongoDB\Server\4.2\bin\mongo.exe"

Mac#

mongo

數據庫常用命令#

show dbs;:查看數據庫

> show dbs;
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB

use q1mi;:切換到指定數據庫,如果不存在該數據庫就創建。

> use q1mi;
switched to db q1mi

db;:顯示當前所在數據庫。

> db;
q1mi

db.dropDatabase():刪除當前數據庫

> db.dropDatabase();
{ "ok" : 1 }

數據集常用命令#

db.createCollection(name,options):創建數據集

  • name:數據集名稱
  • options:可選參數,指定內存大小和索引。
> db.createCollection("student");
{ "ok" : 1 }

show collections;:查看當前數據庫中所有集合。

> show collections;
student

db.student.drop():刪除指定數據集

> db.student.drop()
true

文檔常用命令#

插入一條文檔:

> db.student.insertOne({name:"小王子",age:18});
{
	"acknowledged" : true,
	"insertedId" : ObjectId("5db149e904b33457f8c02509")
}

插入多條文檔:

> db.student.insertMany([
... {name:"張三",age:20},
... {name:"李四",age:25}
... ]);
{
	"acknowledged" : true,
	"insertedIds" : [
		ObjectId("5db14c4704b33457f8c0250a"),
		ObjectId("5db14c4704b33457f8c0250b")
	]
}

查詢所有文檔:

> db.student.find();
{ "_id" : ObjectId("5db149e904b33457f8c02509"), "name" : "小王子", "age" : 18 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250a"), "name" : "張三", "age" : 20 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250b"), "name" : "李四", "age" : 25 }

查詢 age>20 歲的文檔:

> db.student.find(
... {age:{$gt:20}}
... )
{ "_id" : ObjectId("5db14c4704b33457f8c0250b"), "name" : "李四", "age" : 25 }

更新文檔:

> db.student.update(
... {name:"小王子"},
... {name:"老王子",age:98}
... );
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.student.find()
{ "_id" : ObjectId("5db149e904b33457f8c02509"), "name" : "老王子", "age" : 98 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250a"), "name" : "張三", "age" : 20 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250b"), "name" : "李四", "age" : 25 }

刪除文檔:

> db.student.deleteOne({name:"李四"});
{ "acknowledged" : true, "deletedCount" : 1 }
> db.student.find()
{ "_id" : ObjectId("5db149e904b33457f8c02509"), "name" : "老王子", "age" : 98 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250a"), "name" : "張三", "age" : 20 }

命令實在太多,更多命令請參閱官方文檔:shell 命令官方文檔:CRUD 操作

Go 語言操作 mongoDB#

我們這裡使用的是官方的驅動包,當然你也可以使用第三方的驅動包(如 mgo 等)。 mongoDB 官方版的 Go 驅動發布的比較晚(2018 年 12 月 13 號)。

安裝 mongoDB Go 驅動包#

go get github.com/mongodb/mongo-go-driver

透過 Go 代碼連接 mongoDB#

package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
	// 設置客戶端連接配置
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")

	// 連接到MongoDB
	client, err := mongo.Connect(context.TODO(), clientOptions)
	if err != nil {
		log.Fatal(err)
	}

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

連接上 MongoDB 之後,可以透過下面的語句處理我們上面的 q1mi 數據庫中的 student 數據集了:

// 指定獲取要操作的數據集
collection := client.Database("q1mi").Collection("student")

處理完任務之後可以透過下面的命令斷開與 MongoDB 的連接:

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

連接池模式#

import (
	"context"
	"time"

	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

func ConnectToDB(uri, name string, timeout time.Duration, num uint64) (*mongo.Database, error) {
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	o := options.Client().ApplyURI(uri)
	o.SetMaxPoolSize(num)
	client, err := mongo.Connect(ctx, o)
	if err != nil {
		return nil, err
	}

	return client.Database(name), nil
}

BSON#

MongoDB 中的 JSON 文檔存儲在名為 BSON (二進制編碼的 JSON) 的二進制表示中。與其他將 JSON 數據存儲為簡單字符串和數字的數據庫不同,BSON 編碼擴展了 JSON 表示,使其包含額外的類型,如 int、long、date、浮點數和 decimal128。這使得應用程序更容易可靠地處理、排序和比較數據。

連接 MongoDB 的 Go 驅動程序中有兩大類型表示 BSON 數據:DRaw

類型D家族被用來簡潔地構建使用本地 Go 類型的 BSON 對象。這對於構造傳遞給 MongoDB 的命令特別有用。D家族包括四類:

  • D:一個 BSON 文檔。這種類型應該在順序重要的情況下使用,比如 MongoDB 命令。
  • M:一張無序的 map。它和 D 是一樣的,只是它不保持順序。
  • A:一個 BSON 數組。
  • E:D 裡面的一个元素。

要使用 BSON,需要先導入下面的包:

import "go.mongodb.org/mongo-driver/bson"

下面是一個使用 D 類型構建的過濾器文檔的例子,它可以用來查找 name 字段與’張三’或’李四’匹配的文檔:

bson.D{{
	"name",
	bson.D{{
		"$in",
		bson.A{"張三", "李四"},
	}},
}}

Raw類型家族用於驗證字節切片。你還可以使用Lookup()從原始類型檢索單個元素。如果你不想要將 BSON 反序列化成另一種類型的開銷,那麼這是非常有用的。這個教程我們將只使用 D 類型。

CRUD#

我們現在 Go 代碼中定義一個Studet類型如下:

type Student struct {
	Name string
	Age int
}

接下來,創建一些Student類型的值,準備插入到數據庫中:

s1 := Student{"小紅", 12}
s2 := Student{"小蘭", 10}
s3 := Student{"小黃", 11}

插入文檔#

使用collection.InsertOne()方法插入一條文檔記錄:

insertResult, err := collection.InsertOne(context.TODO(), s1)
if err != nil {
	log.Fatal(err)
}

fmt.Println("Inserted a single document: ", insertResult.InsertedID)

使用collection.InsertMany()方法插入多條文檔記錄:

students := []interface{}{s2, s3}
insertManyResult, err := collection.InsertMany(context.TODO(), students)
if err != nil {
	log.Fatal(err)
}
fmt.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs)

更新文檔#

updateone()方法允許你更新單個文檔。它需要一個篩選器文檔來匹配數據庫中的文檔,並需要一個更新文檔來描述更新操作。你可以使用bson.D類型來構建篩選文檔和更新文檔:

filter := bson.D{{"name", "小蘭"}}

update := bson.D{
	{"$inc", bson.D{
		{"age", 1},
	}},
}

接下來,就可以透過下面的語句找到小蘭,給他增加一歲了:

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)

查找文檔#

要找到一個文檔,你需要一個 filter 文檔,以及一個指向可以將結果解碼為其值的指針。要查找單個文檔,使用collection.FindOne()。這個方法返回一個可以解碼為值的結果。

我們使用上面定義過的那個 filter 來查找姓名為’小蘭’的文檔。

// 創建一個Student變量用來接收查詢的結果
var result Student
err = collection.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Found a single document: %+v\n", result)

要查找多個文檔,請使用collection.Find()。此方法返回一個游標。游標提供了一個文檔流,你可以透過它一次迭代和解碼一個文檔。當游標用完之後,應該關閉游標。下面的示例將使用options包設置一個限制以便只返回兩個文檔。

// 查詢多個
// 將選項傳遞給Find()
findOptions := options.Find()
findOptions.SetLimit(2)

// 定義一個切片用來存儲查詢結果
var results []*Student

// 把bson.D{{}}作為一個filter來匹配所有文檔
cur, err := collection.Find(context.TODO(), bson.D{{}}, findOptions)
if err != nil {
	log.Fatal(err)
}

// 查找多個文檔返回一個光標
// 遍歷游標允許我們一次解碼一個文檔
for cur.Next(context.TODO()) {
	// 創建一個值,將單個文檔解碼為該值
	var elem Student
	err := cur.Decode(&elem)
	if err != nil {
		log.Fatal(err)
	}
	results = append(results, &elem)
}

if err := cur.Err(); err != nil {
	log.Fatal(err)
}

// 完成後關閉游標
cur.Close(context.TODO())
fmt.Printf("Found multiple documents (array of pointers): %#v\n", results)

刪除文檔#

最後,可以使用 collection.DeleteOne()collection.DeleteMany() 刪除文檔。如果你傳遞 bson.D{\{\}} 作為過濾器參數,它將匹配數據集中的所有文檔。還可以使用 collection.drop() 刪除整個數據集。

// 刪除名字是小黃的那個
deleteResult1, err := collection.DeleteOne(context.TODO(), bson.D{{"name","小黃"}})
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Deleted %v documents in the trainers collection\n", deleteResult1.DeletedCount)
// 刪除所有
deleteResult2, err := collection.DeleteMany(context.TODO(), bson.D{{}})
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Deleted %v documents in the trainers collection\n", deleteResult2.DeletedCount)

更多方法請查閱官方文檔

參考鏈接#

https://docs.mongodb.com/manual/mongo/

https://www.mongodb.com/blog/post/mongodb-go-driver-tutorial

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。