Appearance
MongoDB 查询语言
MongoDB查询语言是用于从MongoDB数据库中检索数据的强大工具。本章详细介绍MongoDB的查询语法、操作符和高级查询技术。
查询基础
MongoDB查询使用文档形式来指定条件,这些条件定义了要匹配的文档。
基本查询语法
javascript
// 基本查询语法
db.collection.find(query, projection)
// 示例:查找所有年龄为25的用户
db.users.find({ age: 25 })
// 示例:查找特定字段匹配的文档
db.users.find({
name: "张三",
age: { $gte: 18 }
})
等值匹配
javascript
// 精确匹配
db.users.find({ status: "active" })
// 匹配多个字段
db.users.find({
status: "active",
age: 25
})
// 匹配嵌套字段
db.users.find({
"address.city": "北京"
})
查询操作符
比较操作符
javascript
// $eq (等于)
db.users.find({ age: { $eq: 25 } })
// $gt (大于)
db.users.find({ age: { $gt: 25 } })
// $gte (大于等于)
db.users.find({ age: { $gte: 25 } })
// $lt (小于)
db.users.find({ age: { $lt: 30 } })
// $lte (小于等于)
db.users.find({ age: { $lte: 30 } })
// $ne (不等于)
db.users.find({ age: { $ne: 25 } })
// $in (在数组中)
db.users.find({ age: { $in: [20, 25, 30] } })
// $nin (不在数组中)
db.users.find({ age: { $nin: [20, 25, 30] } })
逻辑操作符
javascript
// $and (与操作)
db.users.find({
$and: [
{ age: { $gte: 18 } },
{ age: { $lte: 65 } }
]
})
// $or (或操作)
db.users.find({
$or: [
{ status: "active" },
{ role: "admin" }
]
})
// $not (非操作)
db.users.find({
age: { $not: { $lt: 18 } }
})
// $nor (都不)
db.users.find({
$nor: [
{ status: "inactive" },
{ role: "banned" }
]
})
元素操作符
javascript
// $exists (字段存在)
db.users.find({ email: { $exists: true } })
// $type (字段类型)
db.users.find({ age: { $type: "number" } })
db.users.find({ name: { $type: "string" } })
// 检查字段不存在
db.users.find({ email: { $exists: false } })
评估操作符
javascript
// $regex (正则表达式)
db.users.find({ name: { $regex: /^张/ } })
db.users.find({ email: { $regex: /@gmail\.com$/i } })
// $text (文本搜索)
db.articles.createIndex({ content: "text", title: "text" })
db.articles.find({ $text: { $search: "mongodb" } })
// $where (JavaScript表达式)
db.users.find({
$where: function() {
return this.age > this.name.length;
}
})
// $expr (聚合表达式)
db.sales.find({
$expr: { $gt: ["$price", "$cost"] }
})
数组查询
数组操作符
javascript
// $all (包含所有元素)
db.users.find({
hobbies: { $all: ["读书", "游泳"] }
})
// $elemMatch (数组元素匹配)
db.students.find({
scores: {
$elemMatch: {
subject: "数学",
score: { $gte: 90 }
}
}
})
// $size (数组大小)
db.users.find({
hobbies: { $size: 3 }
})
// 查询数组特定位置
db.students.find({
"grades.0": { $gte: 80 }
})
// 查询数组中包含特定值
db.users.find({
hobbies: "游泳"
})
查询投影
基本投影
javascript
// 只返回指定字段
db.users.find({}, { name: 1, email: 1 })
// 排除指定字段
db.users.find({}, { password: 0, internalId: 0 })
// 混合投影
db.users.find({}, {
name: 1,
email: 1,
password: 0
})
// 投影嵌套字段
db.users.find({}, {
"address.city": 1,
"address.street": 1
})
高级投影
javascript
// $elemMatch投影
db.students.find(
{ scores: { $elemMatch: { subject: "数学", score: { $gte: 90 } } } },
{
name: 1,
scores: { $elemMatch: { subject: "数学", score: { $gte: 90 } } }
}
)
// $slice投影数组元素
db.posts.find(
{ author: "张三" },
{ comments: { $slice: 5 } } // 只返回前5个评论
)
// $meta投影元数据
db.articles.find(
{ $text: { $search: "mongodb" } },
{ score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })
聚合查询
使用聚合管道进行复杂查询
javascript
// 基本聚合查询
db.orders.aggregate([
{
$match: { status: "completed" }
},
{
$group: {
_id: "$customerId",
totalSpent: { $sum: "$amount" },
orderCount: { $sum: 1 }
}
},
{
$match: { totalSpent: { $gte: 1000 } }
}
])
// 条件聚合
db.products.aggregate([
{
$project: {
name: 1,
category: 1,
price: 1,
priceCategory: {
$switch: {
branches: [
{ case: { $lt: ["$price", 100] }, then: "cheap" },
{ case: { $lt: ["$price", 500] }, then: "medium" }
],
default: "expensive"
}
}
}
}
])
正则表达式查询
javascript
// 基本正则表达式
db.users.find({ name: /张/i }) // 不区分大小写
db.users.find({ name: { $regex: "^张" } }) // 以"张"开头
// 使用选项
db.users.find({
email: {
$regex: "@gmail.com$",
$options: "i"
}
})
// 复杂正则表达式
db.products.find({
name: {
$regex: "^(?=.*手机)(?=.*华为).+$",
$options: "i"
}
})
地理空间查询
javascript
// 创建2dsphere索引
db.places.createIndex({ location: "2dsphere" })
// 查找附近的地点
db.places.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [116.397428, 39.90923] // 经纬度
},
$maxDistance: 1000 // 1000米内
}
}
})
// 在多边形内查找
db.places.find({
location: {
$geoWithin: {
$geometry: {
type: "Polygon",
coordinates: [[
[116.0, 39.0],
[117.0, 39.0],
[117.0, 40.0],
[116.0, 40.0],
[116.0, 39.0]
]]
}
}
}
})
查询优化
使用索引
javascript
// 创建索引
db.users.createIndex({ email: 1 })
db.users.createIndex({ age: 1, status: 1 }) // 复合索引
// 查看查询执行计划
db.users.find({ email: "user@example.com" }).explain("executionStats")
// 使用hint强制使用特定索引
db.users.find({ age: 25, status: "active" }).hint({ age: 1, status: 1 })
查询性能分析
javascript
// 使用$comment添加查询注释
db.users.find({
status: "active"
}).comment("get_active_users")
// 分析查询性能
db.setProfilingLevel(2, { slowms: 100 }) // 记录超过100ms的查询
高级查询技术
游标操作
javascript
// 基本游标操作
const cursor = db.users.find({ status: "active" })
.limit(10)
.skip(20)
.sort({ createdAt: -1 })
// 批量处理结果
cursor.forEach(function(doc) {
printjson(doc)
})
// 获取查询结果数组
const results = db.users.find({ age: { $gte: 18 } }).toArray()
条件查询
javascript
// 使用$cond进行条件查询
db.sales.aggregate([
{
$project: {
item: 1,
discount: {
$cond: {
if: { $gte: ["$quantity", 100] },
then: 0.1,
else: 0.05
}
}
}
}
])
最佳实践
查询优化建议
- 使用适当的索引:为经常查询的字段创建索引
- 避免全表扫描:确保查询能够使用索引
- 使用投影:只返回需要的字段
- 限制结果数量:使用limit()限制返回结果
- 避免大偏移量:使用范围查询代替大skip值
安全查询
javascript
// 防止查询注入
function findUserByName(name) {
// 不安全的做法
// return db.users.find({ name: name })
// 安全的做法 - 验证输入
if (typeof name !== 'string' || name.length > 50) {
throw new Error('Invalid name parameter')
}
return db.users.find({ name: name })
}
总结
MongoDB查询语言提供了强大而灵活的数据检索能力。通过合理使用各种查询操作符、投影技术和优化策略,可以构建高效的数据查询系统。理解查询语言的各种特性对于开发高性能的MongoDB应用程序至关重要。