MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

MongoDB数据库管理基础

2023-08-213.3k 阅读

一、MongoDB 基础概念

MongoDB 是一个基于分布式文件存储的开源数据库系统,由 C++ 语言编写。它旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

1.1 数据模型

MongoDB 使用一种称为 BSON(Binary JSON)的二进制序列化格式来表示数据。BSON 类似于 JSON,但支持更多的数据类型,并且在空间和时间效率上更高。在 MongoDB 中,数据以文档(document)的形式存储,文档是一个键值对(key - value pairs)的集合。例如,一个简单的用户文档可以如下表示:

{
    "name": "John Doe",
    "age": 30,
    "email": "johndoe@example.com",
    "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "state": "CA",
        "zip": "12345"
    }
}

文档可以嵌套和包含数组,这使得 MongoDB 能够轻松处理复杂的数据结构。例如,一个包含多个爱好的用户文档:

{
    "name": "Jane Smith",
    "hobbies": ["reading", "swimming", "painting"]
}

1.2 集合(Collection)

集合是一组文档的容器。它类似于关系型数据库中的表,但集合没有固定的模式(schema)。这意味着集合中的文档可以具有不同的结构。例如,一个名为 users 的集合可以同时包含具有不同字段的用户文档:

// 第一个用户文档
{
    "name": "Alice",
    "age": 25
}
// 第二个用户文档
{
    "name": "Bob",
    "email": "bob@example.com",
    "phone": "123 - 456 - 7890"
}

这种灵活性使得 MongoDB 在处理不断变化的数据结构时非常方便,尤其适合于敏捷开发和快速迭代的项目。

1.3 数据库(Database)

MongoDB 可以包含多个数据库,每个数据库都有自己的一组集合。数据库用于隔离不同的应用程序数据或不同的业务模块数据。例如,一个电子商务应用可能有一个数据库用于存储用户数据,另一个数据库用于存储产品数据。在 MongoDB 中,数据库名称是区分大小写的,并且有一些命名限制,例如不能包含空字符、点(.)等特殊字符。

二、MongoDB 安装与启动

2.1 安装 MongoDB

  • Windows 系统
    1. 从 MongoDB 官方网站(https://www.mongodb.com/try/download/community)下载适合 Windows 系统的安装包。
    2. 运行安装包,按照安装向导提示进行安装。在安装过程中,可以选择自定义安装路径等选项。默认情况下,MongoDB 会安装到 C:\Program Files\MongoDB\Server\版本号\ 目录下。
    3. 安装完成后,需要创建数据目录。默认情况下,MongoDB 使用 C:\data\db 作为数据存储目录。如果该目录不存在,需要手动创建。
  • Linux 系统(以 Ubuntu 为例)
    1. 导入 MongoDB 的 GPG 密钥:
wget -qO - https://www.mongodb.org/static/pgp/server - 6.0.asc | sudo apt - key add -
2. 创建 MongoDB 的软件源列表文件:
echo "deb [ arch = amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb - org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb - org - 6.0.list
3. 更新软件包列表并安装 MongoDB:
sudo apt update
sudo apt install - y mongodb - org
  • MacOS 系统
    1. 可以使用 Homebrew 进行安装。首先确保已经安装了 Homebrew,如果没有安装,可以运行以下命令安装:
/bin/bash - c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
2. 安装 MongoDB:
brew install mongodb - community

2.2 启动 MongoDB

  • Windows 系统:打开命令提示符,切换到 MongoDB 的 bin 目录(例如 C:\Program Files\MongoDB\Server\版本号\bin),然后运行以下命令启动 MongoDB 服务:
mongod

如果希望将 MongoDB 作为系统服务运行,可以使用以下命令安装服务:

mongod --config "C:\Program Files\MongoDB\Server\版本号\bin\mongod.cfg" --install

然后使用 net start MongoDB 命令启动服务。

  • Linux 系统:在 Ubuntu 上,安装完成后 MongoDB 会自动作为服务启动。可以使用以下命令管理服务:
# 启动 MongoDB 服务
sudo systemctl start mongod
# 停止 MongoDB 服务
sudo systemctl stop mongod
# 重启 MongoDB 服务
sudo systemctl restart mongod
  • MacOS 系统:使用 Homebrew 安装后,可以使用以下命令启动 MongoDB:
brew services start mongodb - community

要停止服务,可以使用:

brew services stop mongodb - community

三、MongoDB 基本操作

3.1 连接到 MongoDB

可以使用 MongoDB 自带的 mongo 命令行工具连接到运行中的 MongoDB 实例。在命令行中运行 mongo 命令,如果 MongoDB 运行在本地默认端口(27017),则会直接连接到本地数据库。如果 MongoDB 运行在其他主机或端口,可以使用以下命令连接:

mongo <主机地址>:<端口号>

例如,连接到运行在 192.168.1.100 主机上,端口为 27018 的 MongoDB 实例:

mongo 192.168.1.100:27018

连接成功后,会进入 mongo 命令行界面,显示类似以下的提示符:

MongoDB shell version v6.0.3
connecting to: mongodb://127.0.0.1:27017/?directConnection = true&serverSelectionTimeoutMS = 2000&appName = mongosh + 1.6.1
Implicit session: session { "id": UUID("660c2974 - 4e68 - 4a65 - 9c49 - 99d996c37d16") }
MongoDB server version: 6.0.3
>

3.2 创建数据库和集合

在 MongoDB 中,数据库和集合是在插入文档时自动创建的。例如,要创建一个名为 testdb 的数据库,并在其中创建一个名为 testcollection 的集合,可以使用以下代码:

use testdb
db.testcollection.insertOne({ "name": "First Document" })

在上述代码中,use testdb 命令用于切换到 testdb 数据库,如果该数据库不存在,则会在插入文档时自动创建。db.testcollection.insertOne({ "name": "First Document" }) 命令用于向 testcollection 集合中插入一个文档,同时如果 testcollection 集合不存在,也会自动创建。

3.3 插入文档

  • 插入单个文档:使用 insertOne 方法插入单个文档。例如,向 users 集合中插入一个用户文档:
db.users.insertOne({
    "name": "Charlie",
    "age": 28,
    "email": "charlie@example.com"
})

插入成功后,insertOne 方法会返回一个包含插入文档的 _id 的对象,例如:

{
    "acknowledged": true,
    "insertedId": ObjectId("6459d89a2d96c1475c59e193")
}

_id 是 MongoDB 为每个文档自动生成的唯一标识符,如果在插入文档时没有指定 _id,MongoDB 会自动生成一个 ObjectId 类型的 _id

  • 插入多个文档:使用 insertMany 方法插入多个文档。例如,向 products 集合中插入多个产品文档:
db.products.insertMany([
    { "name": "Product 1", "price": 10.99 },
    { "name": "Product 2", "price": 19.99 },
    { "name": "Product 3", "price": 5.99 }
])

insertMany 方法返回一个包含插入结果的对象,其中包含插入的文档数量和每个文档的 _id

{
    "acknowledged": true,
    "insertedIds": [
        ObjectId("6459d90e2d96c1475c59e194"),
        ObjectId("6459d90e2d96c1475c59e195"),
        ObjectId("6459d90e2d96c1475c59e196")
    ]
}

3.4 查询文档

  • 基本查询:使用 find 方法进行基本查询。例如,查询 users 集合中所有年龄大于 25 岁的用户:
db.users.find({ "age": { $gt: 25 } })

上述代码中,$gt 是一个比较操作符,表示“大于”。find 方法返回匹配条件的文档游标,可以使用 pretty() 方法格式化输出结果:

db.users.find({ "age": { $gt: 25 } }).pretty()
  • 投影查询:可以指定返回文档的字段,实现投影查询。例如,只查询用户的姓名和邮箱,不返回年龄:
db.users.find({ }, { "name": 1, "email": 1, "_id": 0 })

在投影中,指定为 1 的字段表示包含该字段,指定为 0 的字段表示排除该字段。_id 字段默认会包含在结果中,如果不想返回 _id 字段,需要显式指定 _id: 0

3.5 更新文档

  • 更新单个文档:使用 updateOne 方法更新单个文档。例如,将 users 集合中姓名为 Charlie 的用户年龄更新为 29 岁:
db.users.updateOne(
    { "name": "Charlie" },
    { $set: { "age": 29 } }
)

updateOne 方法的第一个参数是查询条件,用于确定要更新的文档;第二个参数使用 $set 操作符指定要更新的字段和新的值。

  • 更新多个文档:使用 updateMany 方法更新多个文档。例如,将 products 集合中所有价格小于 10 的产品价格提高 10%:
db.products.updateMany(
    { "price": { $lt: 10 } },
    { $mul: { "price": 1.1 } }
)

这里使用 $mul 操作符对匹配的文档的 price 字段进行乘法运算,实现价格提高 10%。

3.6 删除文档

  • 删除单个文档:使用 deleteOne 方法删除单个文档。例如,删除 users 集合中姓名为 Charlie 的用户:
db.users.deleteOne({ "name": "Charlie" })

deleteOne 方法的参数是查询条件,用于确定要删除的文档。

  • 删除多个文档:使用 deleteMany 方法删除多个文档。例如,删除 products 集合中所有价格大于 50 的产品:
db.products.deleteMany({ "price": { $gt: 50 } })

四、MongoDB 索引管理

4.1 索引的概念

索引在 MongoDB 中类似于书籍的目录,它可以加速查询操作。通过在一个或多个字段上创建索引,MongoDB 可以更快地定位到符合查询条件的文档,而不必扫描整个集合。例如,如果经常根据用户的邮箱查询用户文档,在 email 字段上创建索引可以显著提高查询性能。

4.2 创建索引

  • 单字段索引:使用 createIndex 方法在单个字段上创建索引。例如,在 users 集合的 email 字段上创建索引:
db.users.createIndex({ "email": 1 })

这里的 1 表示升序索引,如果使用 -1 则表示降序索引。

  • 复合索引:在多个字段上创建复合索引。例如,在 orders 集合的 customer_idorder_date 字段上创建复合索引:
db.orders.createIndex({ "customer_id": 1, "order_date": -1 })

复合索引的顺序很重要,查询条件与索引字段顺序匹配时,索引才能发挥最佳效果。

4.3 查看索引

使用 getIndexes 方法可以查看集合上的所有索引。例如,查看 users 集合的索引:

db.users.getIndexes()

返回结果类似以下格式:

[
    {
        "v": 2,
        "key": {
            "_id": 1
        },
        "name": "_id_",
        "ns": "testdb.users"
    },
    {
        "v": 2,
        "key": {
            "email": 1
        },
        "name": "email_1",
        "ns": "testdb.users"
    }
]

每个索引文档包含索引版本(v)、索引键(key)、索引名称(name)和所属集合(ns)等信息。

4.4 删除索引

使用 dropIndex 方法删除索引。例如,删除 users 集合上名为 email_1 的索引:

db.users.dropIndex("email_1")

也可以使用索引键对象来删除索引,例如:

db.users.dropIndex({ "email": 1 })

五、MongoDB 聚合操作

5.1 聚合的概念

聚合操作允许对数据进行分组、统计、转换等复杂操作,类似于关系型数据库中的 GROUP BYSUMAVG 等操作。MongoDB 的聚合框架使用管道(pipeline)的概念,将多个操作连接在一起,每个操作处理前一个操作的输出,并将结果传递给下一个操作。

5.2 聚合管道操作符

  • $match:用于过滤文档,只允许符合条件的文档进入下一个管道阶段。例如,在 orders 集合中筛选出金额大于 100 的订单:
db.orders.aggregate([
    { $match: { "amount": { $gt: 100 } } }
])
  • $group:用于分组文档,并对每个组进行统计操作。例如,按客户 ID 分组订单,并计算每个客户的订单总金额:
db.orders.aggregate([
    { $group: {
        _id: "$customer_id",
        total_amount: { $sum: "$amount" }
    } }
])

$group 操作中,_id 字段指定分组的依据,这里使用 $customer_id 表示按 customer_id 字段分组。total_amount 字段使用 $sum 操作符计算每个组的 amount 字段总和。

  • $project:用于投影操作,选择要包含在输出文档中的字段。例如,在聚合结果中只保留客户 ID 和订单总金额,并将字段名改为更友好的名称:
db.orders.aggregate([
    { $group: {
        _id: "$customer_id",
        total_amount: { $sum: "$amount" }
    } },
    { $project: {
        customer_id: "$_id",
        total_amount: 1,
        _id: 0
    } }
])

这里将 _id 重命名为 customer_id,并排除 _id 字段。

5.3 复杂聚合示例

假设 products 集合包含产品的名称、价格和类别信息,要计算每个类别的产品平均价格,并筛选出平均价格大于 50 的类别,可以使用以下聚合操作:

db.products.aggregate([
    { $group: {
        _id: "$category",
        average_price: { $avg: "$price" }
    } },
    { $match: { "average_price": { $gt: 50 } } },
    { $project: {
        category: "$_id",
        average_price: 1,
        _id: 0
    } }
])

这个聚合操作首先按类别分组产品,计算每个类别的平均价格;然后筛选出平均价格大于 50 的类别;最后投影输出类别和平均价格,排除 _id 字段。

六、MongoDB 备份与恢复

6.1 备份

  • 使用 mongodump 工具mongodump 工具用于备份 MongoDB 数据库。可以在命令行中运行以下命令备份整个数据库:
mongodump --uri="mongodb://127.0.0.1:27017"

上述命令会在当前目录下创建一个 dump 目录,并将数据库中的所有数据备份到该目录中。如果要备份特定的数据库,可以使用 --db 选项,例如备份 testdb 数据库:

mongodump --uri="mongodb://127.0.0.1:27017" --db testdb

如果要备份特定的集合,可以使用 --collection 选项,例如备份 testdb 数据库中的 users 集合:

mongodump --uri="mongodb://127.0.0.1:27017" --db testdb --collection users

6.2 恢复

  • 使用 mongorestore 工具mongorestore 工具用于恢复 MongoDB 备份。要恢复之前备份的数据库,可以在命令行中运行以下命令:
mongorestore --uri="mongodb://127.0.0.1:27017" dump

这里的 dumpmongodump 生成的备份目录。如果要恢复特定的数据库,可以使用 --db 选项,例如恢复 testdb 数据库:

mongorestore --uri="mongodb://127.0.0.1:27017" --db testdb dump/testdb

如果要恢复特定的集合,可以使用 --collection 选项,例如恢复 testdb 数据库中的 users 集合:

mongorestore --uri="mongodb://127.0.0.1:27017" --db testdb --collection users dump/testdb/users.bson

七、MongoDB 安全管理

7.1 用户管理

  • 创建用户:在 MongoDB 中,可以使用 createUser 方法创建用户。例如,在 admin 数据库中创建一个具有管理员权限的用户:
use admin
db.createUser({
    user: "adminuser",
    pwd: "password123",
    roles: [ { role: "root", db: "admin" } ]
})

这里创建了一个名为 adminuser 的用户,密码为 password123,并赋予其 root 角色,该角色在 admin 数据库中具有最高权限。

  • 查看用户:使用 getUsers 方法可以查看数据库中的用户。例如,查看 admin 数据库中的用户:
use admin
db.getUsers()
  • 修改用户密码:使用 updateUser 方法修改用户密码。例如,修改 adminuser 的密码:
use admin
db.updateUser("adminuser", { pwd: "newpassword456" })
  • 删除用户:使用 dropUser 方法删除用户。例如,删除 adminuser
use admin
db.dropUser("adminuser")

7.2 身份验证

为了启用身份验证,需要在 MongoDB 的配置文件(通常是 mongod.cfg)中添加以下配置:

security:
  authorization: enabled

然后重启 MongoDB 服务。之后,连接 MongoDB 时需要提供用户名和密码。例如,使用 mongo 命令行工具连接时,可以使用以下命令:

mongo --uri="mongodb://adminuser:password123@127.0.0.1:27017/admin"

这里的 adminuser 是用户名,password123 是密码,admin 是认证数据库。

7.3 网络安全

  • 绑定 IP 地址:在 MongoDB 配置文件中,可以通过 net.bindIp 选项指定 MongoDB 监听的 IP 地址。例如,只监听本地回环地址 127.0.0.1
net:
  bindIp: 127.0.0.1

这样可以防止 MongoDB 暴露在公网上,提高安全性。

  • 防火墙设置:可以使用操作系统的防火墙工具(如 iptables 在 Linux 上)限制对 MongoDB 端口(默认 27017)的访问。例如,在 Linux 上只允许特定 IP 地址访问 MongoDB 端口:
iptables -A INPUT -p tcp --dport 27017 -s 192.168.1.100 -j ACCEPT
iptables -A INPUT -p tcp --dport 27017 -j DROP

上述命令允许 192.168.1.100 访问 MongoDB 端口,拒绝其他所有 IP 地址访问。

通过以上对 MongoDB 数据库管理基础的介绍,涵盖了从基础概念到实际操作、索引管理、聚合操作、备份恢复以及安全管理等方面的内容,希望能帮助读者全面掌握 MongoDB 的基本管理技能,为进一步深入使用 MongoDB 打下坚实的基础。在实际应用中,还需要根据具体的业务需求和场景,灵活运用这些知识,充分发挥 MongoDB 的优势。