MongoDB 常用增删改查方法及示例
MongoDB 的增删改查(CRUD)操作是其核心功能,主要通过 mongo shell
或驱动(如 Node.js、Python 等)实现。以下是最常用操作的详细说明及示例(基于 mongo shell
语法)。
一、插入操作(Insert)
用于向集合中添加文档,支持插入单条或多条数据。
**1. 插入单条文档:insertOne()
**
向集合中插入一个文档,返回操作结果(包含是否成功、插入的 _id
等信息)。
语法:
db.collection.insertOne({<field1>: <value1>,<field2>: <value2>,...
})
示例:
向 users
集合插入一条用户记录:
// 若集合不存在,MongoDB 会自动创建
db.users.insertOne({name: "Alice",age: 25,email: "alice@example.com",hobbies: ["reading", "hiking"],isStudent: false
})
输出结果:
{"acknowledged": true, // 操作是否被服务端确认(默认开启写确认)"insertedId": ObjectId("650a8b9d0f7d0e1a2c3b4d5e") // 自动生成的唯一 _id
}
**2. 插入多条文档:insertMany()
**
向集合中批量插入多个文档,适合初始化数据或批量导入。
语法:
db.collection.insertMany([{ <doc1> },{ <doc2> },...
])
示例:
插入 3 条用户记录:
db.users.insertMany([{name: "Bob",age: 30,email: "bob@example.com",hobbies: ["gaming", "coding"]},{name: "Charlie",age: 22,email: "charlie@example.com",isStudent: true},{name: "Diana",age: 28,email: "diana@example.com",hobbies: ["painting"],isStudent: false}
])
输出结果:
{"acknowledged": true,"insertedIds": [ObjectId("650a8ba90f7d0e1a2c3b4d5f"),ObjectId("650a8ba90f7d0e1a2c3b4d60"),ObjectId("650a8ba90f7d0e1a2c3b4d61")]
}
二、查询操作(Query)
用于从集合中检索符合条件的文档,核心方法是 find()
和 findOne()
。
**1. 基础查询:find()
**
返回所有符合条件的文档(默认返回所有字段),支持条件过滤、投影(指定返回字段)、排序、分页等。
语法:
db.collection.find(<query>, <projection>)
<query>
:查询条件(类似 SQL 的WHERE
子句)。<projection>
:可选,指定返回的字段(1
表示包含,0
表示排除,不能混合使用_id
与其他字段外的1
和0
)。
示例:
(1) 无过滤查询(返回所有文档)
db.users.find() // 返回 users 集合的所有文档
(2) 条件查询(过滤文档)
使用 查询操作符(如 $eq
、$gt
、$lt
、$in
等)定义条件。
-
示例 1:精确匹配(
$eq
)
查询name
为 "Alice" 的文档:db.users.find({ name: { $eq: "Alice" } }) // 等价于简写:db.users.find({ name: "Alice" })
-
示例 2:范围查询(
$gt
大于,$lt
小于)
查询年龄大于 25 岁的用户:db.users.find({ age: { $gt: 25 } })
-
示例 3:包含查询(
$in
匹配数组中的任意值)
查询邮箱在["alice@example.com", "diana@example.com"]
中的用户:db.users.find({ email: { $in: ["alice@example.com", "diana@example.com"] } })
-
示例 4:嵌套字段查询(点符号
.
访问嵌套字段)
假设文档有嵌套结构(如address.city
):// 插入一条带嵌套字段的文档: db.users.insertOne({name: "Eve",address: { city: "Beijing", zip: "100000" } })// 查询城市为 Beijing 的用户: db.users.find({ "address.city": "Beijing" })
-
示例 5:正则表达式查询(
$regex
)
查询name
以 "A" 开头的用户:db.users.find({ name: { $regex: "^A" } }) // 输出 Alice(假设存在)
2. 投影(Projection)
控制返回的字段,减少网络传输量。
语法:
db.collection.find(<query>, { <field1>: 1, <field2>: 0 })
_id
字段默认返回,若需排除需显式设置"_id": 0
。
示例:
查询所有用户,但只返回 name
和 email
字段:
db.users.find({}, { name: 1, email: 1, _id: 0 })
输出结果:
{ "name" : "Alice", "email" : "alice@example.com" }
{ "name" : "Bob", "email" : "bob@example.com" }
...
3. 排序、分页与统计
-
排序:使用
sort()
方法(1
升序,-1
降序)。
示例:按年龄升序排序:db.users.find().sort({ age: 1 })
-
分页:使用
skip(n)
(跳过前 n 条)和limit(m)
(限制返回 m 条)。
示例:查询第 2 页(每页 2 条):db.users.find().skip(2).limit(2) // 跳过前 2 条,取 2 条
-
统计数量:使用
countDocuments()
(统计符合条件的文档数)。
示例:统计年龄大于 25 岁的用户数量:db.users.countDocuments({ age: { $gt: 25 } })
**4. 单条文档查询:findOne()
**
返回符合条件的第一条文档(适合快速获取单条数据)。
语法:
db.collection.findOne(<query>, <projection>)
示例:
查询 name
为 "Bob" 的第一条文档:
db.users.findOne({ name: "Bob" })
三、更新操作(Update)
用于修改集合中的文档,支持部分更新(仅修改指定字段)或全量替换。核心方法是 updateOne()
、updateMany()
和 replaceOne()
。
**1. 更新单条文档:updateOne()
**
更新第一条符合条件的文档,返回操作结果(包含是否成功、修改的文档数等)。
语法:
db.collection.updateOne(<query>, // 查询条件(匹配要更新的文档)<update>, // 更新操作(使用更新操作符)<options> // 可选参数(如 upsert: true 表示不存在则插入)
)
关键更新操作符(必须配合使用,否则会覆盖整个文档):
$set
:设置字段的值(若字段不存在则创建)。$inc
:对数值型字段递增/递减。$push
:向数组字段末尾添加元素。$pull
:从数组字段中移除指定元素。$unset
:删除指定字段。
示例:
(1) 使用 $set
修改字段
将 name
为 "Alice" 的用户的 email
修改为 "alice.new@example.com":
db.users.updateOne({ name: "Alice" },{ $set: { email: "alice.new@example.com" } }
)
输出结果:
{"acknowledged": true,"matchedCount": 1, // 匹配到的文档数"modifiedCount": 1 // 实际修改的文档数(若字段未变化则为 0)
}
(2) 使用 $inc
递增数值
将 name
为 "Bob" 的用户的 age
加 1:
db.users.updateOne({ name: "Bob" },{ $inc: { age: 1 } }
)
(3) 使用 $push
向数组添加元素
为 name
为 "Charlie" 的用户的 hobbies
数组添加 "swimming":
db.users.updateOne({ name: "Charlie" },{ $push: { hobbies: "swimming" } }
)
(4) 使用 $unset
删除字段
删除 name
为 "Diana" 的用户的 isStudent
字段:
db.users.updateOne({ name: "Diana" },{ $unset: { isStudent: "" } } // 值可以是任意(通常用空字符串)
)
**2. 更新多条文档:updateMany()
**
更新所有符合条件的文档(与 updateOne()
仅匹配数量不同)。
示例:
将所有年龄小于 28 岁的用户的 isStudent
字段设为 true
:
db.users.updateMany({ age: { $lt: 28 } },{ $set: { isStudent: true } }
)
**3. 全量替换文档:replaceOne()
**
用新文档完全替换匹配到的第一条文档(原字段会被覆盖,仅保留 _id
)。
语法:
db.collection.replaceOne(<query>, // 查询条件<replacementDoc> // 替换的新文档(不能包含操作符如 $set)
)
示例:
将 name
为 "Eve" 的用户替换为新文档(仅保留 _id
):
db.users.replaceOne({ name: "Eve" },{newName: "Eve Smith", // 原 name 字段被覆盖age: 30,email: "eve.smith@example.com"}
)
四、删除操作(Delete)
用于删除集合中的文档,核心方法是 deleteOne()
和 deleteMany()
。
**1. 删除单条文档:deleteOne()
**
删除第一条符合条件的文档。
语法:
db.collection.deleteOne(<query>)
示例:
删除 name
为 "Charlie" 的第一条文档:
db.users.deleteOne({ name: "Charlie" })
输出结果:
{"acknowledged": true,"deletedCount": 1 // 实际删除的文档数
}
**2. 删除多条文档:deleteMany()
**
删除所有符合条件的文档。
示例:
删除所有年龄大于 30 岁的用户:
db.users.deleteMany({ age: { $gt: 30 } })
注意:
- 删除操作不可逆,建议先使用
find()
确认匹配的文档,再执行删除。 - 若需清空集合,可使用
db.collection.deleteMany({})
(谨慎!)。
五、聚合查询(Aggregate)
用于复杂数据处理(如分组、统计、关联等),通过聚合管道(多个阶段依次处理)实现。
核心阶段(Stage)
$match
:过滤文档(类似find()
)。$group
:按指定字段分组,计算聚合值(如求和、计数)。$project
:投影(指定输出字段)。$sort
:排序。$limit
:限制输出数量。
示例:统计各城市的用户数量
需求:按 address.city
分组,统计每个城市的用户数。
聚合管道:
db.users.aggregate([{ $match: { "address.city": { $exists: true } } }, // 过滤有城市的文档{ $group: { // 分组统计_id: "$address.city", // 分组依据(城市名)count: { $sum: 1 } // 每组计数 +1}},{ $sort: { count: -1 } } // 按数量降序排序
])
输出结果(假设):
[{ "_id" : "Beijing", "count" : 2 },{ "_id" : "Shanghai", "count" : 1 }
]
总结
MongoDB 的 CRUD 操作围绕文档的增删改查展开,核心方法包括:
- 插入:
insertOne()
、insertMany()
- 查询:
find()
(含投影、排序、分页)、findOne()
- 更新:
updateOne()
(部分更新)、updateMany()
(批量更新)、replaceOne()
(全量替换) - 删除:
deleteOne()
、deleteMany()
- 高级查询:聚合管道(
aggregate()
)处理复杂统计。
实际使用中,需根据业务需求选择合适的操作方法,并注意索引优化(如为常用查询字段创建索引)以提升性能。