MongoDB的Go语言操作示例总结

目录

前提条件

连接到MongoDB

简单示例

插入文档

查询文档

查询单个文档

查询多个文档

更新文档

更新单个文档

更新多个文档

删除文档

删除单个文档

删除多个文档

聚合管道

常见聚合操作符

$match

$group

$project

$sort

$limit

$skip

$lookup

$unwind

 示例

Go中的聚合管道使用示例

完整示例


MongoDB是一个流行的NoSQL数据库,而Go语言是一种简洁、高效的编程语言。这两者组合可以给应用程序提供强大的数据存储和操作能力。

在Go语言中操作MongoDB需要使用官方MongoDB Go驱动程序。以下总结下在Go语言中使用MongoDB数据库涉及到的一些基本操作。如插入文档、查询文档,如何在Go中进行连接、增、删、改、查等常用操作,以及如何使用聚合管道进行复杂查询。

前提条件

1.确保您已经安装了MongoDB和Go语言环境。

2.安装MongoDB Go驱动程序,可以使用go get命令来安装:

go get go.mongodb.org/mongo-driver/mongo

新建个项目文件夹,在下面新建main.go文件,执行yourprj换成你的包名。

go mod init yourprj

不用非得执行上面的go get 方式,直接项目代码中import需要的包,执行go mod tidy即可。 

连接到MongoDB

首先,需要连接到MongoDB实例:

package main

import (
    "context"
    "log"
    "time"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    client, err := mongo.Connect(ctx, clientOptions)
    if err != nil {
        log.Fatal(err)
    }

    defer func() {
        if err = client.Disconnect(ctx); err != nil {
            log.Fatal(err)
        }
    }()

    // 获取数据库和集合
    db := client.Database("testDB")
    collection := db.Collection("users")

    // 接下来的操作在这里进行
}

注意事项

上面的连接url参数针对未开启认证的可以连接成功,若开启有用户名密码验证则需要类似如下的连接参数:

"mongodb://user:yourpwd@localhost:27017/?tls=false&authSource=test1"

简单示例

package main

import (
	"context"
	"fmt"
	"log"
  "time"

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

type User struct {
	Name  string `json:"name"`
	Email string `json:"email"`
  Age   int    `bson:"Agg"`
}
// ... 上面User结构体定义 ...

func main() {
	// 连接MongoDB
	clientOptions := options.Client().ApplyURI("mongodb://test1:111111@localhost:27017/?tls=false&authSource=test1")
	client, err := mongo.Connect(context.Background(), clientOptions)
	if err != nil {
		log.Fatal(err)
	}
	defer func() {
		if err = client.Disconnect(context.Background()); err != nil {
			log.Fatal(err)
		}
	}()

	// 解析JSON字符串到User结构体(假设已经完成)
	user := User{Name: "Alice", Email: "alice@example.com",Age:22}

	// 选择数据库和集合
	collection := client.Database("test1").Collection("users")

	// 插入文档
	insertResult, err := collection.InsertOne(context.TODO(), user)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Inserted ID:", insertResult.InsertedID)
 
	// 插入文档
	doc := bson.D{{"age", 30},{"name", "Alice2"},  {"createdAt", time.Now()}}
	insertResult, err = collection.InsertOne(context.TODO(), doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Inserted ID:", insertResult.InsertedID)

	// 更新文档
	filter := bson.D{{"name", "Alice1"}}
	update := bson.D{{"$set", bson.D{{"age", 31}}}}
	updateResult, err := collection.UpdateOne(context.TODO(), filter, update)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Modified Count:", updateResult.ModifiedCount)

	// 删除文档
  filter = bson.D{{"age", 22}}
	deleteResult, err := collection.DeleteOne(context.TODO(), filter)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Deleted Count:", deleteResult.DeletedCount)

	// 查找单个文档
	var singleResult bson.M
	err = collection.FindOne(context.TODO(), bson.D{}).Decode(&singleResult)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Single Document:", singleResult)

	// 查找所有文档
	cursor, err := collection.Find(context.TODO(), bson.D{})
	if err != nil {
		log.Fatal(err)
	}
	defer cursor.Close(context.TODO())
 
	for cursor.Next(context.TODO()) {
		var result bson.M
		err := cursor.Decode(&result)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println("Document:", result)
	}

	// 过滤查找
	filteredCursor, err := collection.Find(context.TODO(), bson.D{{"age", bson.D{{"$gt", 31}}}})
	if err != nil {
		log.Fatal(err)
	}
	defer filteredCursor.Close(context.TODO())
 
	for filteredCursor.Next(context.TODO()) {
		var filteredDoc bson.M
		err := filteredCursor.Decode(&filteredDoc)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println("Filtered Document:", filteredDoc)
	}
}

插入文档

    user := map[string]interface{}{"name": "Alice", "age": 29}
    _, err = collection.InsertOne(ctx, user)
    if err != nil {
        log.Fatal(err)
    }

    users := []interface{}{
        map[string]interface{}{"name": "Bob", "age": 31},
        map[string]interface{}{"name": "Charlie", "age": 25},
    }
    _, err = collection.InsertMany(ctx, users)
    if err != nil {
        log.Fatal(err)
    }

查询文档

查询单个文档

    var result map[string]interface{}
    filter := map[string]interface{}{"name": "Alice"}
    err = collection.FindOne(ctx, filter).Decode(&result)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(result)

查询多个文档

    filter = map[string]interface{}{"age": map[string]interface{}{"$gte": 30}}
    cursor, err := collection.Find(ctx, filter)
    if err != nil {
        log.Fatal(err)
    }
    defer cursor.Close(ctx)

    var results []map[string]interface{}
    if err = cursor.All(ctx, &results); err != nil {
        log.Fatal(err)
    }
    for _, result := range results {
        log.Println(result)
    }

更新文档

更新单个文档

    filter = map[string]interface{}{"name": "Bob"}
    update := map[string]interface{}{"$set": map[string]interface{}{"age": 32}}
    _, err = collection.UpdateOne(ctx, filter, update)
    if err != nil {
        log.Fatal(err)
    }

更新多个文档

    filter = map[string]interface{}{"age": map[string]interface{}{"$lt": 30}}
    update = map[string]interface{}{"$set": map[string]interface{}{"valid": true}}
    _, err = collection.UpdateMany(ctx, filter, update)
    if err != nil {
        log.Fatal(err)
    }

删除文档

删除单个文档

    filter = map[string]interface{}{"name": "Charlie"}
    _, err = collection.DeleteOne(ctx, filter)
    if err != nil {
        log.Fatal(err)
    }

删除多个文档

    filter = map[string]interface{}{"valid": true}
    _, err = collection.DeleteMany(ctx, filter)
    if err != nil {
        log.Fatal(err)
    }

聚合管道

MongoDB的聚合管道(Aggregation Pipeline)是一种强大的数据处理工具,它允许用户对集合中的文档执行一系列数据转换和处理操作。聚合管道由一系列的阶段(stages)组成,每个阶段会对输入的文档进行一定的操作并将结果传递到下一个阶段。

每个阶段都是一个管道操作符(pipeline operator),共同组成一个管道。常见的管道操作符包括 $match$group$project$sort$limit 等。

聚合管道的基本结构
聚合管道通过 aggregate 方法来执行。其基本结构如下:

db.collection.aggregate([
    { $stage1: {...} },
    { $stage2: {...} },
    ...
])

常见聚合操作符

以下是一些常见的聚合操作符及其作用:

$match

用来过滤文档,其作用类似于 SQL 中的 WHERE 子句。

{ $match: { age: { $gte: 25 } } }

$group

将文档分组,并可以对每个分组应用聚合函数,如计数、求和、平均值等。

{ $group: { _id: "$age", count: { $sum: 1 } } }

$project

用于重新塑造文档,可以用来包括、排除或重命名字段。

{ $project: { name: 1, age: 1, _id: 0 } }

$sort

对文档进行排序。

{ $sort: { age: -1 } }

$limit

限制返回的文档数量。

{ $limit: 10 }

$skip

跳过指定数量的文档。

{ $skip: 5 }

$lookup

用于执行左外连接。

{ $lookup: { from: "otherCollection", localField: "fieldA", foreignField: "fieldB", as: "newField" } }

$unwind

将数组类型字段中的每个值拆分成单独的文档。

{ $unwind: "$arrayField" }

 示例

下面是一个使用 aggregate 方法的具体示例,展示了如何使用聚合管道操作符:

db.users.aggregate([
    // 匹配 age 大于等于 25 的文档
    { $match: { age: { $gte: 25 } } },
    // 按照 age 分组,并计算每个分组的数量
    { $group: { _id: "$age", count: { $sum: 1 } } },
    // 按照 count 字段降序排序
    { $sort: { count: -1 } },
    // 仅保留前 5 个结果
    { $limit: 5 }
])

Go中的聚合管道使用示例

package main

import (
    "context"
    "log"
    "time"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    client, err := mongo.Connect(ctx, clientOptions)
    if err != nil {
        log.Fatal(err)
    }

    defer func() {
        if err = client.Disconnect(ctx); err != nil {
            log.Fatal(err)
        }
    }()

    db := client.Database("testDB")
    collection := db.Collection("users")

    pipeline := mongo.Pipeline{
        {{Key: "$match", Value: map[string]interface{}{"age": map[string]interface{}{"$gte": 25}}}},
        {{Key: "$group", Value: map[string]interface{}{"_id": "$age", "count": map[string]interface{}{"$sum": 1}}}},
        {{Key: "$sort", Value: map[string]interface{}{"count": -1}}},
        {{Key: "$limit", Value: int32(5)}},
    }

    cursor, err := collection.Aggregate(ctx, pipeline)
    if err != nil {
        log.Fatal(err)
    }
    defer cursor.Close(ctx)

    var results []map[string]interface{}
    if err = cursor.All(ctx, &results); err != nil {
        log.Fatal(err)
    }

    for _, result := range results {
        log.Println(result)
    }
}
    pipeline := mongo.Pipeline{
        {{Key: "$match", Value: map[string]interface{}{"age": map[string]interface{}{"$gte": 25}}}},
        {{Key: "$group", Value: map[string]interface{}{"_id": "$age", "count": map[string]interface{}{"$sum": 1}}}},
    }

    cursor, err = collection.Aggregate(ctx, pipeline)
    if err != nil {
        log.Fatal(err)
    }
    defer cursor.Close(ctx)

    var pipelineResults []map[string]interface{}
    if err = cursor.All(ctx, &pipelineResults); err != nil {
        log.Fatal(err)
    }
    for _, result := range pipelineResults {
        log.Println(result)
    }

完整示例

package main

import (
    "context"
    "log"
    "time"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    client, err := mongo.Connect(ctx, clientOptions)
    if err != nil {
        log.Fatal(err)
    }
    
    defer func() {
        if err = client.Disconnect(ctx); err != nil {
            log.Fatal(err)
        }
    }()

    db := client.Database("testDB")
    collection := db.Collection("users")

    // 插入文档
    collection.InsertOne(ctx, map[string]interface{}{"name": "Alice", "age": 29})
    collection.InsertMany(ctx, []interface{}{
        map[string]interface{}{"name": "Bob", "age": 31},
        map[string]interface{}{"name": "Charlie", "age": 25},
    })

    // 查询单个文档
    var result map[string]interface{}
    collection.FindOne(ctx, map[string]interface{}{"name": "Alice"}).Decode(&result)
    log.Println(result)

    // 查询多个文档
    cursor, err := collection.Find(ctx, map[string]interface{}{"age": map[string]interface{}{"$gte": 30}})
    if err != nil {
        log.Fatal(err)
    }
    defer cursor.Close(ctx)

    var results []map[string]interface{}
    cursor.All(ctx, &results)
    for _, res := range results {
        log.Println(res)
    }

    // 更新文档
    collection.UpdateOne(ctx, map[string]interface{}{"name": "Bob"}, map[string]interface{}{"$set": map[string]interface{}{"age": 32}})
    collection.UpdateMany(ctx, map[string]interface{}{"age": map[string]interface{}{"$lt": 30}}, map[string]interface{}{"$set": map[string]interface{}{"valid": true}})
    
    // 删除文档
    collection.DeleteOne(ctx, map[string]interface{}{"name": "Charlie"})
    collection.DeleteMany(ctx, map[string]interface{}{"valid": true})
    
    // 聚合管道
    pipeline := mongo.Pipeline{
        {{Key: "$match", Value: map[string]interface{}{"age": map[string]interface{}{"$gte": 25}}}},
        {{Key: "$group", Value: map[string]interface{}{"_id": "$age", "count": map[string]interface{}{"$sum": 1}}}},
    }
    
    cursor, err = collection.Aggregate(ctx, pipeline)
    if err != nil {
        log.Fatal(err)
    }
    defer cursor.Close(ctx)
    
    var pipelineResults []map[string]interface{}
    cursor.All(ctx, &pipelineResults)
    for _, res := range pipelineResults {
        log.Println(res)
    }
}
  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 在使用 Go 语言操作 MongoDB 数据库时,可以使用事务来管理写入、删除等操作。 首先,在开启事务之前,需要先获取一个 MongoDB 连接: ``` client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) if err != nil { // handle error } ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) defer cancel() err = client.Connect(ctx) if err != nil { // handle error } ``` 然后,可以使用 `client.Database()` 方法来获取数据库的句柄,再使用 `Database.StartSession()` 方法来开启一个事务: ``` sess, err := client.Database("mydb").StartSession() if err != nil { // handle error } defer sess.EndSession(ctx) ``` 在事务中执行写入、删除等操作时,需要使用 `Session.WithTransaction()` 方法来包裹这些操作,并使用 `Session.AbortTransaction()` 方法来回滚事务: ``` err = sess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) error { // perform write operations _, err = client.Database("mydb").Collection("mycoll").InsertOne(sessCtx, bson.M{"x": 1}) if err != nil { sess.AbortTransaction(sessCtx) return err } return nil }) if err != nil { // handle error } ``` 在事务中执行的所有操作都会在事务提交之前保存到内存中,并在事务提交时一起写入到数据库中。如果在事务中出现了错误,可以使用 `Session.AbortTransaction()` 方法来回滚事务,所有在事务中执行的操作都不会写入到数据库中。 在事务结 ### 回答2: 在Go语言操作MongoDB,可以使用事务回滚来进行写入、删除等操作。以下是一些基本操作示例: 1. 初始化MongoDB客户端和数据库连接: ```go clientOptions := options.Client().ApplyURI("mongodb://localhost:27017") client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } database := client.Database("mydatabase") ``` 2. 开启事务: ```go session, err := client.StartSession() if err != nil { log.Fatal(err) } defer session.EndSession(context.TODO()) ``` 3. 事务开始后,可以执行多个操作。例如,插入一条数据: ```go session.StartTransaction() collection := database.Collection("mycollection") doc := bson.D{{"key", "value"}} _, err = collection.InsertOne(session.Context(), doc) if err != nil { session.AbortTransaction(session.Context()) log.Fatal(err) } ``` 4. 执行其他操作,比如删除一条数据: ```go collection := database.Collection("mycollection") filter := bson.D{{"key", "value"}} _, err = collection.DeleteOne(session.Context(), filter) if err != nil { session.AbortTransaction(session.Context()) log.Fatal(err) } ``` 5. 若所有操作都成功执行,提交事务: ```go err = session.CommitTransaction(session.Context()) if err != nil { log.Fatal(err) } ``` 6. 若操作发生错误或者需要回滚,可以调用AbortTransaction()进行事务回滚: ```go session.AbortTransaction(session.Context()) ``` 以上是一个简单的示例,用于展示如何在Go语言中使用事务回滚进行写入和删除操作。实际应用中,可能需要更多的代码和逻辑来处理错误以及处理更复杂的事务操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

特立独行的猫a

您的鼓励是我的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值