MongoDB基础查询 #
一、查询概述 #
1.1 查询方法 #
MongoDB提供多种查询方法:
| 方法 | 说明 |
|---|---|
| find | 查询多个文档 |
| findOne | 查询单个文档 |
| countDocuments | 统计文档数量 |
| distinct | 去重查询 |
1.2 查询结构 #
javascript
// 基本查询结构
db.collection.find(
{ query }, // 查询条件
{ projection } // 投影
).sort({ sort }).limit(limit).skip(skip)
二、find方法 #
2.1 基本查询 #
javascript
// 查询所有文档
db.users.find()
// 格式化输出
db.users.find().pretty()
// 查询单个文档
db.users.findOne()
2.2 条件查询 #
javascript
// 等值查询
db.users.find({ name: "John" })
// 多条件查询(AND)
db.users.find({ name: "John", age: 25 })
// 嵌套字段查询
db.users.find({ "address.city": "Beijing" })
// 数组元素查询
db.users.find({ hobbies: "reading" })
2.3 查询结果处理 #
javascript
// 限制结果数量
db.users.find().limit(10)
// 跳过结果
db.users.find().skip(10)
// 排序
db.users.find().sort({ age: -1 }) // 降序
db.users.find().sort({ age: 1 }) // 升序
// 组合使用
db.users.find()
.sort({ age: -1 })
.skip(10)
.limit(10)
三、查询操作符 #
3.1 比较操作符 #
$eq - 等于
javascript
// 等于
db.users.find({ age: { $eq: 25 } })
// 等同于
db.users.find({ age: 25 })
$ne - 不等于
javascript
// 不等于
db.users.find({ age: { $ne: 25 } })
$gt - 大于
javascript
// 大于
db.users.find({ age: { $gt: 20 } })
$gte - 大于等于
javascript
// 大于等于
db.users.find({ age: { $gte: 20 } })
$lt - 小于
javascript
// 小于
db.users.find({ age: { $lt: 30 } })
$lte - 小于等于
javascript
// 小于等于
db.users.find({ age: { $lte: 30 } })
$in - 在列表中
javascript
// 在列表中
db.users.find({ age: { $in: [20, 25, 30] } })
// 多个值
db.users.find({ city: { $in: ["Beijing", "Shanghai"] } })
$nin - 不在列表中
javascript
// 不在列表中
db.users.find({ age: { $nin: [20, 25, 30] } })
组合比较
javascript
// 范围查询
db.users.find({ age: { $gt: 20, $lt: 30 } })
// 多条件组合
db.users.find({
age: { $gte: 20, $lte: 30 },
city: { $in: ["Beijing", "Shanghai"] }
})
3.2 逻辑操作符 #
$and - 逻辑与
javascript
// 逻辑与
db.users.find({
$and: [
{ age: { $gt: 20 } },
{ city: "Beijing" }
]
})
// 简化写法
db.users.find({
age: { $gt: 20 },
city: "Beijing"
})
$or - 逻辑或
javascript
// 逻辑或
db.users.find({
$or: [
{ age: { $lt: 20 } },
{ age: { $gt: 60 } }
]
})
// 多条件或
db.users.find({
$or: [
{ city: "Beijing" },
{ city: "Shanghai" }
]
})
$not - 逻辑非
javascript
// 逻辑非
db.users.find({
age: { $not: { $gt: 30 } }
})
// 等同于 age <= 30
$nor - 逻辑或非
javascript
// 逻辑或非
db.users.find({
$nor: [
{ age: { $lt: 20 } },
{ city: "Beijing" }
]
})
// 既不满足age < 20,也不满足city = Beijing
组合逻辑
javascript
// 复杂逻辑组合
db.users.find({
$and: [
{
$or: [
{ status: "active" },
{ status: "pending" }
]
},
{ age: { $gte: 18 } }
]
})
3.3 元素操作符 #
$exists - 字段存在
javascript
// 字段存在
db.users.find({ email: { $exists: true } })
// 字段不存在
db.users.find({ email: { $exists: false } })
$type - 类型检查
javascript
// 类型检查
db.users.find({ age: { $type: "number" } })
// 多种类型
db.users.find({ age: { $type: ["number", "string"] } })
// 使用类型编号
db.users.find({ age: { $type: 16 } }) // 32位整数
3.4 数组操作符 #
$all - 包含所有元素
javascript
// 包含所有元素
db.users.find({ hobbies: { $all: ["reading", "swimming"] } })
$size - 数组长度
javascript
// 数组长度
db.users.find({ hobbies: { $size: 3 } })
$elemMatch - 元素匹配
javascript
// 元素匹配
db.users.find({
scores: {
$elemMatch: {
subject: "math",
score: { $gt: 80 }
}
}
})
// 数组嵌套对象查询
db.orders.find({
items: {
$elemMatch: {
productId: ObjectId("..."),
quantity: { $gt: 1 }
}
}
})
3.5 正则表达式 #
javascript
// 正则表达式查询
db.users.find({ name: /^John/ })
// $regex操作符
db.users.find({
name: { $regex: /^john/i }
})
// 复杂正则
db.users.find({
email: {
$regex: /^[a-zA-Z0-9._%+-]+@example\.com$/,
$options: "i"
}
})
四、投影 #
4.1 基本投影 #
javascript
// 包含字段
db.users.find({}, { name: 1, email: 1 })
// 排除字段
db.users.find({}, { password: 0, _id: 0 })
// 混合使用(不能同时使用包含和排除)
db.users.find({}, { name: 1, email: 1, _id: 0 })
4.2 嵌套字段投影 #
javascript
// 嵌套字段投影
db.users.find({}, { "address.city": 1, "address.street": 1 })
// 数组元素投影
db.users.find({}, { "hobbies.$": 1 })
// 数组元素过滤
db.users.find(
{ hobbies: "reading" },
{ "hobbies.$": 1 }
)
4.3 数组投影 #
javascript
// 数组切片
db.users.find({}, { hobbies: { $slice: 3 } })
db.users.find({}, { hobbies: { $slice: -3 } })
db.users.find({}, { hobbies: { $slice: [2, 3] } })
// 数组元素匹配
db.users.find(
{},
{ scores: { $elemMatch: { score: { $gt: 80 } } } }
)
4.4 聚合投影 #
javascript
// 使用聚合表达式
db.users.find({}, {
name: 1,
email: 1,
age: { $add: ["$age", 1] },
fullName: { $concat: ["$firstName", " ", "$lastName"] }
})
五、排序 #
5.1 基本排序 #
javascript
// 升序
db.users.find().sort({ age: 1 })
// 降序
db.users.find().sort({ age: -1 })
// 多字段排序
db.users.find().sort({ city: 1, age: -1 })
5.2 嵌套字段排序 #
javascript
// 嵌套字段排序
db.users.find().sort({ "address.city": 1 })
5.3 排序规则 #
javascript
// 排序规则
db.users.find().sort({ name: 1 }).collation({
locale: "zh",
strength: 2
})
六、分页 #
6.1 skip/limit分页 #
javascript
// 基本分页
const page = 1
const pageSize = 10
db.users.find()
.skip((page - 1) * pageSize)
.limit(pageSize)
// 排序分页
db.users.find()
.sort({ createdAt: -1 })
.skip((page - 1) * pageSize)
.limit(pageSize)
6.2 游标分页 #
javascript
// 游标分页(更高效)
const lastId = ObjectId("...")
db.users.find({ _id: { $gt: lastId } })
.sort({ _id: 1 })
.limit(10)
// 复合游标分页
const lastCreatedAt = ISODate("...")
const lastId = ObjectId("...")
db.users.find({
$or: [
{ createdAt: { $lt: lastCreatedAt } },
{ createdAt: lastCreatedAt, _id: { $gt: lastId } }
]
})
.sort({ createdAt: -1, _id: 1 })
.limit(10)
七、统计 #
7.1 countDocuments #
javascript
// 统计文档数量
db.users.countDocuments({})
// 条件统计
db.users.countDocuments({ age: { $gt: 20 } })
// 复杂条件统计
db.users.countDocuments({
city: "Beijing",
age: { $gte: 18, $lte: 60 }
})
7.2 estimatedDocumentCount #
javascript
// 估算文档数量(更快)
db.users.estimatedDocumentCount()
7.3 distinct #
javascript
// 去重查询
db.users.distinct("city")
// 条件去重
db.users.distinct("city", { age: { $gt: 20 } })
// 嵌套字段去重
db.users.distinct("address.city")
八、查询优化 #
8.1 使用索引 #
javascript
// 创建索引
db.users.createIndex({ name: 1 })
// 使用索引查询
db.users.find({ name: "John" })
// 强制使用索引
db.users.find({ name: "John" }).hint({ name: 1 })
// 查看执行计划
db.users.find({ name: "John" }).explain("executionStats")
8.2 查询分析 #
javascript
// 查看执行计划
db.users.find({ age: { $gt: 20 } }).explain()
// 详细执行计划
db.users.find({ age: { $gt: 20 } }).explain("executionStats")
// 所有执行计划
db.users.find({ age: { $gt: 20 } }).explain("allPlansExecution")
8.3 查询优化建议 #
javascript
// 1. 使用投影减少返回字段
db.users.find({}, { name: 1, email: 1 })
// 2. 使用limit限制结果
db.users.find().limit(100)
// 3. 避免使用$where
// 不推荐
db.users.find({ $where: "this.age > 20" })
// 推荐
db.users.find({ age: { $gt: 20 } })
// 4. 使用索引
db.users.createIndex({ age: 1 })
db.users.find({ age: { $gt: 20 } })
九、查询游标 #
9.1 游标方法 #
javascript
// 遍历游标
const cursor = db.users.find()
while (cursor.hasNext()) {
printjson(cursor.next())
}
// 使用forEach
db.users.find().forEach(user => {
print(user.name)
})
// 转换为数组
const users = db.users.find().toArray()
// 获取单个文档
const user = db.users.find().next()
9.2 游标选项 #
javascript
// 设置批量大小
db.users.find().batchSize(100)
// 设置超时
db.users.find().maxTimeMS(5000)
// 不超时
db.users.find().noCursorTimeout()
十、最佳实践 #
10.1 查询设计 #
javascript
// 推荐:使用索引
db.users.createIndex({ email: 1 })
db.users.find({ email: "john@example.com" })
// 不推荐:全表扫描
db.users.find({ email: { $regex: /example\.com$/ } })
10.2 投影使用 #
javascript
// 推荐:只返回需要的字段
db.users.find({}, { name: 1, email: 1, _id: 0 })
// 不推荐:返回所有字段
db.users.find({})
10.3 分页优化 #
javascript
// 推荐:游标分页
db.users.find({ _id: { $gt: lastId } }).limit(10)
// 不推荐:skip分页(大量数据时性能差)
db.users.find().skip(10000).limit(10)
十一、总结 #
查询操作速查表:
| 方法 | 说明 | 示例 |
|---|---|---|
| find | 查询多个文档 | db.coll.find({…}) |
| findOne | 查询单个文档 | db.coll.findOne({…}) |
| countDocuments | 统计文档数 | db.coll.countDocuments({…}) |
| distinct | 去重查询 | db.coll.distinct(“field”) |
常用操作符:
| 操作符 | 说明 |
|---|---|
| $eq, $ne | 等于、不等于 |
| $gt, $gte, $lt, $lte | 比较操作 |
| $in, $nin | 在列表中、不在列表中 |
| $and, $or, $not | 逻辑操作 |
| $exists, $type | 元素操作 |
| $all, $size, $elemMatch | 数组操作 |
| $regex | 正则表达式 |
下一步,让我们学习高级查询!
最后更新:2026-03-27