您的位置:

Go语言操作MongoDB

一、MongoDB简介

MongoDB是一个广为流行的NoSQL数据库,使用JSON格式进行数据存储。与传统关系型数据库不同,MongoDB没有固定的表结构,而是可以存储各种类型的数据,支持动态的扩展。

MongoDB有多个版本,包括社区版和企业版等,其中最常用的是社区版,可以免费使用。

二、Go语言操作MongoDB的基本API

Go语言操作MongoDB可以使用mgo或官方提供的mongo-go-driver两种库,这里介绍使用mongo-go-driver的基本API。

首先需要安装mongo-go-driver库:

go get go.mongodb.org/mongo-driver

接下来,首先需要建立与MongoDB的连接:

package main

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

func main() {
	// Set client options
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")

	// Connect to MongoDB
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		log.Fatal(err)
	}

	// Ping the primary
	err = client.Ping(ctx, nil)
	if err != nil {
		log.Fatal(err)
	}

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

上面的代码连接了本地的MongoDB数据库,并进行了Ping操作,确认是否连接成功。接下来可以进行数据库的常规操作,比如插入、查询、删除等。

三、插入数据

插入数据可以使用Collection对象的InsertOne或InsertMany方法,使用bson库构建文档对象。示例如下:

package main

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

type Student struct {
	Name    string `bson:"name"`
	Age     int    `bson:"age"`
	Gender  string `bson:"gender"`
	Address string `bson:"address"`
}

func main() {
	// Set client options
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")

	// Connect to MongoDB
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		log.Fatal(err)
	}

	// Collection handle
	collection := client.Database("test").Collection("student")

	// Insert a single document
	student := Student{"Tom", 18, "male", "Beijing"}
	result, err := collection.InsertOne(ctx, student)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Inserted student with ID:", result.InsertedID)

	// Insert multiple documents
	students := []interface{}{
		Student{"Lucy", 17, "female", "Shanghai"},
		Student{"Jerry", 19, "male", "Guangzhou"},
	}
	result, err = collection.InsertMany(ctx, students)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Inserted documents with IDs:", result.InsertedIDs)
}

上面的代码插入了两个学生的数据,其中Student结构体的字段与MongoDB中的文档字段通过bson标签映射。InsertOne方法返回插入的文档ID,InsertMany方法返回插入的多个文档的ID。

四、查询数据

查询数据可以使用Collection对象的Find和FindOne方法,使用bson库构建查询条件。示例如下:

package main

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

type Student struct {
	Name    string `bson:"name"`
	Age     int    `bson:"age"`
	Gender  string `bson:"gender"`
	Address string `bson:"address"`
}

func main() {
	// Set client options
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")

	// Connect to MongoDB
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		log.Fatal(err)
	}

	// Collection handle
	collection := client.Database("test").Collection("student")

	// Find a single document
	var result Student
	err = collection.FindOne(ctx, bson.M{"name": "Tom"}).Decode(&result)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Found student with name:", result.Name)

	// Find multiple documents
	var results []Student
	cur, err := collection.Find(ctx, bson.M{"age": bson.M{"$gt": 17}})
	if err != nil {
		log.Fatal(err)
	}
	defer cur.Close(ctx)
	for cur.Next(ctx) {
		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)
	}
	fmt.Printf("Found multiple students with age > 17: %+v\n", results)
}

上面的代码查询了一个名字为Tom的学生的数据,和年龄大于17岁的多个学生的数据。FindOne方法返回单个文档,Find方法返回多个文档的游标,需要使用Next方法迭代处理。

五、更新数据

更新数据可以使用Collection对象的UpdateOne或UpdateMany方法,使用bson库构建查询条件和更新文档对象。示例如下:

package main

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

type Student struct {
	Name    string `bson:"name"`
	Age     int    `bson:"age"`
	Gender  string `bson:"gender"`
	Address string `bson:"address"`
}

func main() {
	// Set client options
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")

	// Connect to MongoDB
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		log.Fatal(err)
	}

	// Collection handle
	collection := client.Database("test").Collection("student")

	// Update a single document
	filter := bson.M{"name": "Tom"}
	update := bson.M{"$set": bson.M{"address": "Shenzhen"}}
	result, err := collection.UpdateOne(ctx, filter, update)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Matched %v documents and updated %v documents.\n", result.MatchedCount, result.ModifiedCount)

	// Update multiple documents
	filter = bson.M{"age": bson.M{"$gt": 17}}
	update = bson.M{"$set": bson.M{"gender": "unknown"}}
	result, err = collection.UpdateMany(ctx, filter, update)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Matched %v documents and updated %v documents.\n", result.MatchedCount, result.ModifiedCount)
}

上面的代码更新了一个名字为Tom的学生的地址数据,和年龄大于17岁的多个学生的性别数据。UpdateOne方法返回匹配和更新的文档数量,UpdateMany方法也是如此。

六、删除数据

删除数据可以使用Collection对象的DeleteOne或DeleteMany方法,使用bson库构建查询条件。示例如下:

package main

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

type Student struct {
	Name    string `bson:"name"`
	Age     int    `bson:"age"`
	Gender  string `bson:"gender"`
	Address string `bson:"address"`
}

func main() {
	// Set client options
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")

	// Connect to MongoDB
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		log.Fatal(err)
	}

	// Collection handle
	collection := client.Database("test").Collection("student")

	// Delete a single document
	filter := bson.M{"name": "Lucy"}
	result, err := collection.DeleteOne(ctx, filter)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Deleted %v documents.\n", result.DeletedCount)

	// Delete multiple documents
	filter = bson.M{"age": bson.M{"$lt": 18}}
	result, err = collection.DeleteMany(ctx, filter)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Deleted %v documents.\n", result.DeletedCount)
}

上面的代码删除了一个名字为Lucy的学生的数据,和年龄小于18岁的多个学生的数据。DeleteOne方法和UpdateOne方法类似,返回匹配和删除的文档数量,DeleteMany方法也是如此。

七、MongoDB常用操作符

MongoDB支持很多常用的操作符,比如:

  • $eq: 等于
  • $ne: 不等于
  • $in: 在指定列表中
  • $gt: 大于
  • $lt: 小于
  • $gte: 大于等于
  • $lte: 小于等于
  • $or: 或
  • $and: 与

例如,查询年龄在18到20岁之间的学生,可以使用以下代码:

filter := bson.M{"age": bson.M{"$gte": 18, "$lte": 20}}
cur, err := collection.Find(ctx, filter)

八、总结

本文介绍了Go语言操作MongoDB的基本API,包括建立连接、插入数据、查询数据、更新数据和删除数据等。MongoDB具有高可扩展性和灵活性,适用于存储大规模和非结构化的数据,对于复杂查询、高并发和高容错性的应用有很好的支持。