发布于 2026-01-06 4 阅读
0

MongoDB Golang Driver Tutorial DEV's Worldwide Show and Tell Challenge Presented by Mux: Pitch Your Projects!

MongoDB Golang 驱动程序教程

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

多年来,MongoDB 一直依赖mgoglobalsign/mgo等社区驱动程序。去年,MongoDB宣布正在构建自己的解决方案。去年三月,他们发布了1.0.0 版本,那么让我们来看看如何使用官方驱动程序执行一些常规操作。

首先,你需要使用 go get 下载驱动程序。

go.mongodb.org/mongo-driver/mongo
Enter fullscreen mode Exit fullscreen mode

假设您的 MongoDB 安装使用的是默认设置,那么您的方法应该如下所示:

package main

import (
    "context"
    "log"

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

func GetClient() *mongo.Client {
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    client, err := mongo.NewClient(clientOptions)
    if err != nil {
        log.Fatal(err)
    }
    err = client.Connect(context.Background())
    if err != nil {
        log.Fatal(err)
    }
    return client
}
Enter fullscreen mode Exit fullscreen mode

为了测试与 MongoDB 的连接,我们可以调用一个名为 Ping 的函数,并检查它是否返回任何错误。如果没有错误,则表示连接成功。

func main() {
    c := GetClient()
    err := c.Ping(context.Background(), readpref.Primary())
    if err != nil {
        log.Fatal("Couldn't connect to the database", err)
    } else {
        log.Println("Connected!")
    }
}
Enter fullscreen mode Exit fullscreen mode

接下来,我创建了一个名为“database”的数据库civilact和一个集合heroes,并添加了以下文档:

{ 
    "_id" : ObjectId("5d0574824d9f7ff15e989171"), 
    "name" : "Tony Stark", 
    "alias" : "Iron Man", 
    "signed" : true
}
{ 
    "_id" : ObjectId("5d0574d74d9f7ff15e989172"), 
    "name" : "Steve Rodgers", 
    "alias" : "Captain America", 
    "signed" : false
}
{ 
    "_id" : ObjectId("5d0574e94d9f7ff15e989173"), 
    "name" : "Vision", 
    "alias" : "Vision", 
    "signed" : true
}
{ 
    "_id" : ObjectId("5d0575344d9f7ff15e989174"), 
    "name" : "Clint Barton", 
    "alias" : "Hawkeye", 
    "signed" : false
}
Enter fullscreen mode Exit fullscreen mode

为了更好地处理这些文档,我们最好创建一个结构体来表示所有字段及其 JSON 名称。

type Hero struct {
    Name   string `json:"name"`
    Alias  string `json:"alias"`
    Signed bool   `json:"signed"`
}
Enter fullscreen mode Exit fullscreen mode

现在我们创建一个方法,该方法返回所有英雄,它接受两个参数:MongoDB 客户端和一个表示筛选条件的 bson.M 对象。如果筛选条件为空,则该方法返回所有文档。

import (
    "context"
    "log"

    "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/readpref"
)

func ReturnAllHeroes(client *mongo.Client, filter bson.M) []*Hero {
    var heroes []*Hero
    collection := client.Database("civilact").Collection("heroes")
    cur, err := collection.Find(context.TODO(), filter)
    if err != nil {
        log.Fatal("Error on Finding all the documents", err)
    }
    for cur.Next(context.TODO()) {
        var hero Hero
        err = cur.Decode(&hero)
        if err != nil {
            log.Fatal("Error on Decoding the document", err)
        }
        heroes = append(heroes, &hero)
    }
    return heroes
}
Enter fullscreen mode Exit fullscreen mode

具体构成如下:

  1. 创建一个collection表示数据库中集合的元素;
  2. 要求collection返回一个包含基于筛选条件的元素的游标(在这种情况下,筛选条件为空,因此将返回所有元素);
  3. 遍历此光标并将每个文档解码为 Hero 类型;
  4. 将解码后的英雄添加到heroes数组中。

如果在主函数内部运行,返回结果将是:

heroes := ReturnAllHeroes(c, bson.M{})
for _, hero := range heroes {
    log.Println(hero.Name, hero.Alias, hero.Signed)
}

2019/06/15 21:07:00 Tony Stark Iron Man true
2019/06/15 21:07:00 Steve Rodgers Captain America false
2019/06/15 21:07:00 Vision Vision true
2019/06/15 21:07:00 Clint Barton Hawkeye false
Enter fullscreen mode Exit fullscreen mode

要只检索签署了索科维亚协议的英雄,我们只需要更改筛选条件。

heroes := ReturnAllHeroes(c, bson.M{"signed": true})

2019/06/15 21:18:04 Tony Stark Iron Man true
2019/06/15 21:18:04 Vision Vision true
Enter fullscreen mode Exit fullscreen mode

如果只想检索一个英雄,我们的新方法如下:

func ReturnOneHero(client *mongo.Client, filter bson.M) Hero {
    var hero Hero
    collection := client.Database("civilact").Collection("heroes")
    documentReturned := collection.FindOne(context.TODO(), filter)
    documentReturned.Decode(&hero)
    return hero
}
Enter fullscreen mode Exit fullscreen mode

通话内容如下:

    hero := ReturnOneHero(c, bson.M{"name": "Vision"})
    log.Println(hero.Name, hero.Alias, hero.Signed)

    2019/06/15 22:55:44 Vision Vision true
Enter fullscreen mode Exit fullscreen mode

现在,为了扩充我们的英雄阵容,例如加入奇异博士,新的方法如下:

func InsertNewHero(client *mongo.Client, hero Hero) interface{} {
    collection := client.Database("civilact").Collection("heroes")
    insertResult, err := collection.InsertOne(context.TODO(), hero)
    if err != nil {
        log.Fatalln("Error on inserting new Hero", err)
    }
    return insertResult.InsertedID
}
Enter fullscreen mode Exit fullscreen mode

这就是我们的方法将如何被之前的方法使用和检查的方式ReturnOneHero

hero = Hero{Name: "Stephen Strange", Alias: "Doctor Strange", Signed: true}
insertedID := InsertNewHero(c, hero)
log.Println(insertedID)
hero = ReturnOneHero(c, bson.M{"alias": "Doctor Strange"})
log.Println(hero.Name, hero.Alias, hero.Signed)
Enter fullscreen mode Exit fullscreen mode

太棒了!我们把一位至尊法师加入了我们的英雄收藏,但如果他不喜欢,要求我们把他从收藏中移除怎么办?嗯,这就是为什么我们需要一个RemoveOneHero方法。

func RemoveOneHero(client *mongo.Client, filter bson.M) int64 {
    collection := client.Database("civilact").Collection("heroes")
    deleteResult, err := collection.DeleteOne(context.TODO(), filter)
    if err != nil {
        log.Fatal("Error on deleting one Hero", err)
    }
    return deleteResult.DeletedCount
}
Enter fullscreen mode Exit fullscreen mode

这就是我们的检查方法:

heroesRemoved := RemoveOneHero(c, bson.M{"alias": "Doctor Strange"})
log.Println("Heroes removed count:", heroesRemove
hero = ReturnOneHero(c, bson.M{"alias": "Doctor Strange"})
log.Println("Is Hero empty?", hero == Hero{ })
Enter fullscreen mode Exit fullscreen mode

最后,我们假设鹰眼改变了主意,现在想要签署协议。那么,让我们来制定UpdateHero方法。

func UpdateHero(client *mongo.Client, updatedData bson.M, filter bson.M) int64 {
    collection := client.Database("civilact").Collection("heroes")
    atualizacao := bson.D{ {Key: "$set", Value: updatedData} }
    updatedResult, err := collection.UpdateOne(context.TODO(), filter, atualizacao)
    if err != nil {
        log.Fatal("Error on updating one Hero", err)
    }
    return updatedResult.ModifiedCount
}
Enter fullscreen mode Exit fullscreen mode

好了!常规的CRUD操作已经讲解完毕,我们的英雄们可以决定自己的命运了。
所有示例代码都可以在这里找到,本教程也发布在我的博客上。这是驱动程序的官方代码库和官方文档。

如果您有任何问题、建议或发现我的错误,请随时与我联系。

文章来源:https://dev.to/eduardohitek/mongodb-golang-driver-tutorial-49e5