一、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具有高可扩展性和灵活性,适用于存储大规模和非结构化的数据,对于复杂查询、高并发和高容错性的应用有很好的支持。