跳到主要内容

MongoDB 基础

问题

MongoDB 的文档模型是什么?查询和聚合怎么用?

答案

核心概念对比

SQL 概念MongoDB 概念
DatabaseDatabase
TableCollection
RowDocument(JSON/BSON)
ColumnField
JOIN$lookup / 嵌套文档
PRIMARY KEY_id(自动生成)

CRUD 操作

mongodb-crud.ts
import { MongoClient, ObjectId } from 'mongodb';

const client = new MongoClient('mongodb://localhost:27017');
const db = client.db('myapp');
const users = db.collection('users');

// 插入
await users.insertOne({
name: 'Alice',
email: 'alice@example.com',
tags: ['developer', 'gamer'],
address: { city: '北京', district: '朝阳' },
});

// 查询
const user = await users.findOne({ email: 'alice@example.com' });
const devs = await users.find({ tags: 'developer' }).sort({ name: 1 }).limit(10).toArray();

// 更新
await users.updateOne(
{ _id: new ObjectId('...') },
{
$set: { name: 'Bob' },
$push: { tags: 'writer' },
$inc: { loginCount: 1 },
},
);

// 删除
await users.deleteOne({ _id: new ObjectId('...') });

聚合管道

aggregation.ts
// 统计每个城市的用户数和平均年龄
const result = await users.aggregate([
{ $match: { age: { $gte: 18 } } }, // 过滤
{ $group: { // 分组
_id: '$address.city',
count: { $sum: 1 },
avgAge: { $avg: '$age' },
}},
{ $sort: { count: -1 } }, // 排序
{ $limit: 10 }, // 限制
]).toArray();

// $lookup 实现 JOIN
const orders = await db.collection('orders').aggregate([
{
$lookup: {
from: 'users', // 关联的集合
localField: 'userId', // 本集合的字段
foreignField: '_id', // 关联集合的字段
as: 'user', // 结果字段名
},
},
{ $unwind: '$user' }, // 展开数组
]).toArray();

文档设计:嵌套 vs 引用

schema-design.ts
// 嵌套(一对少、读多写少)
interface BlogPost {
title: string;
content: string;
comments: Array<{ // 嵌套在文档内
author: string;
text: string;
createdAt: Date;
}>;
}

// 引用(一对多、独立更新频繁)
interface Order {
userId: ObjectId; // 引用 users 集合
items: Array<{
productId: ObjectId; // 引用 products 集合
quantity: number;
price: number;
}>;
}
嵌套 vs 引用选择
  • 嵌套:数据一起读取、子文档数量有限、子文档不需要独立查询
  • 引用:数据需要独立访问、子文档数量很大、需要跨文档查询

常见面试问题

Q1: MongoDB 的索引和 MySQL 有什么区别?

答案

MongoDB 也使用 B 树索引,支持:

  • 单字段索引、复合索引(同样遵循最左前缀)
  • 文本索引(全文搜索)
  • 地理空间索引(2dsphere)
  • TTL 索引(自动过期删除)

Q2: MongoDB 支持事务吗?

答案

MongoDB 4.0+ 支持多文档事务,4.2+ 支持分布式事务。但过度使用事务会降低性能,应优先通过文档设计减少事务需求。

Q3: Mongoose 和原生 MongoDB 驱动怎么选?

答案

  • Mongoose:提供 Schema 定义、校验、中间件、虚拟属性,适合需要严格 Schema 的项目
  • 原生驱动:更轻量、更灵活、性能更高

相关链接