MongoDB 的 Schema-less(无模式)特性
MongoDB 不需要提前定义表结构(Schema),可以存储不同结构的文档(JSON/BSON),这与传统的 SQL 关系型数据库(RDBMS)有很大不同。
1. MongoDB 的无模式特性
在 MongoDB 中:
- 每个 集合(Collection) 类似于 SQL 的表(Table)。
- 但集合中的 文档(Document)(类似于 SQL 的行 Row)可以有 不同的字段(Columns),无需固定结构。
- 你可以向同一个集合中插入不同结构的数据,MongoDB 会自动处理这些数据。
示例:MongoDB 允许不同结构的数据
// 同一个集合(people),但结构不同
{ "name": "Alice", "age": 25 }
{ "name": "Bob", "age": 30, "email": "bob@example.com" }
{ "name": "Charlie", "age": 28, "address": "New York", "phone": "123456789" }
这里:
- Alice 只有
name
和age
- Bob 额外有
email
- Charlie 额外有
address
和phone
MongoDB 不会报错,而 SQL 关系数据库(如 MySQL、PostgreSQL)要求所有记录(Row)遵循相同的列结构,否则会导致插入失败。
2. MongoDB vs SQL:结构对比
特性 | MongoDB(NoSQL) | SQL 关系数据库(RDBMS) |
---|---|---|
数据存储单位 | 文档(JSON/BSON) | 表(Table)中的行(Row) |
模式(Schema) | 无模式(Schema-less),字段可以不固定 | 需要预定义模式,所有行必须符合表结构 |
字段约束 | 没有强制约束,字段可以缺失或不同 | 需要在表定义时固定字段和数据类型 |
数据查询 | 使用 BSON 文档查询(MongoDB Query Language) | 使用 SQL 查询 |
扩展性 | 水平扩展(Sharding)较容易 | 垂直扩展为主,水平扩展较难 |
事务 | 事务支持较弱(支持 ACID 事务,但不如 SQL 强大) | 强事务支持(ACID) |
3. MongoDB 与 SQL 主要不同点
插入数据
MongoDB
可以向同一个集合(Collection)中插入不同结构的文档:
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
db = client["testdb"]
collection = db["people"]
# 插入不同结构的数据
collection.insert_one({"name": "Alice", "age": 25})
collection.insert_one({"name": "Bob", "age": 30, "email": "bob@example.com"})
collection.insert_one({"name": "Charlie", "age": 28, "address": "New York"})
# 查询所有数据
for doc in collection.find():
print(doc)
特点:
- 无需创建表结构
- 不同文档的字段可以不同
- 直接插入数据,MongoDB 会自动存储
SQL(MySQL 示例)
CREATE TABLE people (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age INT NOT NULL,
email VARCHAR(255),
address VARCHAR(255)
);
INSERT INTO people (name, age) VALUES ('Alice', 25);
INSERT INTO people (name, age, email) VALUES ('Bob', 30, 'bob@example.com');
INSERT INTO people (name, age, address) VALUES ('Charlie', 28, 'New York');
特点:
- 必须 先定义表结构(CREATE TABLE)
- 插入数据时,必须符合表的字段
- 不能动态增加字段,除非 ALTER TABLE
数据查询
MongoDB
# 查询 name 为 "Alice" 的人
result = collection.find_one({"name": "Alice"})
print(result)
使用 JSON/BSON 格式查询
SQL
SELECT * FROM people WHERE name = 'Alice';
如果字段不存在(例如 phone
),需要 ALTER TABLE 添加
结构变化的影响
MongoDB
如果需要给某些文档增加 phone
字段,可以直接更新:
collection.update_one({"name": "Alice"}, {"$set": {"phone": "123456789"}})
MongoDB 允许文档的字段动态增加,不影响已有数据。
SQL
如果想给 people
表增加 phone
字段:
ALTER TABLE people ADD COLUMN phone VARCHAR(20);
SQL 需要修改整个表结构,否则无法存储新的字段。
4. 什么时候选择 MongoDB?什么时候选择 SQL?
适合 MongoDB 的场景
- 数据结构不固定,经常变化(如电商商品、社交媒体动态)
- 高并发读写,需要快速查询和写入(如日志、IoT 设备数据)
- 海量数据存储,需要水平扩展(如大数据分析)
- JSON 格式存储需求,适用于 RESTful API
适合 SQL 关系数据库的场景
- 数据结构固定,表结构清晰(如银行系统、ERP)
- 强事务支持(ACID)(如金融支付系统)
- 复杂的多表 JOIN 查询(如关系紧密的数据管理)
5. 结论
对比项 | MongoDB(NoSQL) | SQL 关系数据库 |
---|---|---|
模式(Schema) | 无模式(Schema-less),文档字段可以不同 | 固定模式(Schema),表结构必须固定 |
灵活性 | 高,随时增加字段 | 低,需要修改表结构 |
查询方式 | BSON 文档查询(Mongo Query Language) | SQL |
扩展性 | 水平扩展(Sharding)容易 | 主要依赖垂直扩展 |
事务支持 | 基础事务支持(ACID 事务较弱) | 强 ACID 事务支持 |
适用场景 | 非结构化数据、大数据、高并发 | 事务性强、结构清晰的业务 |
MongoDB 更适合灵活性高、数据结构多变的场景,而 SQL 关系数据库更适合结构清晰、事务要求严格的应用。
MongoDB 环境部署
1. 安装 MongoDB
Ubuntu / Debian
sudo apt update
sudo apt install -y mongodb
CentOS / RHEL
sudo yum install -y mongodb-org
Windows
- 前往 MongoDB 官网 下载安装包
- 安装后,确保 MongoDB 在系统可用:
mongod --version
2. 启动 MongoDB
sudo systemctl start mongod
sudo systemctl enable mongod
确保 MongoDB 成功启动:
sudo systemctl status mongod
3. 初始化 MongoDB
MongoDB 需要预先定义数据库文件夹,可以手动创建并在配置文件中修改,也可以按照默认的文件夹路径。
如果需要定制数据目录,可以修改配置文件 /etc/mongod.conf
:
storage:
dbPath: /var/lib/mongodb
systemLog:
destination: file
path: /var/log/mongodb/mongod.log
logAppend: true
修改配置后,重启 MongoDB:
sudo systemctl restart mongod
[!TIP]
有时可能会遇到文件权限问题,可以首先手动启动数据库
mongod
查看报错信息。如果实在不行可以修改守护进程配置文件,将启动命令的配置删除。--config /etc/mongod.conf
MongoDB 常用操作
1. 连接 MongoDB
在终端输入:
mongosh
如果 MongoDB 运行在非默认端口,可以指定服务器与端口:
mongosh --host <hostname>:<port>
2. 查看环境信息
# 查看当前数据库
show dbs
# 切换到指定数据库
use <database_name>
# 查看当前集合
show collections
3. 数据操作
# 查询所有文档
db.<collection_name>.find()
# 插入文档
db.<collection_name>.insertOne({"name": "Alice", "age": 25})
# 更新文档
db.<collection_name>.updateOne({"name": "Alice"}, {"$set": {"age": 26}})
# 删除文档
db.<collection_name>.deleteOne({"name": "Alice"})
4. 退出 MongoDB 命令行
quit()
exit