mongodb基础教程

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型

mongo应用场景

MongoDB 和 MySQL 是两种不同类型的数据库(分别属于 NoSQL 和关系型数据库),适用场景和核心特性有显著区别

对于关系型数据库来说,我们开发的时候,需要先定义好表、字段这些,后期如果要扩展字段这些相对来说比较麻烦

但是对于非关系型数据库来说,开发的时候就不需要提前定义表和字段这些了,适合快速迭代以及差异化展示

  1. 内容管理系统(CMS)

存储文章、评论、用户生成内容等,这些数据往往结构多变(例如不同文章可能有不同字段:视频文章有 “时长”,图文文章有 “图片列表”),MongoDB 的文档模型可以直接嵌套存储,无需像 MySQL 那样拆分成多张表。

  1. 大数据与实时分析

支持高并发写入和水平扩展(分片),适合存储日志、埋点数据、传感器数据等海量时序数据,可快速写入并通过聚合管道进行实时分析。

  1. 移动 / 物联网(IoT)应用

设备采集的非结构化数据(如设备状态、地理位置、传感器读数)可以直接以文档形式存储,无需预先定义严格 schema,方便适配不同设备的数据格式。

  1. 社交应用

存储用户动态、关系链、消息记录等,文档模型支持嵌套数组(如 “好友列表”“评论列表”),避免 MySQL 中多表关联查询的性能开销。

  1. 电商平台

存储商品信息(不同商品属性差异大:服装有 “尺码”,电子设备有 “参数”)、购物车、订单等,灵活的 schema 可快速适配业务变化。

mongodb安装

拉取镜像

docker pull mongo:8.0.15

创建容器,并创建用户和数据库

docker run --name mongo -p 27017:27017 -v /home/mongo:/data/db -d mongo:8.0.15

docker exec -it mongo bash

# 进入mongo的shell
mongosh 
# 创建并进入数据库 test
use test

# 创建用户并授权
db.createUser({
  user: "root1",
  pwd: "root1",
  roles: [{ role: "dbOwner", db: "test" }]
})

# 验证用户是否创建成功
show users

# 创建的这个root1用户,只能访问test这个数据库

# 后续进入数据库
mongosh -u root1 -p root1 test


也可以直接在启动容器的时候,创建用户名和密码

docker run --name mongo -p 27017:27017 -v /home/mongo:/data/db -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=root -d mongo:8.0.15 --auth

# 通过此命令创建的用户,可以进所有用户创建的数据库,不过要指定认证数据库
mongosh -u root -p root --authenticationDatabase admin test


但是还是需要手动创建数据库,不过可以在客户端里面创建

mongo客户端

可以使用goland里面的mongodb客户端

后续学习mongo的基本命令,也是基于此客户端

mongodb基本命令

就和学习mysql一样,我们需要先了解mongo的基本命令

基本操作

// 查看数据库
show databases

// 创建数据库
use test

// 查看所有集合
show collections

// 创建集合
db.createCollection("user")

// 删除集合
db.user.drop()

// 删除库 
db.dropDatabase()

// 创建文档
db.user.insert({"name": "fengfeng"})
db.user.insert({"name": "fengfeng", "age": 21})
db.user.insertOne({name: "王五"})

// 如果集合不存在,会自动创建
db.student.insertOne({name: "王五"})

// 批量创建文档
db.user.insertMany([{name: "lisi"}, {name: "张三"}])

// 创建的时候,指定id
db.user.insertOne({_id: 110, name: "yuanfang"})

// 使用for循环批量创建
for(let i=1;i<10;i++){
    db.user.insertOne({name:"a"+i,age:i})
}

// 查询文档
db.user.find()

// 删除 db.集合名.remove(条件 [,是否删除一条])
// 删除全部文档
db.user.remove({}, false)

// 删除满足条件的一条文档 指定id删除
db.user.remove({_id: ObjectId("68e8b50129427f6eb783f216")}, true)
// 指定其他条件删除
db.user.remove({name: "a8"}, true)

// 修改文档  db.集合名.update(条件, 新数据 [,是否新增, 是否修改多条])
// 把 a7换成a77
db.user.update({name:"a7"},{$set: {name:"a77"}})

查询

// 查询 db.集合名.find(条件 [,查询的列])
// 查询全部
db.user.find()

// 带条件查询  查询age大于5的
db.user.find({age: {$gt: 5}})
// 带条件查询  查询name 在区间内的
db.user.find({name: {$in: ["a1", "a2"]}})

// 只显示name列
db.user.find({}, {name: 1, _id: 0})

// 排序
db.user.find().sort({age: -1}) // 1 升序 -1 降序

// 分页
db.user.find()
db.user.find().limit(2) // 查询前两条数据
db.user.find().skip(2).limit(2) // 跳过两条,查询两条数据

运算符

运算符作用
$gt大于
$gte大于等于
$lt小于
$lte小于等于
$ne不等于
$inin
$ninnot in

聚合查询

// 准备数据
db.people.insert({_id: 1, name: "a", sex: "男", age: 21})
db.people.insert({_id: 2, name: "b", sex: "男", age: 20})
db.people.insert({_id: 3, name: "c", sex: "女", age: 20})
db.people.insert({_id: 4, name: "d", sex: "女", age: 18})
db.people.insert({_id: 5, name: "e", sex: "男", age: 19})

// 统计男生、女生的总年龄
db.people.aggregate([
    {$group: {_id: "$sex", age_sum: {$sum: "$age"}}}
])

// 统计男生女生的总人数
db.people.aggregate([
    {$group: {_id: "$sex", sum: {$sum: 1}}}
])

// 求学生总数和平均年龄
db.people.aggregate([
    {$group: {_id: null, total_num: {$sum: 1}, total_avg: {$avg: "$age"}}}
])

// 查询男生、女生人数,按人数升序
db.people.aggregate([
    {$group: {_id: "$sex", rs: {$sum: 1}}},
    {$sort: {rs: 1}}
])

常用管道

$group将集合中的文档分组,用于统计结果
$match过滤数据,只输出符合条件的文档
$sort聚合数据进一步排序
$skip跳过指定文档数
$limit限制集合数据返回文档数

常用表达式

$sum总和($num:1同count表示统计)
$avg平均
$min最小值
$max最大值

go操作mongodb

其实mongo更适合在nodejs和python这类动态语言中进行使用

在go里面,我们掌握基本的mongo操作就可以了

重点还是要对mongo的原生操作熟悉

使用的库

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

基本连接

package main

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

func main() {
  // 设置客户端连接配置
  clientOptions := options.Client().
    ApplyURI("mongodb://192.168.80.170:27017").
    SetAuth(options.Credential{
      Username: "root",
      Password: "root",
    }).                  // 用户名和密码
    SetMaxPoolSize(100). // 最大连接数
    SetMinPoolSize(10)   // 最小连接数
  // 连接到MongoDB
  client, err := mongo.Connect(context.TODO(), clientOptions)
  if err != nil {
    log.Fatal(err)
  }
  // 检查连接
  err = client.Ping(context.TODO(), nil)
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println("Connected to MongoDB!")

  // 断开连接
  err = client.Disconnect(context.TODO())
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println("Connection to MongoDB closed.")

}


crud操作

插入数据

package main

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

func main() {
  insert3()
}

func insert1() {
  collection := client.Database("test").Collection("users")

  data := bson.D{
    {
      Key:   "name",
      Value: "fengfeng",
    },
    {
      Key:   "age",
      Value: 18,
    },
  }

  result, err := collection.InsertOne(context.Background(), data)
  if err != nil {
    fmt.Println(err)
    return
  }

  fmt.Println(result.InsertedID)
}

func insert2() {
  collection := client.Database("test").Collection("users")

  data := bson.M{
    "name": "张三",
    "age":  21,
  }

  result, err := collection.InsertOne(context.Background(), data)
  if err != nil {
    fmt.Println(err)
    return
  }

  fmt.Println(result.InsertedID)
}

func insert3() {
  collection := client.Database("test").Collection("users")

  type Info struct {
    Name string `bson:"name1"`
    Age  int    `bson:"age1"`
  }
  var info = Info{"王五", 12}
  result, err := collection.InsertOne(context.Background(), info)
  if err != nil {
    fmt.Println(err)
    return
  }

  fmt.Println(result.InsertedID)
}


查询数据

package main

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

func main() {
  find5()
}

func find1() {
  collection := client.Database("test").Collection("users")

  sr := collection.FindOne(context.Background(), bson.M{"name": "fengfeng"})
  fmt.Println(sr.Raw())

  var data bson.M
  err := sr.Decode(&data)
  fmt.Println(data, err)

  type Info struct {
    Name string
    Age  int
    ID   string `bson:"_id"`
  }
  var info Info
  err = sr.Decode(&info)
  fmt.Println(info, err)

}

func find2() {
  collection := client.Database("test").Collection("users")

  objectID, err := primitive.ObjectIDFromHex("68e9104e26aef638551098ab")
  fmt.Println(objectID, err)

  sr := collection.FindOne(context.Background(), bson.M{"_id": objectID})
  fmt.Println(sr.Raw())
}

func find3() {
  collection := client.Database("test").Collection("users")
  cursor, err := collection.Find(context.Background(), bson.M{})
  fmt.Println(cursor, err)
  for cursor.Next(context.Background()) {
    fmt.Println(cursor.Current.String())
  }

}

func find4() {
  collection := client.Database("test").Collection("users")

  var limit int64 = 2
  var skip int64 = 2

  cursor, err := collection.Find(context.Background(), bson.M{}, &options.FindOptions{
    Limit: &limit,
    Skip:  &skip,
  })
  fmt.Println(cursor, err)
  for cursor.Next(context.Background()) {
    fmt.Println(cursor.Current.String())
  }

}

func find5() {
  collection := client.Database("test").Collection("users")
  cursor, err := collection.Find(context.Background(), bson.M{})
  fmt.Println(cursor, err)
  //var data bson.A
  //err = cursor.All(context.Background(), &data)
  //fmt.Println(data, err)
  // 调了all之后,就没有了

  type Info struct {
    Name string
    Age  int
    ID   string `bson:"_id"`
  }
  var infoList []Info
  err = cursor.All(context.Background(), &infoList)
  fmt.Println(infoList, err)
}

删除数据

func remove1() {
  collection := client.Database("test").Collection("users")
  dr, err := collection.DeleteOne(context.Background(), bson.M{"name": "fengfeng"})
  fmt.Println(dr.DeletedCount, err)
}

func remove2() {
  collection := client.Database("test").Collection("users")
  dr, err := collection.DeleteMany(context.Background(), bson.M{})
  fmt.Println(dr.DeletedCount, err)
}

更新数据

func update1() {
  collection := client.Database("db").Collection("user")
  //c, err := collection.Find(context.Background(), bson.M{})
  //var data bson.A
  //err = c.All(context.Background(), &data)
  //fmt.Println(data, err)

  ur, err := collection.UpdateOne(context.Background(), bson.M{"name": "auth_0"}, bson.M{"$set": bson.M{"name": "auth_00"}})
  fmt.Println(ur, err)
}

func update2() {
  collection := client.Database("db").Collection("user")
  //c, err := collection.Find(context.Background(), bson.M{})
  //var data bson.A
  //err = c.All(context.Background(), &data)
  //fmt.Println(data, err)

  objectID, _ := primitive.ObjectIDFromHex("68e8f4406f59126e045d8f92")

  ur, err := collection.UpdateByID(context.Background(), objectID, bson.M{"$set": bson.M{"name": "auth_11"}})
  fmt.Println(ur, err)
}

func update3() {
  collection := client.Database("db").Collection("user")
  ur, err := collection.UpdateMany(context.Background(), bson.M{
    "index": bson.M{"$in": []int{1, 2, 3}},
  }, bson.M{"$set": bson.M{"name": "000"}})
  fmt.Println(ur, err)

  c, _ := collection.Find(context.Background(), bson.M{
    "index": bson.M{"$in": []int{1, 2, 3}},
  })
  var data bson.A
  c.All(context.Background(), &data)
  fmt.Println(data)

}

不同的bson类型

bson.D(有序文档)
字段顺序严格按照添加顺序存储和传输,查询时也会保持顺序。
适合需要精确控制字段顺序的场景(如 MongoDB 的聚合管道、排序规则等)。

bson.E(文档字段元素)
作为 bson.D 的组成单元,用于定义有序文档中的每个字段。

bson.M(无序文档)
语法更简洁,使用方式类似 JSON 对象,适合快速构建简单文档。
字段顺序在编码 / 解码时可能被打乱,不适合依赖顺序的场景。

bson.A(数组)
元素可以是任意类型(字符串、数字、bson.D、bson.M 甚至另一个 bson.A)。
保留元素的插入顺序,与 MongoDB 中的数组行为一致。

mongodb高级操作

索引

索引是一种排序好的便于快速查询数据的数据结构,用于帮助数据库高效的查询数据

优点

  • 提高数据查询的效率,降低数据库的IO成本
  • 通过索引对数据进行排序,降低数据排序的成本,降低CPU的消耗

缺点

  • 占用磁盘空间
  • 大量索引影响SQL语句的执行效率,因为每次插入和修改数据都要更新索引
// 创建索引  db.集合名.createIndex({待创建索引的列:方式} [,额外选项]) 1表示升序,-1表示降序
//  额外选项:设置索引的名称或者唯一索引等
//    设置名称:{name:索引名}
//    唯一索引:{unique:列名}
db.user.createIndex({name: 1})

// 查看索引
db.user.getIndexes()

// 删除全部索引
db.user.dropIndexes()
// 删除指定索引
db.user.dropIndex("name_1")

可以看到,加了索引之后,查询效率的提升是很明显的

权限机制

安装完Mongodb后,在命令行输入mongosh 命令即可登录数据库,这肯定是不安全的,我们需要使用权限机制,开启验证模式

创建账号

db.createUser({
  "user":"账号",
  "pwd":"密码",
  "roles":[{
    role:"角色",
    db:"所属数据库"
  }]
})

角色种类

超级用户角色:root
数据库用户角色:read、readWrite
数据库管理角色:dbAdmin、userAdmin
集群管理角色: clusterAdmin、clusterManager、clusterMonitor、hostManager
备份恢复角色: backup、restore
所有数据库角色: readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase

角色说明

root:只在admin数据库中可用。超级账号,超级权限;
read:允许用户读取指定数据库;
readWrite:允许用户读写指定数据库
db.createUser({
    "user":"fengfeng",
    "pwd":"1234",
    "roles":[{
        role:"read",
        db:"test"
    }]
})

// 查询当前库下的用户列表
db.getUsers()

// 删除用户
db.dropUser("fengfeng")

权限的用法

管理人员创建一个很复杂的root用户,基于这个root用户创建不同角色的用户,再把这些用户分配给不同人去使用mongo

数据导入导出

MongoDB 提供了专门的工具用于数据的导入导出,最常用的是 mongoexport(导出)和 mongoimport(导入),支持 JSON、CSV 等格式。

数据导出
mongoexport --uri="mongodb://用户名:密码@主机:端口/数据库名?authSource=认证数据库" \
  --collection=集合名 \
  --out=输出文件路径 \
  [--type=格式]  # 可选,默认json,支持csv

导出json

mongoexport --uri="mongodb://root:root@127.0.0.1:27017/test?authSource=admin" --collection=user --out=user.json --type=json

导出csv

mongoexport --uri="mongodb://root:root@localhost:27017/test?authSource=admin" --collection=user  --type=csv  --fields=name,age --out=./user.csv

带条件导出

mongoexport --uri="mongodb://root:root@localhost:27017/test?authSource=admin" --collection=user --query='{"age": {"$gt": 18}}' --out=./adult_user.json
数据导入

mongoimport 用于将 JSON/CSV 数据导入到集合

mongoimport --uri="mongodb://用户名:密码@主机:端口/数据库名?authSource=认证数据库" \
  --collection=集合名 \
  --file=输入文件路径 \
  [--type=格式]  # 可选,默认json,支持csv
  [--headerline]  # CSV格式时使用,第一行为字段名

导入json数据

mongoimport --uri="mongodb://root:root@localhost:27017/test?authSource=admin"  --collection=user1 --file=./user.json
备份与恢复

如果需要完整备份数据库(包括索引、结构等),推荐使用 mongodump 和 mongorestore

# 备份整个数据库(生成二进制BSON文件)
mongodump --uri="mongodb://root:root@localhost:27017/?authSource=admin"  --db=test --out=./backup  
  
# 恢复test数据库
mongorestore --uri="mongodb://root:root@localhost:27017/?authSource=admin" --db=test ./backup/test  
  

参考文档

MongoDB从零开始详细教程 https://blog.youkuaiyun.com/qq_45173404/article/details/114260970

go操作mongo https://blog.youkuaiyun.com/cui_yonghua/article/details/152553260

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值