一份面向开发者的 MongoDB 6.0 实战指南,涵盖核心概念、安装部署、CRUD 操作、数据类型详解及 Spring Boot 整合实践。
一、MongoDB 是什么?
MongoDB 是一款文档型数据库 ,使用 JSON/BSON 作为数据模型,由 C++ 编写,专为 Web 应用提供可扩展、高性能的数据存储方案。
它介于关系型数据库与非关系型数据库之间,是 NoSQL 阵营中功能最丰富、最像 RDBMS 的产品。其核心特点:
-
半结构化:同一集合中的文档可以拥有不同字段,无需预先定义 Schema。
-
弱关系 :没有外键约束,通过聚合管道(
$lookup)实现类似表连接的功能。 -
强大的查询语言:支持索引、聚合、地理空间查询等,能完成大多数单表查询操作。
-
原生高可用与水平扩展:通过复制集提供 99.999% 高可用,通过分片实现海量数据无缝扩容。
截至 2021 年底,MongoDB 在数据库总排名第 5,NoSQL 中排名第 1,社区活跃度和应用广度持续攀升。
二、MongoDB vs 关系型数据库(概念对照)
| MongoDB 概念 | 关系型数据库概念 |
|---|---|
| 数据库(Database) | 数据库 |
| 集合(Collection) | 表(Table) |
| 文档(Document) | 行(Row) |
| 字段(Field) | 列(Column) |
| 索引(Index) | 索引 |
_id |
主键(Primary Key) |
| 视图(View) | 视图 |
$lookup |
表连接(Join) |
注意:MongoDB 的文档支持嵌套 和数组,更贴合面向对象的编程模型,开发效率更高。
三、适用场景
只要满足以下任意一项,就可以考虑使用 MongoDB:
-
游戏:用户信息、装备、积分以内嵌文档存储,方便查询更新。
-
物流:订单状态变更以数组存储,一次查询获取完整轨迹。
-
社交:用户信息、朋友圈,配合地理位置索引实现"附近的人"。
-
物联网:设备信息、日志存储,并进行多维分析。
-
视频直播:用户、礼物等实时数据。
-
大数据:作为云存储系统,方便数据提取分析。
国内外众多互联网公司(如阿里、腾讯、Google、Facebook 等)都在生产环境中广泛使用 MongoDB。
四、Linux 环境搭建(CentOS 7)
1. 下载并解压 MongoDB Community Server
bash
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-6.0.5.tgz
tar -zxvf mongodb-linux-x86_64-rhel70-6.0.5.tgz
2. 创建数据目录和日志文件
bash
mkdir -p /mongodb/data /mongodb/log
touch /mongodb/log/mongodb.log
3. 启动 MongoDB(命令行方式)
bash
bin/mongod --port=27017 --dbpath=/mongodb/data --logpath=/mongodb/log/mongodb.log --bind_ip=0.0.0.0 --fork
4. 使用配置文件启动(推荐)
创建 /mongodb/conf/mongo.conf:
yaml
systemLog:
destination: file
path: /mongodb/log/mongod.log
logAppend: true
storage:
dbPath: /mongodb/data
engine: wiredTiger
journal:
enabled: true
net:
bindIp: 0.0.0.0
port: 27017
processManagement:
fork: true
启动:
bash
mongod -f /mongodb/conf/mongo.conf
5. 关闭 MongoDB
bash
# 方式一
mongod --port=27017 --dbpath=/mongodb/data --shutdown
# 方式二(进入 mongosh)
use admin
db.shutdownServer()
6. 安装 mongosh(MongoDB 6.0 已移除旧的 mongo 客户端)
bash
wget https://downloads.mongodb.com/compass/mongodb-mongosh-1.8.0.x86_64.rpm
yum install -y mongodb-mongosh-1.8.0.x86_64.rpm
连接:
bash
mongosh --host=192.168.65.206 --port=27017
五、安全认证(用户管理)
1. 创建管理员用户(在 admin 库中)
javascript
use admin
db.createUser({user: "fox", pwd: "fox", roles: ["root"]})
2. 创建应用数据库用户
javascript
use appdb
db.createUser({user: "appdb", pwd: "fox", roles: ["dbOwner"]})
3. 启用认证启动
bash
mongod -f /mongodb/conf/mongo.conf --auth
4. 连接时认证
bash
mongosh 192.168.65.206:27017 -u fox -p fox --authenticationDatabase=admin
六、Docker 安装(快速体验)
bash
docker pull mongo:6.0.5
docker run --name mongo-server -p 29017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=fox \
-e MONGO_INITDB_ROOT_PASSWORD=fox \
-d mongo:6.0.5 --wiredTigerCacheSizeGB 1
连接:
bash
mongosh ip:29017 -u fox -p fox
七、核心文档操作(CRUD)
1. 插入文档
javascript
// 插入单个
db.books.insertOne({ title: "MongoDB实战", type: "technology", favCount: 30 })
// 批量插入(可用 load("books.js") 执行脚本)
db.books.insertMany([...])
2. 查询文档
javascript
// 查询所有
db.books.find()
// 条件查询(收藏数 > 60)
db.books.find({ type: "travel", favCount: { $gt: 60 } })
// 正则匹配
db.books.find({ type: { $regex: "so" } })
// 排序 + 分页
db.books.find().sort({ favCount: -1 }).skip(16).limit(8)
// 巧分页(避免 skip 大数据量)
db.books.find({ _id: { $gt: lastId } }).sort({ _id: 1 }).limit(10)
3. 更新文档
javascript
// 更新单个(自增收藏数)
db.books.updateOne({ _id: ObjectId("...") }, { $inc: { favCount: 1 } })
// 更新多个(添加发布时间)
db.books.updateMany({ type: "novel" }, { $set: { publishedDate: new Date() } })
// upsert(不存在则插入)
db.books.updateOne(
{ title: "my book" },
{ $set: { tags: ["nosql"], type: "none" } },
{ upsert: true }
)
4. 删除文档
javascript
db.books.deleteOne({ type: "novel" })
db.books.deleteMany({ type: "novel" })
db.books.findOneAndDelete({ type: "novel" }) // 返回被删文档
5. 批量操作(bulkWrite)
javascript
db.pizzas.bulkWrite([
{ insertOne: { document: { _id: 3, type: "beef", price: 6 } } },
{ updateOne: { filter: { type: "cheese" }, update: { $set: { price: 8 } } } },
{ deleteOne: { filter: { type: "pepperoni" } } }
])
八、BSON 数据类型与 ObjectId
为什么使用 BSON?
-
二进制编码,遍历更快(记录每个元素长度,支持 seek 直接读取)。
-
支持更丰富的类型:日期、二进制、ObjectId、Decimal128 等。
-
文档最大 16MB,嵌套级别不超过 100。
ObjectId 结构(12 字节)
-
4 字节:Unix 时间戳(秒)
-
5 字节:随机数(机器号 + 进程号)
-
3 字节:计数器(初始随机)
自动生成,保证唯一性,减轻服务器压力。
日期类型
MongoDB 使用 UTC 时间存储,new Date() 和 ISODate() 均生成 ISODate 类型。
九、内嵌文档与数组(灵活建模)
内嵌文档示例
javascript
db.books.insert({
title: "撒哈拉的故事",
author: { name: "三毛", gender: "女", hometown: "重庆" }
})
// 查询
db.books.find({ "author.name": "三毛" })
// 更新内嵌字段
db.books.updateOne({ "author.name": "三毛" }, { $set: { "author.hometown": "重庆/台湾" } })
数组操作
javascript
// 添加标签
db.books.updateOne({ "author.name": "三毛" }, { $push: { tags: "猎奇" } })
// 批量添加并保留最后 3 个
db.books.updateOne(
{ "author.name": "三毛" },
{ $push: { tags: { $each: ["伤感", "想象力"], $slice: -3 } } }
)
// 根据数组元素查询
db.books.find({ tags: "伤感" })
db.books.find({ tags: { $all: ["伤感", "想象力"] } })
多属性商品(数组内嵌文档)
javascript
db.goods.insertMany([{
name: "羽绒服",
tags: [
{ tagKey: "size", tagValue: ["M","L","XL"] },
{ tagKey: "color", tagValue: ["黑色","宝蓝"] }
]
}])
// 查询 color=黑色 且 size=XL
db.goods.find({
tags: {
$all: [
{ $elemMatch: { tagKey: "color", tagValue: "黑色" } },
{ $elemMatch: { tagKey: "size", tagValue: "XL" } }
]
}
})
十、固定集合(Capped Collection)
固定集合是限定大小的集合,采用 FIFO(先进先出)策略,适用于日志 、消息队列 、最新 TopN 等场景。
javascript
// 创建(size=4096字节,max=10条)
db.createCollection("logs", { capped: true, size: 4096, max: 10 })
// 普通集合转固定集合
db.runCommand({ convertToCapped: "mycoll", size: 100000 })
实战:股票消息队列
生产者每秒插入一条股价变动:
javascript
function pushEvent() {
while (true) {
db.stock_queue.insert({
timestamped: new Date(),
stock: "MongoDB Inc",
price: 100 * Math.random()
});
sleep(1000);
}
}
消费者持续监听(类似 tail -f):
javascript
function listen() {
var cursor = db.stock_queue.find({ timestamped: { $gte: new Date() } }).tailable();
while (true) {
if (cursor.hasNext()) {
print(JSON.stringify(cursor.next(), null, 2));
}
sleep(1000);
}
}
十一、Spring Boot 整合 MongoDB
1. 引入依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
2. 配置 yml
yaml
spring:
data:
mongodb:
uri: mongodb://fox:fox@192.168.65.174:27017/test?authSource=admin
3. 实体类(使用注解)
java
@Document("emp")
@Data
public class Employee {
@Id
private Integer id;
@Field("username")
private String name;
@Field
private int age;
@Field
private Double salary;
@Field
private Date entryDay;
}
4. 常用操作示例
插入:
java
mongoTemplate.insert(employee);
mongoTemplate.insert(list, Employee.class);
查询:
java
// 条件 + 排序 + 分页
Query query = new Query(Criteria.where("salary").gt(4000).lt(10000))
.with(Sort.by(Sort.Order.desc("salary")))
.skip(0).limit(4);
List<Employee> list = mongoTemplate.find(query, Employee.class);
更新:
java
Query query = new Query(Criteria.where("salary").is(15000));
Update update = new Update().set("salary", 13000);
UpdateResult result = mongoTemplate.updateMulti(query, update, Employee.class);
删除:
java
Query query = new Query(Criteria.where("salary").is(10000));
mongoTemplate.remove(query, Employee.class);
5. 去掉自动添加的 _class 字段(可选)
java
@Configuration
public class MongoConfig {
@Bean
public MappingMongoConverter mappingMongoConverter(
MongoDatabaseFactory factory, MongoMappingContext context, MongoCustomConversions conversions) {
DbRefResolver resolver = new DefaultDbRefResolver(factory);
MappingMongoConverter converter = new MappingMongoConverter(resolver, context);
converter.setCustomConversions(conversions);
converter.setTypeMapper(new DefaultMongoTypeMapper(null)); // 关键
return converter;
}
}
十二、小结
MongoDB 以其灵活的文档模型 、强大的查询能力 、原生高可用与扩展性,成为 NoSQL 领域的领军者。无论是快速迭代的互联网产品,还是海量数据的物联网、大数据场景,MongoDB 都能显著降低开发成本,提升系统弹性。
本文从概念到实战,从 Linux 安装到 Spring Boot 整合,覆盖了日常开发所需的全部基础知识。希望你能以此为起点,在项目中充分发挥 MongoDB 的优势。