MongoDB 条件操作符

MongoDB 条件操作符全解析

(MongoDB 8.0+,2025 年最新实践)

核心结论
条件操作符 = 查询(find)和更新(update)的“逻辑引擎”
所有操作符都以 $ 开头,支持嵌套、数组、正则、地理、逻辑组合


一、条件操作符分类速览

分类操作符用途
比较$eq, $ne, $gt, $gte, $lt, $lte, $in, $nin数值、字符串、日期比较
逻辑$and, $or, $not, $nor组合多个条件
元素$exists, $type判断字段存在或类型
数组$all, $elemMatch, $size数组匹配
评估$regex, $text, $mod, $where正则、文本、取模、JS 表达式
地理$geoWithin, $near, $geoIntersects地理空间查询

二、比较操作符(Comparison Operators)

操作符等价写法示例
$eqfield: value{ age: { $eq: 30 } }{ age: 30 }
$ne不等于{ status: { $ne: "active" } }
$gt大于{ salary: { $gt: 5000 } }
$gte大于等于{ createdAt: { $gte: new Date("2025-01-01") } }
$lt小于{ age: { $lt: 25 } }
$lte小于等于{ score: { $lte: 100 } }
$in在数组中{ role: { $in: ["admin", "editor"] } }
$nin不在数组中{ tag: { $nin: ["spam", "ad"] } }
// 推荐写法(简洁)
db.users.find({ age: 30 })                    // $eq
db.users.find({ age: { $gte: 18, $lte: 65 } }) // 范围
db.users.find({ email: { $in: [/gmail\.com$/, /163\.com$/] } }) // 正则数组

三、逻辑操作符(Logical Operators)

操作符说明示例
$and所有条件都满足{ $and: [{ age: { $gt: 18 } }, { status: "active" }] }
$or任一条件满足{ $or: [{ age: { $lt: 13 } }, { age: { $gt: 65 } }] }
$not取反{ age: { $not: { $gte: 30 } } }
$nor都不满足{ $nor: [{ status: "banned" }, { role: "admin" }] }
// 查找 18~65 岁活跃用户
db.users.find({
  $and: [
    { age: { $gte: 18 } },
    { age: { $lte: 65 } },
    { status: "active" }
  ]
})

// 简写:MongoDB 自动隐式 AND
db.users.find({ age: { $gte: 18, $lte: 65 }, status: "active" })

// 查找未激活或已封禁用户
db.users.find({
  $or: [
    { status: "inactive" },
    { banned: true }
  ]
})

四、元素操作符(Element Operators)

操作符说明示例
$exists字段是否存在{ phone: { $exists: true } }
$type字段类型{ age: { $type: "number" } }{ age: { $type: 2 } }
// 查找有地址的用户
db.users.find({ "address": { $exists: true } })

// 查找 age 是数字的用户(排除字符串)
db.users.find({ age: { $type: "number" } })

// 常见类型编号
// 1: double, 2: string, 3: object, 4: array, 8: boolean, 9: date, 10: null, 16: int, 18: long

五、数组操作符(Array Operators)

操作符说明示例
$all数组包含所有元素{ tags: { $all: ["tech", "ai"] } }
$elemMatch数组中任一对象满足多条件{ scores: { $elemMatch: { subject: "math", score: { $gte: 90 } } } }
$size数组长度{ hobbies: { $size: 3 } }
// 拥有 JS 和 Python 技能
db.employees.find({ skills: { $all: ["JavaScript", "Python"] } })

// 成绩中数学 ≥90 且英语 ≥85
db.students.find({
  scores: {
    $elemMatch: {
      subject: "math",
      score: { $gte: 90 }
    }
  },
  scores: {
    $elemMatch: {
      subject: "english",
      score: { $gte: 85 }
    }
  }
})

// 爱好正好 3 个
db.users.find({ hobbies: { $size: 3 } })

六、评估操作符(Evaluation Operators)

操作符说明示例
$regex正则匹配{ name: { $regex: /^李/, $options: "i" } }
$text全文搜索(需文本索引){ $text: { $search: "MongoDB" } }
$mod取模{ age: { $mod: [5, 0] } } → 年龄能被 5 整除
$whereJS 表达式(慎用!){ $where: "this.age > this.children.length * 10" }
// 姓名以 “张” 开头(忽略大小写)
db.users.find({ name: { $regex: /^张/i } })

// 全文搜索(需先创建索引)
db.articles.createIndex({ title: "text", content: "text" })
db.articles.find({ $text: { $search: "MongoDB 性能" } })

// 年龄是 5 的倍数
db.users.find({ age: { $mod: [5, 0] } })

七、地理空间操作符(Geospatial)

// 创建 2dsphere 索引
db.stores.createIndex({ location: "2dsphere" })

// 查找 10km 内门店
db.stores.find({
  location: {
    $near: {
      $geometry: { type: "Point", coordinates: [116.4, 39.9] },
      $maxDistance: 10000
    }
  }
})

// 查找在北京三环内的点
db.stores.find({
  location: {
    $geoWithin: {
      $geometry: {
        type: "Polygon",
        coordinates: [/* 三环坐标数组 */]
      }
    }
  }
})

八、更新中使用的条件操作符

// 只有当年龄 > 30 才加薪
db.employees.updateMany(
  { age: { $gt: 30 } },
  { $inc: { salary: 1000 } }
)

// 数组中存在 Python 才添加 Go
db.employees.updateMany(
  { skills: "Python" },
  { $addToSet: { skills: "Go" } }
)

九、性能与索引建议

操作符是否建议建索引索引类型
$eq, $gt, $lt单字段 / 复合
$in是(小数组)单字段
$regex(前缀)单字段
$text必须text 索引
$elemMatch复合索引
$where否(全表扫描)避免使用
// 推荐索引
db.users.createIndex({ status: 1, age: -1 })
db.users.createIndex({ email: 1 })
db.users.createIndex({ "address.city": 1 })

十、完整条件查询示例脚本

// complex_query.js
use company

print("复杂条件查询示例\n")

// 1. 技术部、30~40岁、会 Python 的活跃员工
const result1 = db.employees.find({
  department: "技术部",
  age: { $gte: 30, $lte: 40 },
  skills: "Python",
  status: "active"
})
.sort({ age: -1 })
.limit(5)
.projection({ name: 1, age: 1, skills: 1, _id: 0 })

print("技术部 Python 工程师(30-40岁):")
result1.forEach(printjson)

// 2. 姓名含“李”或邮箱是163,地址存在
const result2 = db.users.find({
  $or: [
    { name: { $regex: /李/ } },
    { email: { $regex: /@163\.com$/ } }
  ],
  "address": { $exists: true }
}).count()

print(`\n匹配“李”或163邮箱且有地址的用户:${result2} 人`)

// 3. 爱好正好3个,且包含“阅读”
const result3 = db.users.find({
  hobbies: { $size: 3 },
  hobbies: "阅读"
}).limit(3)

print("\n爱好正好3个且包含阅读的用户:")
result3.forEach(doc => printjson(doc.hobbies))

运行:

mongosh complex_query.js

十一、一句话总结

“MongoDB 条件操作符 = $ + 逻辑/比较/数组/正则 + 索引 = 强大查询引擎”


快速操作符模板

// 范围查询
{ age: { $gte: 18, $lte: 65 } }

// 数组包含
{ tags: { $all: ["A", "B"] } }

// 正则忽略大小写
{ name: { $regex: /^admin/i } }

// 逻辑组合
{
  $and: [
    { status: "active" },
    { $or: [{ role: "admin" }, { role: "editor" }] }
  ]
}

官方文档

  • https://www.mongodb.com/docs/manual/reference/operator/query/
  • https://www.mongodb.com/docs/manual/reference/operator/aggregation/

如需 复杂嵌套条件正则性能优化从 SQL WHERE 迁移实时条件订阅(Change Streams),欢迎继续提问!

文章已创建 2349

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部