查询运算符
$in/$elemMatch/$regex。
30 分钟
查询运算符
这一课你将能做到
- 熟练使用比较(
$gt/$lt/$in/$ne)、逻辑($and/$or/$not)、元素($exists/$type)三大类运算符组合出任意查询 - 正确使用
$elemMatch匹配数组元素,并说清楚它和「多个点号条件」的区别 - 用
$regex和$expr处理模糊匹配与「字段间比较」这类高级场景,知道它们的性能代价
为什么要学
find({userId: 1024}) 只能解决 10% 的查询。真实需求是:「查最近 7 天得分 60 到 100 之间的提交」「查 tags 里同时包含 mongo 和 index 的课程」「查 doneLessons 数组长度大于 5 的用户」。这些全靠运算符。
面试里「MongoDB 查询怎么写」几乎是必问,而 $elemMatch 是区分「用过」和「用明白」的分水岭。
先建立图像
运算符分类地图:
比较: $eq $ne $gt $gte $lt $lte $in $nin
逻辑: $and $or $not $nor
元素: $exists $type
数组: $all $elemMatch $size
字符串: $regex
评估: $expr(字段 vs 字段比较) $mod
隐式 AND vs 显式 $and 的区别场景:
// 这两个等价
db.submissions.find({ userId: 1024, status: "accepted" })
db.submissions.find({ $and: [ {userId: 1024}, {status: "accepted"} ] })
// 但「同一字段两个条件 + 另一个字段」时,对象 key 不能重复,必须用 $and
db.submissions.find({ $and: [ {score: {$gte: 60}}, {score: {$lt: 90}} ] })
// 其实同字段多条件写一个对象里就行:
db.submissions.find({ score: { $gte: 60, $lt: 90 } })
跟着做
准备数据:
use codeforge
db.submissions.drop()
db.submissions.insertMany([
{ userId: 1024, lessonSlug: "mdbrm-intro", status: "accepted", score: 100, attempts: 1, tags: ["easy","crud"], submittedAt: new Date("2026-10-01") },
{ userId: 1024, lessonSlug: "mdbrm-types", status: "failed", score: 40, attempts: 2, tags: ["hard"], submittedAt: new Date("2026-10-02") },
{ userId: 1024, lessonSlug: "mdbrm-crud", status: "accepted", score: 85, attempts: 3, tags: ["crud","write"], submittedAt: new Date("2026-10-04") },
{ userId: 2048, lessonSlug: "mdbrm-intro", status: "accepted", score: 60, attempts: 1, tags: ["easy"], submittedAt: new Date("2026-10-05") },
{ userId: 2048, lessonSlug: "mdbrm-types", status: "pending", score: 0, attempts: 0, submittedAt: new Date("2026-10-06") }
])
步骤 1:比较运算符
// 及格线以上
db.submissions.find({ score: { $gte: 60 } })
// 区间:60 ~ 90(含头不含尾)
db.submissions.find({ score: { $gte: 60, $lt: 90 } })
// 在集合内
db.submissions.find({ status: { $in: ["accepted", "pending"] } })
// 不等于(注意:$ne 也会匹配「字段不存在」的文档!)
db.submissions.find({ status: { $ne: "failed" } })