MongoDB 使用文档

MongoDB 使用文档

一、MongoDB 简介

1.1 什么是 MongoDB

MongoDB 是一个开源的、面向文档的 NoSQL 数据库,采用 BSON(Binary JSON)格式存储数据。

1.2 主要特性

  • 文档模型:数据以 JSON-like 文档形式存储
  • 灵活的模式:不需要预定义表结构
  • 水平扩展:支持分片集群
  • 高可用性:支持副本集
  • 丰富的查询语言:支持复杂的查询操作
  • 聚合框架:强大的数据处理能力
  • 地理空间:内置地理空间索引和查询

1.3 适用场景

  • ✅ 内容管理系统
  • ✅ 实时分析
  • ✅ 物联网应用
  • ✅ 移动应用后端
  • ✅ 电子商务平台
  • ✅ 社交网络

二、安装与配置

2.1 在 CentOS 上安装

# 1. 配置 MongoDB 仓库
sudo tee /etc/yum.repos.d/mongodb-org-4.4.repo << 'EOF'
[mongodb-org-4.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/\$releasever/mongodb-org/4.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc
EOF

# 2. 安装 MongoDB
sudo yum install -y mongodb-org

# 3. 启动服务
sudo systemctl start mongod
sudo systemctl enable mongod

# 4. 验证安装
mongod --version

2.2 配置文件位置

/etc/mongod.conf      # 主配置文件
/var/log/mongodb/     # 日志目录
/var/lib/mongo/       # 数据目录

2.3 基本配置

# /etc/mongod.conf
systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true

storage:
  dbPath: /var/lib/mongo
  journal:
    enabled: true

net:
  port: 27017
  bindIp: 127.0.0.1  # 或 0.0.0.0 允许远程访问

processManagement:
  fork: true
  pidFilePath: /var/run/mongodb/mongod.pid

三、基本概念

3.1 数据模型

SQL 概念 MongoDB 概念
Database Database
Table Collection
Row Document
Column Field
Primary Key _id
Index Index

3.2 文档结构示例

{
  "_id": ObjectId("507f1f77bcf86cd799439011"),
  "name": "张三",
  "age": 25,
  "email": "zhangsan@example.com",
  "address": {
    "city": "北京",
    "street": "朝阳路",
    "postalCode": "100000"
  },
  "hobbies": ["游泳", "阅读", "编程"],
  "created_at": ISODate("2024-01-15T10:30:00Z")
}

3.3 BSON 数据类型

类型 描述 示例
String 字符串 "hello"
Integer 整数 42
Double 浮点数 3.14
Boolean 布尔值 true/false
Array 数组 [1, 2, 3]
Object 对象/文档
Null 空值 null
Date 日期 new Date()
ObjectId 对象ID ObjectId()
Binary Data 二进制数据 BinData()
Timestamp 时间戳 Timestamp()

四、基本操作

4.1 启动和连接

# 启动 MongoDB 服务
sudo systemctl start mongod

# 连接 MongoDB
mongo                         # 本地连接
mongo --host 192.168.1.100    # 远程连接
mongo --port 27017           # 指定端口
mongo -u admin -p password   # 认证连接

4.2 数据库操作

// 查看所有数据库
show dbs

// 查看当前数据库
db

// 切换数据库(不存在则创建)
use mydb

// 删除当前数据库(谨慎!)
db.dropDatabase()

// 查看数据库统计信息
db.stats()

4.3 集合操作

// 查看所有集合
show collections
show tables

// 创建集合
db.createCollection("users")
db.createCollection("products", {
  capped: true,      // 固定集合
  size: 100000,      // 大小(字节)
  max: 1000          // 最大文档数
})

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

// 查看集合信息
db.users.stats()
db.users.getCollectionInfos()

// 重命名集合
db.users.renameCollection("customers")

4.4 插入文档

// 插入单条文档
db.users.insertOne({
  name: "张三",
  age: 25,
  email: "zhangsan@example.com",
  status: "active"
})

// 插入多条文档
db.users.insertMany([
  {
    name: "李四",
    age: 30,
    email: "lisi@example.com"
  },
  {
    name: "王五",
    age: 28,
    email: "wangwu@example.com"
  }
])

// 插入并返回结果
let result = db.users.insertOne({name: "赵六"})
print("Inserted ID:", result.insertedId)

// 使用 save(存在则更新,不存在则插入)
db.users.save({
  _id: ObjectId("507f1f77bcf86cd799439011"),
  name: "更新后的名字",
  age: 26
})

五、查询操作

5.1 基本查询

// 查询所有文档
db.users.find()

// 格式化输出
db.users.find().pretty()

// 查询第一条
db.users.findOne()

// 查询特定字段(投影)
db.users.find({}, { name: 1, email: 1 })      // 只返回 name 和 email
db.users.find({}, { _id: 0, name: 1 })        // 不返回 _id
db.users.find({}, { password: 0 })            // 排除 password 字段

5.2 条件查询运算符

运算符 描述 示例
$eq 等于 {age: {$eq: 25}}
$ne 不等于 {age: {$ne: 25}}
$gt 大于 {age: {$gt: 25}}
$gte 大于等于 {age: {$gte: 25}}
$lt 小于 {age: {$lt: 25}}
$lte 小于等于 {age: {$lte: 25}}
$in 在数组中 {age: {$in: [25, 30, 35]}}
$nin 不在数组中 {age: {$nin: [20, 25]}}

5.3 查询示例

// 等值查询
db.users.find({ name: "张三" })
db.users.find({ age: 25 })
db.users.find({ "address.city": "北京" })

// 比较查询
db.users.find({ age: { $gt: 25 } })      // 年龄大于25
db.users.find({ age: { $gte: 20, $lte: 30 } })  // 年龄20-30之间

// 逻辑运算符
db.users.find({ $and: [
  { age: { $gt: 20 } },
  { age: { $lt: 30 } }
]})

db.users.find({ $or: [
  { status: "active" },
  { age: { $gt: 25 } }
]})

db.users.find({ $nor: [
  { status: "inactive" },
  { age: { $lt: 18 } }
]})

// 正则表达式查询
db.users.find({ name: /^张/ })           // 以"张"开头
db.users.find({ name: /三$/ })           // 以"三"结尾
db.users.find({ name: /李.*四/i })       // 不区分大小写

5.4 数组查询

// 数组包含
db.users.find({ hobbies: "游泳" })

// 数组精确匹配
db.users.find({ hobbies: ["游泳", "阅读"] })

// 数组多个元素
db.users.find({ hobbies: { $all: ["游泳", "阅读"] } })

// 数组大小
db.users.find({ hobbies: { $size: 3 } })

// 数组元素匹配
db.users.find({ "hobbies.0": "游泳" })  // 第一个元素是"游泳"

// $elemMatch
db.users.find({
  scores: {
    $elemMatch: {
      $gte: 80,
      $lt: 90
    }
  }
})

5.5 其他查询运算符

// 存在性查询
db.users.find({ email: { $exists: true } })
db.users.find({ middle_name: { $exists: false } })

// 类型查询
db.users.find({ age: { $type: "int" } })
db.users.find({ name: { $type: "string" } })

// 文本搜索(需要文本索引)
db.articles.find({ $text: { $search: "mongodb tutorial" } })

// 查询空值
db.users.find({ email: null })
db.users.find({ email: { $eq: null } })

5.6 查询修饰符

// 排序
db.users.find().sort({ age: 1 })      // 升序
db.users.find().sort({ age: -1 })     // 降序
db.users.find().sort({ age: 1, name: -1 })  // 多字段排序

// 限制数量
db.users.find().limit(10)

// 跳过文档
db.users.find().skip(20)

// 分页查询(第2页,每页10条)
db.users.find()
  .skip(10)
  .limit(10)
  .sort({ created_at: -1 })

// 计数
db.users.countDocuments()
db.users.countDocuments({ status: "active" })
db.users.estimatedDocumentCount()  // 更快但不准确

// 去重
db.users.distinct("city")
db.users.distinct("status", { age: { $gt: 25 } })

六、更新操作

6.1 更新运算符

运算符 描述 示例
$set 设置字段值 {$set: {status: "active"}}
$unset 删除字段 {$unset: {middle_name: ""}}
$inc 增减数值 {$inc: {age: 1}}
$mul 乘以数值 {$mul: {price: 1.1}}
$rename 重命名字段 {$rename: {"phone": "mobile"}}
$min 如果小于当前值则更新 {$min: {score: 90}}
$max 如果大于当前值则更新 {$max: {score: 90}}
$currentDate 设置当前日期 {$currentDate: {updated_at: true}}

6.2 数组更新运算符

运算符 描述 示例
$push 向数组添加元素 {$push: {tags: "new"}}
$addToSet 向数组添加不重复元素 {$addToSet: {tags: "unique"}}
$pop 删除数组元素 {$pop: {tags: 1}}
$pull 删除匹配元素 {$pull: {tags: "old"}}
$pullAll 删除多个元素 {$pullAll: {tags: ["a", "b"]}}
$each 与$push/$addToSet一起添加多个 {$push: {tags: {$each: ["a", "b"]}}}

6.3 更新方法

// updateOne - 更新单条文档
db.users.updateOne(
  { name: "张三" },
  { 
    $set: { age: 26, status: "vip" },
    $currentDate: { updated_at: true }
  }
)

// updateMany - 更新多条文档
db.users.updateMany(
  { age: { $lt: 18 } },
  { $set: { category: "未成年" } }
)

// replaceOne - 替换整个文档
db.users.replaceOne(
  { name: "张三" },
  {
    name: "张三",
    age: 27,
    email: "new_email@example.com",
    updated_at: new Date()
  }
)

// 带选项的更新
db.users.updateOne(
  { email: "new@example.com" },
  { $set: { status: "active" } },
  { upsert: true }  // 如果不存在则插入
)

// 批量更新示例
db.products.updateMany(
  {},
  { 
    $inc: { view_count: 1 },
    $set: { last_viewed: new Date() }
  }
)

6.4 数组更新示例

// 向数组添加元素
db.users.updateOne(
  { name: "张三" },
  { $push: { hobbies: "游泳" } }
)

// 向数组添加多个元素
db.users.updateOne(
  { name: "张三" },
  { 
    $push: { 
      hobbies: { 
        $each: ["编程", "阅读"],
        $position: 0,  // 插入到数组开头
        $slice: 5      // 限制数组最多5个元素
      }
    }
  }
)

// 添加不重复元素
db.users.updateOne(
  { name: "张三" },
  { $addToSet: { tags: "VIP" } }
)

// 删除数组元素
db.users.updateOne(
  { name: "张三" },
  { $pop: { hobbies: 1 } }    // 1:删除最后一个,-1:删除第一个
)

db.users.updateOne(
  { name: "张三" },
  { $pull: { hobbies: "游戏" } }
)

// 更新数组中的特定元素
db.users.updateOne(
  { "hobbies": "游泳" },
  { $set: { "hobbies.$": "游泳运动" } }
)

七、删除操作

// deleteOne - 删除单条文档
db.users.deleteOne({ name: "张三" })

// deleteMany - 删除多条文档
db.users.deleteMany({ status: "inactive" })
db.users.deleteMany({ age: { $lt: 18 } })

// 删除所有文档(清空集合)
db.users.deleteMany({})

// 删除整个集合
db.users.drop()

八、索引操作

8.1 创建索引

// 单字段索引
db.users.createIndex({ email: 1 })      // 升序索引
db.users.createIndex({ created_at: -1 }) // 降序索引

// 复合索引
db.users.createIndex({ last_name: 1, first_name: 1 })

// 多键索引(数组字段)
db.users.createIndex({ tags: 1 })

// 文本索引
db.articles.createIndex(
  { title: "text", content: "text" },
  { 
    weights: { title: 10, content: 5 },
    default_language: "english"
  }
)

// 地理空间索引
db.places.createIndex({ location: "2dsphere" })
db.places.createIndex({ coordinates: "2d" })  // 平面地理空间

// 哈希索引
db.users.createIndex({ user_id: "hashed" })

// 唯一索引
db.users.createIndex({ email: 1 }, { unique: true })

// 部分索引
db.users.createIndex(
  { status: 1 },
  { partialFilterExpression: { status: { $exists: true } } }
)

// 稀疏索引
db.users.createIndex({ middle_name: 1 }, { sparse: true })

// TTL索引(自动过期)
db.sessions.createIndex(
  { created_at: 1 },
  { expireAfterSeconds: 3600 }  // 1小时后自动删除
)

// 隐藏索引(测试用)
db.users.createIndex({ test_field: 1 }, { hidden: true })

8.2 索引选项

选项 描述 示例
unique 唯一索引
sparse 稀疏索引
background 后台创建
name 索引名称
partialFilterExpression 部分索引条件 {partialFilterExpression: {status: "active"}}
expireAfterSeconds TTL时间
weights 文本索引权重 {weights: {title: 10}}
default_language 默认语言

8.3 索引管理

// 查看所有索引
db.users.getIndexes()

// 查看索引大小
db.users.totalIndexSize()
db.users.stats().indexSizes

// 删除索引
db.users.dropIndex("email_1")
db.users.dropIndex({ "last_name": 1, "first_name": 1 })

// 删除所有索引(除了_id)
db.users.dropIndexes()

// 重建索引
db.users.reIndex()

// 查看索引使用情况
db.users.aggregate([{ $indexStats: {} }])

// 解释查询计划
db.users.find({ email: "test@example.com" }).explain("executionStats")

// 强制使用指定索引
db.users.find({ email: "test@example.com" })
  .hint({ email: 1 })

九、聚合框架

9.1 聚合管道阶段

阶段 描述 示例
$match 过滤文档 {$match: {status: "active"}}
$group 分组统计 {$group: {_id: "$city", count: {$sum: 1}}}
$project 字段投影 {$project: {name: 1, email: 1}}
$sort 排序 {$sort: {age: -1}}
$limit 限制数量
$skip 跳过文档
$unwind 展开数组
$lookup 关联查询 {$lookup: {from: "orders", ...}}
$facet 多维度聚合 {$facet: {...}}
$bucket 分桶 {$bucket: {...}}

9.2 聚合操作符

累加器操作符(用于$group)

$sum      // 求和
$avg      // 平均值
$min      // 最小值
$max      // 最大值
$first    // 第一个值
$last     // 最后一个值
$push     // 数组
$addToSet // 不重复数组

其他操作符

// 算术操作符
$add, $subtract, $multiply, $divide, $mod

// 比较操作符
$eq, $ne, $gt, $gte, $lt, $lte

// 逻辑操作符
$and, $or, $not

// 字符串操作符
$concat, $substr, $toLower, $toUpper

// 日期操作符
$year, $month, $dayOfMonth, $hour, $minute, $second

9.3 聚合示例

// 基本分组统计
db.orders.aggregate([
  {
    $group: {
      _id: "$customer_id",
      total_amount: { $sum: "$amount" },
      avg_amount: { $avg: "$amount" },
      order_count: { $sum: 1 },
      max_amount: { $max: "$amount" },
      min_amount: { $min: "$amount" },
      first_order: { $first: "$order_date" },
      last_order: { $last: "$order_date" },
      all_orders: { $push: "$order_id" },
      unique_products: { $addToSet: "$product_id" }
    }
  }
])

// 多阶段聚合
db.sales.aggregate([
  // 1. 过滤数据
  { $match: { 
      date: { 
        $gte: new Date("2024-01-01"),
        $lt: new Date("2024-02-01")
      }
    }
  },
  
  // 2. 分组统计
  { $group: {
      _id: {
        year: { $year: "$date" },
        month: { $month: "$date" },
        day: { $dayOfMonth: "$date" }
      },
      total_sales: { $sum: "$amount" },
      avg_sale: { $avg: "$amount" },
      transaction_count: { $sum: 1 }
    }
  },
  
  // 3. 字段投影
  { $project: {
      date: {
        $concat: [
          { $toString: "$_id.year" }, "-",
          { $toString: "$_id.month" }, "-",
          { $toString: "$_id.day" }
        ]
      },
      total_sales: 1,
      avg_sale: { $round: ["$avg_sale", 2] },
      transaction_count: 1,
      _id: 0
    }
  },
  
  // 4. 排序
  { $sort: { date: 1 } },
  
  // 5. 限制结果
  { $limit: 10 }
])

// 展开数组并统计
db.users.aggregate([
  { $unwind: "$hobbies" },
  { $group: {
      _id: "$hobbies",
      user_count: { $sum: 1 }
    }
  },
  { $sort: { user_count: -1 } }
])

// 关联查询
db.orders.aggregate([
  {
    $lookup: {
      from: "customers",
      localField: "customer_id",
      foreignField: "_id",
      as: "customer_info"
    }
  },
  {
    $lookup: {
      from: "products",
      localField: "product_id",
      foreignField: "_id",
      as: "product_info"
    }
  }
])

// 多维度聚合
db.sales.aggregate([
  {
    $facet: {
      "total_stats": [
        { $group: {
            _id: null,
            total_revenue: { $sum: "$amount" },
            avg_order_value: { $avg: "$amount" }
          }
        }
      ],
      "category_stats": [
        { $group: {
            _id: "$category",
            revenue: { $sum: "$amount" },
            count: { $sum: 1 }
          }
        },
        { $sort: { revenue: -1 } },
        { $limit: 5 }
      ],
      "daily_trend": [
        { $group: {
            _id: { 
              $dateToString: { 
                format: "%Y-%m-%d", 
                date: "$date" 
              }
            },
            revenue: { $sum: "$amount" }
          }
        },
        { $sort: { _id: 1 } },
        { $limit: 30 }
      ]
    }
  }
])

// 分桶统计
db.products.aggregate([
  {
    $bucket: {
      groupBy: "$price",
      boundaries: [0, 50, 100, 200, 500, 1000],
      default: "1000+",
      output: {
        count: { $sum: 1 },
        avg_rating: { $avg: "$rating" },
        products: { 
          $push: { 
            name: "$name", 
            price: "$price" 
          }
        }
      }
    }
  }
])

// 条件聚合
db.employees.aggregate([
  {
    $project: {
      name: 1,
      salary: 1,
      bonus_level: {
        $switch: {
          branches: [
            { case: { $gte: ["$salary", 100000] }, then: "A" },
            { case: { $gte: ["$salary", 50000] }, then: "B" },
            { case: { $gte: ["$salary", 30000] }, then: "C" }
          ],
          default: "D"
        }
      }
    }
  }
])

十、事务管理

10.1 事务基本操作

// 开始一个会话
session = db.getMongo().startSession()

// 开始事务
session.startTransaction({
  readConcern: { level: "snapshot" },
  writeConcern: { w: "majority" }
})

try {
  // 在事务中执行操作
  db.users.insertOne(
    { name: "张三", balance: 1000 },
    { session: session }
  )
  
  db.accounts.updateOne(
    { user_id: "123" },
    { $inc: { balance: -1000 } },
    { session: session }
  )
  
  // 提交事务
  session.commitTransaction()
} catch (error) {
  // 回滚事务
  session.abortTransaction()
  throw error
} finally {
  // 结束会话
  session.endSession()
}

10.2 事务选项

// 读取关注级别
readConcern: { level: "local" }       // 默认
readConcern: { level: "majority" }    // 多数节点确认
readConcern: { level: "snapshot" }    // 快照隔离

// 写入关注级别
writeConcern: { w: 1 }                // 默认,主节点确认
writeConcern: { w: "majority" }       // 多数节点确认
writeConcern: { w: 1, j: true }       // 写入journal
writeConcern: { w: 1, wtimeout: 5000 } // 5秒超时

// 事务选项
{
  readConcern: { level: "snapshot" },
  writeConcern: { w: "majority" },
  readPreference: "primary",          // 只从主节点读取
  maxCommitTimeMS: 10000              // 10秒超时
}

十一、用户和权限管理

11.1 创建和管理用户

// 切换到admin数据库
use admin

// 创建管理员用户
db.createUser({
  user: "admin",
  pwd: "Admin123!",
  roles: [
    { role: "root", db: "admin" }
  ]
})

// 创建数据库用户
use mydb
db.createUser({
  user: "appuser",
  pwd: "App123!",
  roles: [
    { role: "readWrite", db: "mydb" },
    { role: "read", db: "reporting" }
  ]
})

// 查看用户
db.getUsers()

// 更新用户
db.updateUser("appuser", {
  pwd: "NewPassword123!",
  roles: [
    { role: "readWrite", db: "mydb" },
    { role: "dbAdmin", db: "mydb" }
  ]
})

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

// 修改密码
db.changeUserPassword("username", "newPassword")

11.2 内置角色

角色 权限描述
数据库用户角色
read 读取数据
readWrite 读写数据
数据库管理角色
dbAdmin 数据库管理操作
userAdmin 用户管理
dbOwner 数据库所有者
集群管理角色
clusterAdmin 集群管理
clusterManager 集群管理(部分权限)
hostManager 主机管理
备份恢复角色
backup 备份数据
restore 恢复数据
所有数据库角色
readAnyDatabase 所有数据库读取
readWriteAnyDatabase 所有数据库读写
userAdminAnyDatabase 所有数据库用户管理
dbAdminAnyDatabase 所有数据库管理
超级权限
root 超级用户权限

11.3 启用认证

# 1. 启动时启用认证
mongod --auth

# 2. 或在配置文件中启用
security:
  authorization: enabled

十二、备份与恢复

12.1 使用命令行工具

# 备份整个数据库
mongodump --host localhost --port 27017 --out /backup/

# 备份指定数据库
mongodump --db mydb --out /backup/

# 备份指定集合
mongodump --collection users --db mydb --out /backup/

# 带认证的备份
mongodump -u admin -p password --authenticationDatabase admin

# 压缩备份
mongodump --gzip --out /backup/

# 恢复数据库
mongorestore --host localhost --port 27017 /backup/mydb/

# 恢复指定集合
mongorestore --collection users --db mydb /backup/mydb/users.bson

# 恢复时删除现有数据
mongorestore --drop /backup/mydb/

# 导入导出JSON数据
mongoexport --db mydb --collection users --out users.json
mongoimport --db mydb --collection users --file users.json

12.2 备份脚本示例

#!/bin/bash
# backup_mongo.sh

BACKUP_DIR="/data/backup/mongodb"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_PATH="$BACKUP_DIR/$DATE"

# 创建备份目录
mkdir -p $BACKUP_PATH

# 备份所有数据库
mongodump --host localhost --port 27017 \
  -u admin -p "password" \
  --authenticationDatabase admin \
  --out $BACKUP_PATH \
  --gzip

# 保留最近7天的备份
find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} \;

echo "Backup completed: $BACKUP_PATH"

十三、监控与性能优化

13.1 监控命令

// 查看服务器状态
db.serverStatus()

// 查看当前操作
db.currentOp()

// 杀死操作
db.killOp(opid)

// 查看数据库统计
db.stats()

// 查看集合统计
db.users.stats()

// 查看连接信息
db.serverStatus().connections

// 查看内存使用
db.serverStatus().mem

// 查看网络统计
db.serverStatus().network

// 查看存储引擎统计
db.serverStatus().wiredTiger

13.2 性能分析

// 启用慢查询日志
db.setProfilingLevel(1, 100)  // 记录超过100ms的操作
db.setProfilingLevel(2)       // 记录所有操作
db.setProfilingLevel(0)       // 关闭分析

// 查看分析结果
db.system.profile.find().limit(10).sort({ ts: -1 })

// 解释查询计划
db.users.find({ email: "test@example.com" }).explain("executionStats")

// 验证集合完整性
db.users.validate({ full: true })

// 修复集合
db.repairDatabase()

13.3 性能优化建议

  1. 索引优化
    • 为查询字段创建合适的索引
    • 使用复合索引覆盖查询
    • 避免在频繁更新的字段上创建索引
  2. 查询优化
    • 使用投影只返回需要的字段
    • 避免全表扫描
    • 使用分页限制返回数据量
  3. 架构设计
    • 合理设计文档结构
    • 适当使用嵌入文档和引用
    • 考虑数据访问模式
  4. 硬件和配置
    • 确保足够的内存
    • 使用SSD硬盘
    • 调整连接池大小

十四、副本集

14.1 配置副本集

# 1. 启动三个MongoDB实例
mongod --replSet rs0 --port 27017 --dbpath /data/db1
mongod --replSet rs0 --port 27018 --dbpath /data/db2
mongod --replSet rs0 --port 27019 --dbpath /data/db3

# 2. 连接到主节点并初始化
mongo --port 27017

# 3. 初始化副本集
rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "localhost:27017" },
    { _id: 1, host: "localhost:27018" },
    { _id: 2, host: "localhost:27019" }
  ]
})

# 4. 查看副本集状态
rs.status()

# 5. 添加节点
rs.add("localhost:27020")

# 6. 移除节点
rs.remove("localhost:27020")

14.2 副本集命令

// 查看状态
rs.status()
rs.conf()

// 强制重新配置
rs.reconfig(config, {force: true})

// 降级主节点
rs.stepDown(300)  // 300秒内不参与选举

// 冻结节点
rs.freeze(100)  // 100秒内不参与选举

// 查看从节点状态
rs.secondaryOk()

// 同步状态
rs.printReplicationInfo()
rs.printSlaveReplicationInfo()

十五、分片集群

15.1 分片组件

# 配置服务器(存储元数据)
mongod --configsvr --replSet configRS --port 27019

# 路由服务器(mongos)
mongos --configdb configRS/localhost:27019 --port 27017

# 分片服务器
mongod --shardsvr --replSet shard1 --port 27018

15.2 分片管理

// 连接到mongos
mongo --port 27017

// 添加分片
sh.addShard("shard1/localhost:27018")

// 启用数据库分片
sh.enableSharding("mydb")

// 创建分片键
sh.shardCollection("mydb.users", { user_id: 1 })

// 查看分片状态
sh.status()
sh.getBalancerState()

// 平衡器控制
sh.startBalancer()
sh.stopBalancer()

// 数据迁移状态
sh.isBalancerRunning()

十六、常用工具和技巧

16.1 导入导出数据

# 从CSV导入
mongoimport --db mydb --collection users --type csv --headerline --file users.csv

# 导出为CSV
mongoexport --db mydb --collection users --type csv --fields name,age,email --out users.csv

# 从JSON文件导入
mongoimport --db mydb --collection users --file users.json

# 导出为JSON数组
mongoexport --db mydb --collection users --jsonArray --out users.json

16.2 批量操作脚本

// 批量插入
var bulk = db.users.initializeUnorderedBulkOp();
for (var i = 0; i < 1000; i++) {
  bulk.insert({ 
    name: "user" + i, 
    value: i,
    created_at: new Date()
  });
}
bulk.execute();

// 批量更新
var bulk = db.users.initializeOrderedBulkOp();
bulk.find({ status: "pending" }).update({ $set: { status: "processed" } });
bulk.find({ age: { $lt: 18 } }).update({ $set: { category: "minor" } });
bulk.execute();

16.3 JavaScript函数

// 创建存储函数
db.system.js.save({
  _id: "calculateAge",
  value: function(birthYear) {
    return new Date().getFullYear() - birthYear;
  }
});

// 使用存储函数
db.loadServerScripts();
db.users.find().forEach(function(user) {
  print("Age:", calculateAge(user.birth_year));
});

// 在查询中使用函数
db.users.find({
  $where: function() {
    return this.age > 18 && this.status === "active";
  }
});

十七、故障排除

17.1 常见问题解决

# 1. 连接失败
# 检查服务是否启动
sudo systemctl status mongod

# 检查端口是否监听
sudo netstat -tlnp | grep 27017

# 检查防火墙
sudo firewall-cmd --list-all
sudo firewall-cmd --add-port=27017/tcp --permanent

# 2. 认证失败
# 检查用户密码
# 检查认证数据库

# 3. 磁盘空间不足
# 检查磁盘使用
df -h

# 清理日志文件
sudo rm /var/log/mongodb/mongod.log
sudo systemctl restart mongod

# 4. 内存不足
# 检查内存使用
free -h

# 调整缓存大小
mongod --wiredTigerCacheSizeGB 2

# 5. 修复损坏的数据库
mongod --repair --dbpath /var/lib/mongo

17.2 日志分析

# 查看实时日志
sudo tail -f /var/log/mongodb/mongod.log

# 查看错误日志
sudo grep -i error /var/log/mongodb/mongod.log

# 查看慢查询
sudo grep "slow query" /var/log/mongodb/mongod.log

# 分析日志文件
mongod --logpath /var/log/mongodb/mongod.log --logappend

十八、最佳实践

18.1 设计指南

  1. 文档设计
    • 根据查询模式设计文档结构
    • 适当使用嵌入和引用
    • 控制文档大小(建议小于16MB)
  2. 索引策略
    • 为所有查询创建合适的索引
    • 使用复合索引覆盖查询
    • 定期监控和优化索引
  3. 安全实践
    • 启用认证和授权
    • 使用TLS加密连接
    • 定期备份数据
    • 限制网络访问
  4. 性能优化
    • 监控慢查询
    • 合理使用分页
    • 批量操作减少网络往返

18.2 监控清单

# 每日检查
1. 检查磁盘空间
2. 检查内存使用
3. 查看慢查询日志
4. 检查复制延迟
5. 验证备份完整性

# 每周检查
1. 分析索引使用情况
2. 清理无用索引
3. 检查集合碎片
4. 更新统计信息

十九、常用命令速查

19.1 快速参考

// 连接
mongo
mongo --host hostname --port 27017

// 基本信息
show dbs
show collections
show users
show profile
show logs

// 数据库操作
use dbname
db.dropDatabase()
db.cloneDatabase("hostname")
db.copyDatabase("from", "to", "hostname")

// 集合操作
db.createCollection(name, options)
db.collection.drop()
db.collection.renameCollection(newName)
db.collection.stats()

// 文档操作
db.collection.insert()
db.collection.find()
db.collection.update()
db.collection.remove()
db.collection.count()

// 索引操作
db.collection.createIndex()
db.collection.getIndexes()
db.collection.dropIndex()
db.collection.reIndex()

// 聚合
db.collection.aggregate(pipeline)

// 管理
db.currentOp()
db.killOp()
db.fsyncLock()
db.fsyncUnlock()

19.2 退出和帮助

// 退出mongo shell
exit
quit()
Ctrl + D

// 获取帮助
help
db.help()
db.collection.help()
db.collection.find().help()

// 查看命令历史
history
posted @ 2025-12-24 02:11  binlicoder  阅读(2)  评论(0)    收藏  举报