MongoDB高级查询 #
一、复杂条件查询 #
1.1 嵌套条件 #
javascript
// 嵌套文档查询
db.users.find({
"address.city": "Beijing",
"address.zipCode": "100000"
})
// 嵌套数组查询
db.orders.find({
"items.productId": ObjectId("..."),
"items.quantity": { $gt: 1 }
})
1.2 多层嵌套 #
javascript
// 多层嵌套查询
db.companies.find({
"headquarters.address.city": "Shanghai",
"headquarters.address.country": "China"
})
// 嵌套数组中的对象
db.users.find({
"education.school": "MIT",
"education.degree": "Bachelor"
})
1.3 复杂逻辑组合 #
javascript
// 复杂逻辑组合
db.users.find({
$and: [
{
$or: [
{ status: "active" },
{ status: "pending" }
]
},
{
$or: [
{ age: { $lt: 18 } },
{ age: { $gt: 60 } }
]
}
]
})
// 使用$expr进行字段间比较
db.products.find({
$expr: { $gt: ["$price", "$cost"] }
})
// 使用$expr进行复杂计算
db.orders.find({
$expr: {
$gt: [
{ $multiply: ["$quantity", "$price"] },
1000
]
}
})
二、数组高级查询 #
2.1 数组元素匹配 #
javascript
// $elemMatch精确匹配数组元素
db.users.find({
scores: {
$elemMatch: {
subject: "math",
score: { $gte: 80, $lte: 100 }
}
}
})
// 多条件元素匹配
db.orders.find({
items: {
$elemMatch: {
productId: ObjectId("..."),
quantity: { $gt: 1 },
price: { $lt: 100 }
}
}
})
2.2 数组索引查询 #
javascript
// 按索引查询数组元素
db.users.find({ "hobbies.0": "reading" })
// 按索引查询嵌套对象
db.users.find({ "scores.0.subject": "math" })
2.3 数组长度查询 #
javascript
// 查询数组长度
db.users.find({ hobbies: { $size: 3 } })
// 查询数组长度范围(使用$expr)
db.users.find({
$expr: { $gt: [{ $size: "$hobbies" }, 2] }
})
2.4 数组包含查询 #
javascript
// 包含所有元素
db.users.find({
hobbies: { $all: ["reading", "swimming", "coding"] }
})
// 包含任意元素(使用$in)
db.users.find({
hobbies: { $in: ["reading", "swimming"] }
})
2.5 数组元素更新位置操作符 #
javascript
// 查询时使用$定位操作符
db.users.find(
{ "scores.subject": "math" },
{ "scores.$": 1 }
)
// 更新时使用$定位操作符
db.users.updateOne(
{ "scores.subject": "math" },
{ $set: { "scores.$.score": 95 } }
)
三、正则表达式查询 #
3.1 基本正则查询 #
javascript
// 正则表达式查询
db.users.find({ name: /^John/ })
// 不区分大小写
db.users.find({ name: /^john/i })
// 使用$regex操作符
db.users.find({
name: { $regex: /^john/, $options: "i" }
})
3.2 正则选项 #
javascript
// 正则选项
db.users.find({
name: {
$regex: "john",
$options: "imxs"
}
})
// 选项说明:
// i - 不区分大小写
// m - 多行匹配
// x - 忽略空白
// s - 点号匹配所有字符
3.3 复杂正则查询 #
javascript
// 邮箱格式验证
db.users.find({
email: {
$regex: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
}
})
// 手机号验证
db.users.find({
phone: {
$regex: /^1[3-9]\d{9}$/
}
})
// IP地址验证
db.logs.find({
ip: {
$regex: /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/
}
})
3.4 正则与索引 #
javascript
// 创建文本索引支持正则查询
db.users.createIndex({ name: "text" })
// 使用文本索引查询
db.users.find({ $text: { $search: "John" } })
// 前缀匹配可以使用索引
db.users.find({ name: /^John/ }) // 可以使用索引
// 非前缀匹配不能使用索引
db.users.find({ name: /John/ }) // 不能使用索引
四、文本搜索 #
4.1 创建文本索引 #
javascript
// 创建文本索引
db.articles.createIndex({ title: "text", content: "text" })
// 创建复合文本索引
db.articles.createIndex({
title: "text",
content: "text"
}, {
weights: {
title: 10,
content: 5
},
default_language: "none"
})
4.2 基本文本搜索 #
javascript
// 文本搜索
db.articles.find({ $text: { $search: "MongoDB" } })
// 多词搜索(OR)
db.articles.find({ $text: { $search: "MongoDB database" } })
// 短语搜索
db.articles.find({ $text: { $search: "\"MongoDB database\"" } })
// 排除词
db.articles.find({ $text: { $search: "MongoDB -MySQL" } })
4.3 文本搜索排序 #
javascript
// 按相关性排序
db.articles.find(
{ $text: { $search: "MongoDB" } },
{ score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })
4.4 文本搜索选项 #
javascript
// 文本搜索选项
db.articles.find(
{ $text: { $search: "MongoDB", $language: "en", $caseSensitive: false } },
{ score: { $meta: "textScore" } }
)
五、地理位置查询 #
5.1 地理索引 #
javascript
// 创建2dsphere索引
db.places.createIndex({ location: "2dsphere" })
// 创建2d索引
db.places.createIndex({ location: "2d" })
// 创建复合地理索引
db.places.createIndex({ location: "2dsphere", category: 1 })
5.2 地理位置数据格式 #
javascript
// GeoJSON格式
{
location: {
type: "Point",
coordinates: [116.4074, 39.9042] // [经度, 纬度]
}
}
// LineString
{
location: {
type: "LineString",
coordinates: [[116.4074, 39.9042], [121.4737, 31.2304]]
}
}
// Polygon
{
location: {
type: "Polygon",
coordinates: [[[116.4074, 39.9042], [121.4737, 31.2304], [113.2644, 23.1291], [116.4074, 39.9042]]]
}
}
5.3 附近查询 #
javascript
// 查找附近的点
db.places.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [116.4074, 39.9042]
},
$maxDistance: 1000, // 最大距离(米)
$minDistance: 10 // 最小距离(米)
}
}
})
// 使用$nearSphere(球面距离)
db.places.find({
location: {
$nearSphere: {
$geometry: {
type: "Point",
coordinates: [116.4074, 39.9042]
},
$maxDistance: 1000
}
}
})
5.4 范围查询 #
javascript
// 在多边形范围内查询
db.places.find({
location: {
$geoWithin: {
$geometry: {
type: "Polygon",
coordinates: [[[116.4074, 39.9042], [121.4737, 31.2304], [113.2644, 23.1291], [116.4074, 39.9042]]]
}
}
}
})
// 在圆形范围内查询
db.places.find({
location: {
$geoWithin: {
$center: [[116.4074, 39.9042], 10] // [中心点, 半径(弧度)]
}
}
})
// 在球面圆形范围内查询
db.places.find({
location: {
$geoWithin: {
$centerSphere: [[116.4074, 39.9042], 10 / 6378.1] // [中心点, 半径(弧度)]
}
}
})
5.5 相交查询 #
javascript
// 查找相交的几何图形
db.places.find({
location: {
$geoIntersects: {
$geometry: {
type: "Polygon",
coordinates: [[[116.4074, 39.9042], [121.4737, 31.2304], [113.2644, 23.1291], [116.4074, 39.9042]]]
}
}
}
})
5.6 地理聚合 #
javascript
// 计算距离
db.places.aggregate([
{
$geoNear: {
near: {
type: "Point",
coordinates: [116.4074, 39.9042]
},
distanceField: "distance",
maxDistance: 10000,
spherical: true
}
}
])
六、日期查询 #
6.1 日期范围查询 #
javascript
// 日期范围查询
db.events.find({
createdAt: {
$gte: ISODate("2024-01-01"),
$lt: ISODate("2025-01-01")
}
})
// 最近N天
db.events.find({
createdAt: {
$gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
}
})
6.2 日期聚合查询 #
javascript
// 按日期分组
db.events.aggregate([
{
$group: {
_id: {
year: { $year: "$createdAt" },
month: { $month: "$createdAt" },
day: { $dayOfMonth: "$createdAt" }
},
count: { $sum: 1 }
}
}
])
// 按小时分组
db.events.aggregate([
{
$group: {
_id: {
year: { $year: "$createdAt" },
month: { $month: "$createdAt" },
day: { $dayOfMonth: "$createdAt" },
hour: { $hour: "$createdAt" }
},
count: { $sum: 1 }
}
}
])
七、null和存在性查询 #
7.1 null值查询 #
javascript
// 查询null值
db.users.find({ middleName: null })
// 注意:这会匹配null值和不存在的字段
// 只匹配null值
db.users.find({ middleName: { $type: 10 } })
// 只匹配字段不存在
db.users.find({ middleName: { $exists: false } })
7.2 存在性查询 #
javascript
// 字段存在
db.users.find({ email: { $exists: true } })
// 字段不存在
db.users.find({ email: { $exists: false } })
// 字段存在且不为null
db.users.find({
email: {
$exists: true,
$ne: null
}
})
八、查询优化技巧 #
8.1 使用索引 #
javascript
// 创建合适的索引
db.users.createIndex({ email: 1 })
db.users.createIndex({ "address.city": 1, age: -1 })
// 使用hint强制索引
db.users.find({ email: "john@example.com" }).hint({ email: 1 })
8.2 限制结果 #
javascript
// 使用limit
db.users.find().limit(100)
// 使用投影
db.users.find({}, { name: 1, email: 1 })
8.3 避免全表扫描 #
javascript
// 不推荐:使用$where
db.users.find({ $where: "this.age > 20" })
// 推荐:使用操作符
db.users.find({ age: { $gt: 20 } })
// 不推荐:使用函数
db.users.find({ $expr: { $gt: [{ $function: { body: function(age) { return age * 2; }, args: ["$age"], lang: "js" }}, 40] } })
// 推荐:使用聚合表达式
db.users.find({ $expr: { $gt: [{ $multiply: ["$age", 2] }, 40] } })
8.4 查询分析 #
javascript
// 查看执行计划
db.users.find({ age: { $gt: 20 } }).explain("executionStats")
// 关注指标:
// - totalDocsExamined:扫描的文档数
// - totalKeysExamined:扫描的索引键数
// - executionTimeMillis:执行时间
// - indexUsed:使用的索引
九、总结 #
高级查询操作符:
| 操作符 | 说明 |
|---|---|
| $elemMatch | 数组元素匹配 |
| $all | 包含所有元素 |
| $size | 数组长度 |
| $regex | 正则表达式 |
| $text | 文本搜索 |
| $near | 附近查询 |
| $geoWithin | 范围查询 |
| $geoIntersects | 相交查询 |
| $expr | 表达式查询 |
下一步,让我们学习聚合管道!
最后更新:2026-03-27