MongoDB
2026年1月14日 · 552 字 · 3 分钟
介绍了mongoDB的基本语法,以及在go中操作mongoDB
MongoDB
一、MongoDB 是什么
MongoDB 是典型的 文档型数据库(Document DB),数据以 BSON(类似 JSON)形式存储。它的核心优势是:
- 结构灵活:同一个集合里,不同文档字段可以不同(你后面插入“张三/李四”就是典型例子)。
- 开发效率高:对象结构和 JSON 很接近,适合快速迭代。
- 横向扩展能力强:天然适合分片、复制集等分布式方案(适合海量数据与高并发)。
二、MongoDB 典型应用场景
1)内容/信息流类(字段经常变、迭代快)
比如:博客文章、评论、点赞、标签、用户行为记录。 特点:字段可能不断新增(阅读量、推荐权重、AB实验分组……),MongoDB 的“无固定表结构”很省事。
2)日志与埋点数据(写多读少、数据量大)
如:访问日志、系统日志、业务埋点。 MongoDB 写入性能好,配合索引和分片可承载较大吞吐。
3)用户画像/配置中心(每个人字段不一样)
如:用户偏好、标签、权限、个性化配置。 不同用户属性差异大,用关系型表会变成“稀疏列/多表拆分”,MongoDB 反而自然。
4)原型验证与快速开发
项目早期需求不稳定,MongoDB 可以让你先把功能跑通,再逐步优化模型。
不太建议:强事务、强一致、多表复杂 JOIN 的场景(虽然 MongoDB 支持事务,但复杂关联依旧不是它的强项)。
三、MongoDB 基本语法
1)查看集合
test> show collections
作用:列出当前数据库 test 下所有集合(类似 MySQL 的 show tables)。
2)创建集合
test> db.createCollection("student")
{ ok: 1 }
db.createCollection("student"):显式创建集合 student。
MongoDB 其实也支持 隐式创建:当你第一次向 student 插入数据时,如果集合不存在,也会自动创建。
验证:
test> show collections
student
3)创建索引:你遇到的坑
MongoDB 的 createIndex() 参数里:
- 第一个参数是 key(字段与排序方向)
- 第二个参数才是 options(例如 unique)
db.student.createIndex({ name: 1 }, { unique: true })
4)查看索引
test> db.student.getIndexes()
[
{ v: 2, key: { _id: 1 }, name: '_id_' },
{ v: 2, key: { name: 1 }, name: 'name_1', unique: true }
]
解释:
- MongoDB 默认每个集合都有
_id_索引(主键)。
5)删除索引
test> db.student.dropIndex("name_1")
{ nIndexesWas: 2, ok: 1 }
删除指定名字的索引(索引名来自 createIndex 返回值)。
再查:
test> db.student.getIndexes()
[ { v: 2, key: { _id: 1 }, name: '_id_' } ]
只剩默认 _id_。
6)重新创建一个普通索引
test> db.student.createIndex({name:1})
name_1
单字段升序索引:对 name 的查询会更快,例如 find({name:"张三"})。
四、插入数据 insert
1)插入一条
db.student.insertOne({name:"张三",city:"北京"})
返回 insertedId,MongoDB 自动生成 _id(ObjectId)。
2)查询全部
db.student.find()
你看到集合里有一条文档。
3)批量插入
db.student.insertMany([{name:"张三",city:"北京"},{name:"李四",gender:"男"}])
特点:
- 同一个集合里,第二条文档没有
city,却有gender—— 这就是 MongoDB 的“字段灵活”。
五、查询 find(带条件)
db.student.find({name:"张三"})
返回所有 name="张三" 的文档。
这个查询会受益于你之前建的 name_1 索引。
六、更新 update
1)更新一条 updateOne
db.student.updateOne({name:"张三"},{$set:{gender:"女"}})
解释:
{name:"张三"}:过滤条件(匹配第一条符合条件的文档){$set:{gender:"女"}}:更新操作符(只改 gender 字段,不会覆盖整个文档)
返回值里:
matchedCount: 1:匹配到 1 条modifiedCount: 1:实际修改 1 条
再查:
db.student.find({name:"张三"})
你会发现:只有其中一个张三有 gender 字段。
2)更新多条 updateMany
db.student.updateMany({name:"张三"},{$set:{city:"上海"}})
匹配到的两条张三都被更新为 city:"上海"。
七、删除 delete
1)删除一条 deleteOne
db.student.deleteOne({name:"张三"})
只删第一条匹配到的张三。
2)删除多条 deleteMany
db.student.deleteMany({name:"张三"})
删除所有匹配到的张三。
八、删除集合 drop
db.student.drop()
true
删除整个集合(数据 + 索引都会没)。
验证:
show collections
student 不见了。
九、总结
show collections:查看集合db.createCollection():创建集合(也可插入时自动创建)createIndex / getIndexes / dropIndex:索引管理(注意 unique 是 options,不是 key)insertOne / insertMany:插入find(条件):查询updateOne / updateMany + $set:更新deleteOne / deleteMany:删除drop():删集合
go操作mongoDB
连接mongoDB
func MongoDBInit() {
ctx := context.Background()
option := options.Client().ApplyURI("mongodb://localhost:27017").
SetConnectTimeout(time.Second). //设置超时时长
SetAuth(options.Credential{
//AuthSource代表Database
Username: "",
Password: "",
AuthSource: "test",
})
client, err := mongo.Connect(ctx, option)
if err != nil {
log.Fatal(err)
}
//Connect没有返回error不代表连接成功,ping一下检查是否连接成功
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx) //释放连接
collection := client.Database("test").Collection("student")
//增
create(ctx, collection)
//改
update(ctx, collection)
//删
delete(ctx, collection)
//查
find(ctx, collection)
}
增
type Student struct {
Name string
City string
Score float32
}
func create(ctx context.Context, collection *mongo.Collection) {
//插入一个doc
student := Student{
Name: "张三",
City: "北京",
Score: 85.5,
}
res, err := collection.InsertOne(ctx, student)
if err != nil {
log.Fatal(err)
}
fmt.Println("插入成功", res.InsertedID) //每个doc都会有一个全世界唯一的ID(时间+空间唯一)
//插入多个docs
docs := []interface{}{Student{Name: "李四", City: "北京", Score: 24}, Student{Name: "王五", City: "南京", Score: 21}}
manyRes, err := collection.InsertMany(ctx, docs)
if err != nil {
log.Fatal(err)
}
fmt.Println("插入多个doc成功", manyRes.InsertedIDs)
}
删
func delete(ctx context.Context, collection *mongo.Collection) {
//删除一个doc
filter := bson.D{{Key: "name", Value: "张三"}}
//切片过滤条件可以有多个
res, err := collection.DeleteMany(ctx, filter)
if err != nil {
log.Fatal(err)
}
fmt.Println("删除成功", res.DeletedCount)
}
改
func update(ctx context.Context, collection *mongo.Collection) {
//更新一个doc
filter := bson.D{{Key: "city", Value: "北京"}}
//切片过滤条件可以有多个
//把满足在北京的学生,score加上5
update := bson.D{{Key: "$inc", Value: bson.D{{Key: "score", Value: 5}}}}
//切片更新条件可以有多个
res, err := collection.UpdateMany(ctx, filter, update)
if err != nil {
log.Fatal(err)
}
//打印修改了多少条记录
fmt.Println("更新成功", res.ModifiedCount)
}
查
func find(ctx context.Context, collection *mongo.Collection) {
//查询一个doc
sort := bson.D{{Key: "name", Value: 1}} //查询结果按name进行排序。1代表升序,-1代表降序
//gt代表greater than
filter := bson.D{{Key: "score", Value: bson.D{{Key: "$gt", Value: 3}}}} //查询结果按score大于3进行过滤
//切片过滤条件可以有多个
findOptions := options.Find()
findOptions.SetSort(sort)
findOptions.SetLimit(10) //限制查询结果最多10条
findOptions.SetSkip(3) //跳过前3个
cursor, err := collection.Find(ctx, filter, findOptions)
if err != nil {
log.Fatal(err)
}
defer cursor.Close(ctx) //关闭迭代器
for cursor.Next(ctx) {
var student Student
if err = cursor.Decode(&student); err != nil {
log.Fatal(err)
}
fmt.Println("查询成功", student.Name, student.City, student.Score)
}
}