1. MongoDB基础核心语法全解析
刚接触MongoDB时,我被它灵活的文档结构和直观的操作方式所吸引。与传统关系型数据库不同,MongoDB不需要预先定义表结构,每条记录都是一个完整的文档对象,这种设计特别适合处理现代应用中的半结构化数据。下面我将从实际使用角度,分享MongoDB最核心的语法要点和实战技巧。
2. MongoDB基础操作
2.1 数据库与集合操作
MongoDB的基本操作单元是数据库和集合。集合类似于关系型数据库中的表,但不需要预先定义字段结构。以下是最常用的管理命令:
// 查看所有数据库 show dbs // 切换/创建数据库(当第一次插入数据时才会真正创建) use my_database // 查看当前数据库中的集合 show collections // 显式创建集合(带选项) db.createCollection("users", { capped: true, // 固定大小集合 size: 100000, // 大小限制(字节) max: 1000 // 文档数量限制 }) // 删除集合 db.users.drop() // 删除当前数据库 db.dropDatabase()注意:MongoDB中的数据库和集合名称区分大小写,建议统一使用小写字母和下划线组合。
2.2 文档CRUD操作
文档是MongoDB的核心数据单元,采用BSON格式(Binary JSON)存储。以下是基本的增删改查操作:
插入文档:
// 插入单条文档 db.users.insertOne({ name: "张三", age: 28, skills: ["JavaScript", "MongoDB"], address: { city: "北京", district: "海淀区" }, created_at: new Date() }) // 插入多条文档 db.users.insertMany([ {name: "李四", age: 25}, {name: "王五", age: 30} ])查询文档:
// 查询所有文档 db.users.find() // 带条件查询 db.users.find({age: {$gt: 25}}) // 查询并格式化输出 db.users.find().pretty() // 查询单条文档 db.users.findOne({name: "张三"})更新文档:
// 更新单条文档 db.users.updateOne( {name: "张三"}, {$set: {age: 29}} ) // 更新多条文档 db.users.updateMany( {age: {$lt: 30}}, {$inc: {age: 1}} // 年龄加1 ) // 替换整个文档 db.users.replaceOne( {name: "李四"}, {name: "李四", age: 26, department: "研发部"} )删除文档:
// 删除单条文档 db.users.deleteOne({name: "王五"}) // 删除多条文档 db.users.deleteMany({age: {$gt: 40}})3. 高级查询技巧
3.1 查询操作符详解
MongoDB提供了丰富的查询操作符,用于构建复杂的查询条件:
// 比较操作符 db.users.find({age: {$gt: 25, $lte: 35}}) // 大于25且小于等于35 // 逻辑操作符 db.users.find({ $or: [ {age: {$lt: 25}}, {age: {$gt: 35}} ] }) // 元素操作符 db.users.find({skills: {$exists: true}}) // 存在skills字段的文档 // 数组操作符 db.users.find({skills: {$all: ["JavaScript", "MongoDB"]}}) // 同时包含两项技能 db.users.find({skills: {$size: 2}}) // 技能数量为23.2 投影与排序
控制返回字段和排序方式:
// 只返回name和age字段(_id默认返回) db.users.find({}, {name: 1, age: 1}) // 排除address字段 db.users.find({}, {address: 0}) // 结果排序(1升序,-1降序) db.users.find().sort({age: -1, name: 1}) // 分页查询 db.users.find() .skip(10) // 跳过前10条 .limit(5) // 返回5条3.3 聚合管道
聚合框架是MongoDB最强大的功能之一,可以实现复杂的数据处理:
// 按年龄段统计用户数量 db.users.aggregate([ { $group: { _id: { $switch: { branches: [ {case: {$lt: ["$age", 20]}, then: "20岁以下"}, {case: {$lt: ["$age", 30]}, then: "20-29岁"}, {case: {$lt: ["$age", 40]}, then: "30-39岁"}, {case: {$gte: ["$age", 40]}, then: "40岁及以上"} ], default: "未知" } }, count: {$sum: 1}, avgAge: {$avg: "$age"} } }, { $sort: {count: -1} } ])4. 索引与性能优化
4.1 索引创建与管理
合理的索引可以显著提高查询性能:
// 创建单字段索引 db.users.createIndex({name: 1}) // 创建复合索引 db.users.createIndex({age: 1, name: -1}) // 创建唯一索引 db.users.createIndex({email: 1}, {unique: true}) // 创建文本索引(支持全文搜索) db.users.createIndex({bio: "text"}) // 查看集合索引 db.users.getIndexes() // 删除索引 db.users.dropIndex("name_1")4.2 查询性能分析
使用explain()方法分析查询执行计划:
// 查看查询执行计划 db.users.find({age: {$gt: 25}}).explain("executionStats") // 强制使用特定索引 db.users.find({name: "张三"}).hint({name: 1})提示:关注executionStats中的"totalDocsExamined"和"executionTimeMillis"指标,前者表示扫描的文档数,后者是执行时间(毫秒)。
5. 事务与数据一致性
MongoDB从4.0版本开始支持多文档事务:
// 开启一个事务 session = db.getMongo().startSession() session.startTransaction() try { const users = session.getDatabase("my_database").users const orders = session.getDatabase("my_database").orders users.insertOne({name: "新用户", balance: 100}) orders.insertOne({user: "新用户", amount: 50}) session.commitTransaction() } catch (error) { session.abortTransaction() throw error } finally { session.endSession() }6. 实战经验与常见问题
6.1 设计模式最佳实践
嵌入式 vs 引用式设计:
- 一对一关系:通常嵌入文档
- 一对多关系:少量子文档可嵌入,大量则使用引用
- 多对多关系:通常使用引用数组
写优化技巧:
- 批量操作优先使用insertMany/bulkWrite
- 更新时使用$inc/$set等原子操作符
- 合理使用写关注级别(writeConcern)
6.2 常见错误排查
连接问题:
- 检查MongoDB服务是否运行
- 验证连接字符串格式:mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[database][?options]]
查询性能低下:
- 使用explain()分析慢查询
- 确保查询使用了适当的索引
- 避免全集合扫描(COLLSCAN)
内存问题:
- 监控工作集大小(working set)
- 确保有足够的内存容纳常用数据和索引
6.3 监控与维护
常用监控命令:
// 查看服务器状态 db.serverStatus() // 查看集合统计信息 db.users.stats() // 查看当前操作 db.currentOp()定期维护任务:
- 重建碎片化严重的索引
- 压缩集合(compact)
- 定期备份重要数据
MongoDB的灵活性和强大功能使其成为现代应用开发的理想选择。掌握这些核心语法后,你可以根据具体业务需求设计高效的数据模型和查询方案。在实际项目中,建议结合官方文档和性能分析工具不断优化你的MongoDB使用方式。