MongoDB 增删改查完整语法
insert/find/update/delete 四类操作的完整语法、常用查询运算符与实战示例拆解。
0. 一句话理解
MongoDB 的增删改查就是四个动词:
insert加、find查、update改、delete删;查询和修改条件都写成 JSON 文档。
1. 插入:insertOne 与 insertMany
db.students.insertOne({
name: "小红",
age: 17,
scores: { math: 92, english: 88 }
})
db.students.insertMany([
{ name: "小刚", age: 18, scores: { math: 70, english: 75 } },
{ name: "小丽", age: 19, scores: { math: 85, english: 95 } }
])
讲解:
insertOne插入单条;insertMany接收数组批量插入,比循环单条插入快一个数量级。scores字段内嵌了数学和英语成绩,属于典型的”整份对象一起读写”设计。- 批量插入时若某条违反唯一索引约束,默认整批失败;传
{ ordered: false }可以让成功的继续、只报告失败的那条。
2. 查询:find 与查询运算符
2.1 基础查询
// 查所有
db.students.find({})
// 等值查询
db.students.find({ age: 18 })
// 投影:只要 name 和 age,_id 默认保留
db.students.find({ age: 18 }, { name: 1, age: 1 })
讲解:
find({})的空对象表示”无条件”,等价于 SQL 的SELECT *。- 第二个参数是投影:
1表示要的字段,0表示不要的字段(_id: 0可去掉主键)。
2.2 比较运算符
// age 大于 17:$gt 大于、$gte 大于等于、$lt 小于、$lte 小于等于
db.students.find({ age: { $gt: 17 } })
// age 在 17 到 19 之间(含边界)
db.students.find({ age: { $gte: 17, $lte: 19 } })
// name 在指定数组中
db.students.find({ name: { $in: ["小红", "小刚"] } })
// 逻辑组合:age > 18 且 math 成绩 >= 90
db.students.find({
age: { $gt: 18 },
"scores.math": { $gte: 90 }
})
讲解:
$gt/$gte/$lt/$lte对应>、>=、<、<=,是查询条件里最常见的四个运算符。$in相当于 SQL 的IN (...)。- 嵌套字段用点路径
"scores.math"访问,注意键名必须加引号,因为包含点号。 - 多个条件写在同一对象里表示”并且”(AND)。
2.3 数组与正则
// courses 数组包含 "数学"
db.students.find({ courses: "数学" })
// name 以 "小" 开头(正则查询)
db.students.find({ name: /^小/ })
讲解:
- 数组字段直接写值,表示”包含该元素”,这是文档模型非常实用的特性。
- 正则
/^小/匹配以”小”开头的字符串;正则查询无法利用普通索引前缀,数据量大时慎用。
3. 更新:updateOne / updateMany / replaceOne
// 修改第一条匹配的文档:把 age 加 1($inc 自增)
db.students.updateOne(
{ name: "小红" },
{ $inc: { age: 1 } }
)
// 批量修改:所有 18 岁及以上的学生,标记 adult: true
db.students.updateMany(
{ age: { $gte: 18 } },
{ $set: { adult: true } }
)
// 整个文档替换(保留 _id)
db.students.replaceOne(
{ name: "小刚" },
{ name: "小刚", age: 20, remark: "已毕业" }
)
讲解:
$set只新增/修改指定字段,$inc做原子自增,$unset删除字段。updateOne只更新第一条匹配;需要更新全部匹配时用updateMany,这两个名字最容易写混。replaceOne用新文档整体替换旧文档(_id不变),适合”整份重写”场景;忘记写上的字段会被丢掉。- 更新操作的第二个参数必须以
$运算符开头(如$set),直接写{ age: 19 }是语法错误。
4. 删除:deleteOne / deleteMany
// 删除第一条匹配
db.students.deleteOne({ name: "小丽" })
// 删除所有 age 小于 18 的学生
db.students.deleteMany({ age: { $lt: 18 } })
// 清空集合(保留集合本身)
db.students.deleteMany({})
讲解:
deleteOne({})会删掉”第一条”文档,而deleteMany({})会清空整个集合——企业环境里误执行后者是常见事故,操作前务必先用find确认条件。- 想连集合一起删掉,使用
db.students.drop()。
5. 排序、分页与计数
// 按 age 降序,再按 name 升序
db.students.find({}).sort({ age: -1, name: 1 })
// 跳过前 2 条,取 5 条(第 3 页,每页 5 条)
db.students.find({}).sort({ age: -1 }).skip(10).limit(5)
// 计数
db.students.countDocuments({ age: { $gte: 18 } })
讲解:
sort中1升序、-1降序,多字段按书写顺序依次比较。skip + limit是经典分页写法;数据量极大时深分页性能差,可改用”上一页最后一条的 _id”做游标分页。countDocuments是推荐计数方法,count()已废弃。
6. 动手试试
- 建一个
products集合,批量插入 5 个商品(字段:名称、分类、价格、库存)。 - 查询价格在 50-200 之间的商品,按价格降序排列,只显示名称和价格。
- 把所有库存为 0 的商品价格打 8 折(
$mul运算符)。 - 删除”分类为配件”的所有商品,删除前先数一数有多少条。
7. 一句话记住
条件一律写 JSON:
{ 字段: 值 }是等值,{ 字段: { $gt: 值 } }是比较;改数据记得先查一遍,updateOne/deleteOne只动第一条。