跳转至

MongoDB NoSQL 数据库

MongoDB 是最流行的 NoSQL 文档数据库,用类似 JSON 的格式存储数据(叫 BSON),不需要预定义表结构,特别适合快速开发和处理非结构化数据,是生信项目中存储样本元数据、分析结果的好选择。

核心知识点

知识点说明
数据库类型文档型 NoSQL 数据库
最新版本v8.2(性能大幅提升,支持向量搜索)
数据格式BSON(Binary JSON),类似 JSON 的二进制格式
核心优势灵活 schema、水平扩展、丰富查询、ACID 事务
适用场景Web 应用、物联网、日志存储、生信元数据管理
v8.0 亮点吞吐量提升 25%、批量插入快 54%、向量搜索
许可证SSPL(Server Side Public License)
云服务MongoDB Atlas(全托管云数据库)

安装配置

方法一:Docker 安装(推荐,最简单)

# 用 Docker 运行 MongoDB
docker run -d \
  --name mongodb \                   # 容器名
  -p 27017:27017 \                   # 端口映射
  -v mongodb_data:/data/db \         # 数据持久化
  -e MONGO_INITDB_ROOT_USERNAME=admin \   # 管理员用户名
  -e MONGO_INITDB_ROOT_PASSWORD=password \  # 管理员密码
  mongo:8                            # 使用 MongoDB 8 镜像

# 验证运行
docker exec -it mongodb mongosh      # 进入 MongoDB Shell

方法二:系统安装(Ubuntu/Debian)

# 导入 MongoDB GPG 密钥
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \
  sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor

# 添加仓库
echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] \
  https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/8.0 multiverse" | \
  sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list

# 安装
sudo apt update && sudo apt install -y mongodb-org  # 安装 MongoDB

# 启动服务
sudo systemctl start mongod          # 启动
sudo systemctl enable mongod         # 设置开机自启
mongosh                               # 连接 MongoDB Shell

方法三:Conda 安装(轻量级)

conda install -c conda-forge mongodb  # 安装 MongoDB
mongod --dbpath ./data/db            # 指定数据目录启动

基本使用

1. 数据库和集合操作

// 在 mongosh 中操作

// 查看所有数据库
show dbs                              // 列出所有数据库

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

// 创建集合(类似 SQL 的表)
db.createCollection("samples")        // 创建 samples 集合

// 查看当前数据库的集合
show collections                      // 列出所有集合

2. 插入文档

// 插入单个文档
db.samples.insertOne({
  sample_id: "T2D_001",              // 样本 ID
  patient_age: 55,                    // 患者年龄
  diagnosis: "T2D",                   // 诊断
  sequencing: {                       // 嵌套文档(测序信息)
    platform: "Illumina NovaSeq",
    read_length: 150,
    total_reads: 50000000
  },
  taxa: ["Bacteroides", "Firmicutes", "Proteobacteria"],  // 数组
  created_at: new Date()              // 时间戳
})

// 批量插入
db.samples.insertMany([
  { sample_id: "T2D_002", diagnosis: "T2D", bmi: 28.5 },
  { sample_id: "HC_001", diagnosis: "Healthy", bmi: 22.0 },
  { sample_id: "HC_002", diagnosis: "Healthy", bmi: 21.5 }
])

3. 查询文档

// 查询所有文档
db.samples.find()                     // 返回所有文档

// 条件查询
db.samples.find({ diagnosis: "T2D" })  // 查找所有 T2D 样本

// 比较查询
db.samples.find({ bmi: { $gt: 25 } })  // BMI > 25 的样本
db.samples.find({ bmi: { $gte: 20, $lte: 30 } })  // BMI 在 20-30 之间

// 数组查询
db.samples.find({ taxa: "Bacteroides" })  // 包含 Bacteroides 的样本

// 嵌套文档查询
db.samples.find({ "sequencing.platform": "Illumina NovaSeq" })

// 限制返回字段(投影)
db.samples.find(
  { diagnosis: "T2D" },              // 查询条件
  { sample_id: 1, bmi: 1, _id: 0 }  // 只返回 sample_id 和 bmi
)

// 排序和限制
db.samples.find().sort({ bmi: -1 }).limit(5)  // BMI 降序排列,取前 5

4. 更新文档

// 更新单个文档
db.samples.updateOne(
  { sample_id: "T2D_001" },          // 查询条件
  { $set: { bmi: 29.0 } }            // 设置新值
)

// 更新多个文档
db.samples.updateMany(
  { diagnosis: "T2D" },              // 匹配所有 T2D
  { $set: { group: "case" } }        // 添加 group 字段
)

// 数组操作
db.samples.updateOne(
  { sample_id: "T2D_001" },
  { $push: { taxa: "Lactobacillus" } }  // 向数组添加元素
)

5. 删除文档

// 删除单个文档
db.samples.deleteOne({ sample_id: "T2D_002" })

// 删除多个文档
db.samples.deleteMany({ diagnosis: "Healthy" })  // 删除所有健康样本

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

高级用法

1. 聚合管道(Aggregation Pipeline)

// 按诊断分组统计
db.samples.aggregate([
  { $group: {                          // 分组
    _id: "$diagnosis",                 // 按 diagnosis 分组
    count: { $sum: 1 },                // 计数
    avg_bmi: { $avg: "$bmi" },         // 平均 BMI
    max_bmi: { $max: "$bmi" }          // 最大 BMI
  }},
  { $sort: { count: -1 } }            // 按计数降序
])

// 多阶段聚合
db.samples.aggregate([
  { $match: { diagnosis: "T2D" } },    // 过滤 T2D 样本
  { $unwind: "$taxa" },                // 展开 taxa 数组
  { $group: {                          // 按物种分组计数
    _id: "$taxa",
    count: { $sum: 1 }
  }},
  { $sort: { count: -1 } },           // 降序排列
  { $limit: 10 }                       // 取前 10
])

2. 索引优化

// 创建索引(加速查询)
db.samples.createIndex({ sample_id: 1 })       // 单字段索引
db.samples.createIndex({ diagnosis: 1, bmi: -1 })  // 复合索引
db.samples.createIndex({ sample_id: 1 }, { unique: true })  // 唯一索引

// 查看索引
db.samples.getIndexes()                // 列出所有索引

// 查询性能分析
db.samples.find({ diagnosis: "T2D" }).explain("executionStats")

3. Python 操作(pymongo)

from pymongo import MongoClient  # 导入 MongoDB Python 驱动

# 连接 MongoDB
client = MongoClient("mongodb://admin:password@localhost:27017/")  # 连接

# 选择数据库和集合
db = client["bioinfo_db"]           # 选择数据库
samples = db["samples"]             # 选择集合

# 插入
result = samples.insert_one({       # 插入一个文档
    "sample_id": "T2D_003",
    "diagnosis": "T2D",
    "abundance": {"Bacteroides": 0.35, "Firmicutes": 0.40}
})
print(f"插入 ID: {result.inserted_id}")

# 查询
for doc in samples.find({"diagnosis": "T2D"}):  # 查询所有 T2D
    print(doc["sample_id"], doc.get("bmi"))

# 聚合
pipeline = [
    {"$group": {"_id": "$diagnosis", "count": {"$sum": 1}}}
]
for result in samples.aggregate(pipeline):  # 聚合查询
    print(result)

# 关闭连接
client.close()

常见报错与解决

报错信息原因解决方法
connection refusedMongoDB 服务未启动sudo systemctl start mongod
Authentication failed用户名或密码错误检查连接字符串中的用户名密码
E11000 duplicate key error插入了重复的唯一键检查唯一索引字段是否重复
ns not found集合不存在检查集合名拼写
磁盘空间不足数据文件太大清理数据或扩展磁盘,检查 journal 日志
BSON field too large单个文档超过 16MB 限制拆分大文档或使用 GridFS 存储大文件

速查表

// ===== MongoDB 速查表 =====

// === 数据库操作 ===
show dbs                              // 列出数据库
use mydb                              // 切换数据库
db.dropDatabase()                     // 删除当前数据库

// === 集合操作 ===
show collections                      // 列出集合
db.createCollection("name")           // 创建集合
db.name.drop()                        // 删除集合

// === CRUD 操作 ===
db.col.insertOne({...})               // 插入一条
db.col.insertMany([{...}, {...}])     // 插入多条
db.col.find({key: "value"})           // 查询
db.col.find().sort({key: 1})          // 排序(1升序 -1降序)
db.col.find().limit(10)               // 限制数量
db.col.updateOne({条件}, {$set: {更新}})  // 更新
db.col.deleteOne({条件})              // 删除

// === 查询操作符 ===
// $gt $gte $lt $lte $ne              比较
// $in $nin                           包含/不包含
// $and $or $not                      逻辑
// $exists                            字段存在
// $regex                             正则匹配

// === 聚合 ===
// $match   过滤
// $group   分组
// $sort    排序
// $limit   限制
// $project 投影
// $unwind  展开数组
// $lookup  关联查询(类似 JOIN)

// === 索引 ===
db.col.createIndex({key: 1})          // 创建索引
db.col.getIndexes()                   // 查看索引
db.col.dropIndex("index_name")       // 删除索引

// === Python (pymongo) ===
// pip install pymongo
// client = MongoClient("mongodb://localhost:27017/")
// db = client["mydb"]
// col = db["mycol"]
// col.insert_one({...})
// col.find({...})