Skip to content
On this page

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
        }
      }
    }
  }
])

最佳实践

查询优化建议

  1. 使用适当的索引:为经常查询的字段创建索引
  2. 避免全表扫描:确保查询能够使用索引
  3. 使用投影:只返回需要的字段
  4. 限制结果数量:使用limit()限制返回结果
  5. 避免大偏移量:使用范围查询代替大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应用程序至关重要。