Golang学习日志 ━━ mongo-go-driver连接mongodb数据库

mongo-go-driver 为官方出品,网上盛行的 mgo 驱动已经停止更新很久。

初始化

定义一个结构体Trainer,后面操作会用到

package main

import (
    "context"
    "fmt"
    "log"

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

// You will be using this Trainer type later in the program
type Trainer struct {
    Name string
    Age  int
    City string
}

func main() {
    // Rest of the code will go here
}

接入

使用 mongo.Connect() 连接,需要提供两个参数:

  1. context 上下文
  2. clientOptions 详细配置,详细 options 包说明点击 options Documentation
// Set client options
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")

// Connect to MongoDB
client, err := mongo.Connect(context.TODO(), clientOptions)

if err != nil {
	log.Fatal(err)
}

// Check the connection
err = client.Ping(context.TODO(), nil)

if err != nil {
	log.Fatal(err)
}

fmt.Println("Connected to MongoDB!")

库和集合

定位到 TEST 库的 trainers 集合

collection := client.Database("TEST").Collection("trainers")

BSON

mongodb用bson来实现各种数据库命令。

Go Driver中用D系列类型和Raw系列类型表示来BSON数据。

  • D系列类型 使用原生Go类型构建BSON对象,其包含4种类型:
    – D:一个BSON文档。这个类型需要用在顺序很重要的场景, 比如MongoDB命令。
    – M: 一个无序map。 它和D是一样的, 除了它不保留顺序。
    – A: 一个BSON数组。
    – E: 在D里面的一个单一的子项。

本例是使用D类型构建的过滤文档, 类似关系型数据库中的 where name='Alice' or name='Bob' ,查询name字段匹配“Alice”或者“Bob”的文档:

bson.D{{
    "name", 
    bson.D{{
        "$in", 
        bson.A{"Alice", "Bob"}
    }}
}}
  • Raw系列类型 被用来验证bytes类型的slice, 也可以从Raw类型使用 Lookup() 获得单个的子项, 这在你不想要unmarshall某个BSON到另一个类型的时候很有用。

插入

  • 先准备好一些数据:
ash := Trainer{"Ash", 10, "Pallet Town"}
misty := Trainer{"Misty", 10, "Cerulean City"}
brock := Trainer{"Brock", 15, "Pewter City"}
  • collection.InsertOne() 插入单条
insertResult, err := collection.InsertOne(context.TODO(), ash)
if err != nil {
	log.Fatal(err)
}

fmt.Println("Inserted a single document: ", insertResult.InsertedID)
  • collection.InsertMany() 插入多条
trainers := []interface{}{misty, brock}

insertManyResult, err := collection.InsertMany(context.TODO(), trainers)
if err != nil {
	log.Fatal(err)
}

fmt.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs)

更新

  • 准备好条件
filter := bson.D{{"name", "Ash"}}

update := bson.D{
    {"$inc", bson.D{
        {"age", 1},
    }},
}
  • collection.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)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.UpdateMany() 更新多条

  • ReplaceOne() 替换单条
    replace替换整条文档,update用于更新某条文档对应字段

查询

  • collection.FindOne() 查询单条
    需要一个查询条件及一个指针在它里边保存结果的解码。
// create a value into which the result can be decoded
var result Trainer

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 包来设定一些操作选项,比如设定返回文档数量值为2条。
// Pass these options to the Find method
findOptions := options.Find()
findOptions.SetLimit(2)

// Here's an array in which you can store the decoded documents
var results []*Trainer

// Passing bson.D{{}} as the filter matches all documents in the collection
cur, err := collection.Find(context.TODO(), bson.D{{}}, findOptions)
if err != nil {
	log.Fatal(err)
}

// Finding multiple documents returns a cursor
// Iterating through the cursor allows us to decode documents one at a time
for cur.Next(context.TODO()) {

	// create a value into which the single document can be decoded
	var elem Trainer
	err := cur.Decode(&elem)
	if err != nil {
		log.Fatal(err)
	}

	results = append(results, &elem)
}

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

// Close the cursor once finished
cur.Close(context.TODO())

fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)

删除

  • collection.DeleteOne() 删除单条

  • collection.DeleteMany() 删除多条
    bson.D{{}} 参数表示不限,用在此处即表示全部删除

deleteResult, err := collection.DeleteMany(context.TODO(), bson.D{{}})
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Deleted %v documents in the trainers collection\n", deleteResult.DeletedCount)
  • collection.Drop() 删除集合

关闭

client.Disconnect() 主动关闭连接,这也是传统习惯

err = client.Disconnect(context.TODO())

if err != nil {
	log.Fatal(err)
}
fmt.Println("Connection to MongoDB closed.")

在这里插入图片描述

参考:
mongo-go-driver Document
从mgo到mongo driver,更换支持mongo db的驱动
mgo和mongo-go-driver使用心得比较
MongoDB Go Driver使用帮助文档
理解Go的Context机制
Golang 连接 MongoDB使用连接池
MongoDB 提升性能的18原则(开发设计阶段)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、为什么会做这个封装 提供CURD,事务等基础功能封装,提高开发效率: golang提供了很多的类库下载,但是并不方便直接使用,或者重复使用的方法没有基于业务层的封装,调用极其繁琐反复,笔者在使用时深有感受;故封装了连接池数据库常用功能(增删改查,事务执行,管道聚合操作),并提供具体的使用和详细的demo,代码块注释和readme.txt文件中简要记录笔者从0-1的踩坑总结 二、这个目录涉及哪些主要包,提供哪些功能 基于Mgo,Mongo-go-driver这两个比较常用的MongoDB基础库,做了连接池初始化,model层服务封装,提供:初始化MongoDB连接池复用, MongoDB集合(类似MySQL的数据表)的增、删、改、查,事务、管道操作、聚合操作、mongoShell原生命令执行、多表关联查询 等功能;另外明确一下,此包是笔者为了提供开发效率,基于上述基础库的二次功能封装,可能存在不足,如有异议,欢迎交流 三、使用本工具代码块,可以帮助到你什么 使用须知: 1. 首先本代码块是基于企业业务的封装,具有普遍使用性,涵盖了绝大部分应用场景 2. 适合MongoDB初学者:降低学习成本,底层实现对使用者透明,操作简单,提升开发效率 3. 适合从RDB(关系型数据库)刚转用MongoDB的使用者:此封装照顾了 MySQL等RDB使用者的用户习惯,返回的数据格式和ORM(关系映射数据格式)基本一致, 4. 照顾了 PHP 转 Golang的使用者,笔者以前也做过PHP,故使用过PHP的YII2,Laravel,ThinkPHP的开发者也能很清晰的看懂封装逻辑 5. 适合还未参加工作的同学,这些代码来自企业的基础功能包,是真实的工作代码 6. 本文件目录为功能代码块,可参考笔者的一篇MongoDB相关的博客使用,包含作者踩过的一些坑,可帮助初学使用者加深理解,内容涉及MongoDB相关(安装,常识,Mysql和MongoDB的基本对比,原生mongo shell命令...) 四、下载后,请先阅读readme.txt,如有异议,欢迎交流

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值