Go:mongo

时间:May 12, 2020 分类:

目录:

官方的驱动包github.com/mongodb/mongo-go-driver,也可以使用mgo等

通过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!")
}

连接到mongo上可以获取要操作的数据集

collection := client.Database("whytest").Collection("User")

处理完成后断开连接

// 断开连接
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存储为简单字符串和数字的数据库不同,Bson扩展了Json,包含了int,long,date,浮点等数据类型

MongoDB的Go驱动中有两大类型来表示Bson数据,D和Raw

D是简洁的构建使用本地Go类型的Bson对象,用于构建MongoDB命令,D家族包含4类

  • D:一个BSON文档。这种类型应该在顺序重要的情况下使用,比如MongoDB命令。
  • M:一张无序的map。它和D是一样的,只是它不保持顺序。
  • A:一个BSON数组。
  • E:D里面的一个元素。

使用Bson需要导入

import "go.mongodb.org/mongo-driver/bson"
bson.D{{
    "name",
    bson.D{{
        "$in",
        bson.A{"why", "pqt"},
    }},
}}

CURD

type Student struct {
    Name string
    Age int
}

插入文档

使用collection.InsertOne()插入单条数据

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

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

使用collection.InsertMany()插入多条数据

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

查找文档

查找单一文档使用collection.FindOne()

// 创建一个Student变量用来接收查询的结果
var result Student

filter := bson.D{{"name", "why"}}

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(),返回的是一个游标,游标提供文档流,可以进行迭代和解码,当游标使用完需要关闭

// 查询多个
// 将选项传递给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)

更新文档

使用bson.D构建筛选文档和更新文档

filter := bson.D{{"name", "lyp"}}

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

使用UpdateOne进行更新

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()和collection.DeleteMany()删除文档

// 删除名字是小黄的那个
deleteResult1, err := collection.DeleteOne(context.TODO(), bson.D{{"name","mb"}})
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)

完整示例

package main

import (
    "context"
    "fmt"
    "log"

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

)

type Features struct {
    S string
}

type User struct {
    ID       int
    Features *[]Features
}

func main() {
    // 设置客户端连接配置
    clientOptions := options.Client().ApplyURI("mongodb://172.20.30.19:8290")

    // 连接到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!")

    f1 := Features{S:"s1"}
    f2 := Features{S:"s2"}
    s := []Features{f1, f2}
    u := User{1, &s}
    c := client.Database("whytest").Collection("user")
    c.InsertOne(context.TODO(), u)

    fmt.Println("Connected to MongoDB!")
}