MongoDB 查询语句备忘手册

一、基本检索

1.1 条件查询

javascript 复制代码
// ===== 等值 =====
db.users.find({ status: "active" })

// ===== 比较 =====
db.orders.find({ amount: { $gt: 100 } })           // >
db.orders.find({ amount: { $gte: 100 } })          // >=
db.orders.find({ amount: { $lt: 500 } })           // <
db.orders.find({ amount: { $gte: 100, $lte: 500 } })  // 100-500

// ===== IN / NOT IN =====
db.products.find({ category: { $in: ["电子", "家居"] } })
db.products.find({ status: { $nin: ["废弃", "下架"] } })

// ===== 不等于 =====
db.users.find({ level: { $ne: "guest" } })

// ===== 存在/不存在 =====
db.users.find({ email: { $exists: true } })    // 有 email 字段
db.users.find({ phone: { $exists: false } })   // 没有 phone 字段

// ===== 类型判断 =====
db.orders.find({ amount: { $type: "double" } })    // 金额为 double 类型
db.orders.find({ amount: { $type: ["int", "long", "double"] } })

1.2 逻辑组合

javascript 复制代码
// AND (隐式, 逗号分隔)
db.users.find({ status: "active", age: { $gte: 18 } })

// OR
db.users.find({ $or: [
    { status: "active" },
    { vipLevel: { $gte: 3 } }
]})

// NOR (全部不满足)
db.users.find({ $nor: [
    { status: "banned" },
    { deleted: true }
]})

// NOT
db.users.find({ age: { $not: { $gte: 18 } } })   // 未满 18

// 组合
db.orders.find({
    status: "completed",
    $or: [{ channel: "app" }, { channel: "web" }],
    amount: { $gt: 100 }
})

1.3 正则与模糊搜索

javascript 复制代码
// 以 "张" 开头
db.users.find({ name: /^张/ })

// 包含 "科技"
db.users.find({ company: /科技/ })

// 不区分大小写
db.products.find({ name: /iphone/i })

// 以 .com 结尾
db.users.find({ email: /\.com$/ })

// $regex 写法
db.users.find({ name: { $regex: "^张", $options: "i" } })

1.4 嵌套文档与数组查询

javascript 复制代码
// ===== 嵌套文档精确匹配 =====
db.orders.find({ "address.city": "北京" })

// ===== 数组包含 =====
db.products.find({ tags: "热销" })                    // tags 数组包含 "热销"
db.products.find({ tags: { $all: ["热销", "新品"] } })  // 同时包含

// ===== 数组大小 =====
db.users.find({ hobbies: { $size: 3 } })             // 正好 3 个爱好

// ===== $elemMatch: 数组元素复合条件 =====
db.orders.find({
    items: { $elemMatch: { product: "SKU001", qty: { $gt: 5 } } }
})

// ===== 数组第 N 个元素 =====
db.orders.find({ "items.0.product": "SKU001" })      // 第一个元素

1.5 投影与分页

javascript 复制代码
// 只返回指定字段
db.users.find({}, { name: 1, email: 1, _id: 0 })

// 排除某些字段
db.users.find({}, { password: 0, salt: 0 })

// 分页 (skip + limit)
db.orders.find({}).skip(20).limit(10)     // 第 3 页

// 游标分页 (推荐, 利用索引)
db.orders.find({ _id: { $gt: lastId } }).limit(50).sort({ _id: 1 })

// 排序
db.orders.find({}).sort({ createdAt: -1 })           // 最新在前
db.orders.find({}).sort({ status: 1, amount: -1 })   // 多字段

二、更新操作

2.1 字段更新

javascript 复制代码
// 设置字段
db.users.updateOne(
    { _id: userId },
    { $set: { lastLogin: new Date(), status: "active" } }
)

// 批量更新
db.orders.updateMany(
    { status: "expired" },
    { $set: { status: "cancelled", cancelledAt: new Date() } }
)

// 删除字段
db.users.updateOne({ _id: userId }, { $unset: { tempToken: "" } })

// 重命名字段
db.products.updateMany({}, { $rename: { "oldName": "newName" } })

// 字段不存在时设置 (insert 时生效)
db.users.updateOne(
    { _id: userId },
    { $setOnInsert: { createdAt: new Date() } },
    { upsert: true }
)

2.2 数值增减

javascript 复制代码
// 原子加减
db.products.updateOne({ _id: pid }, { $inc: { stock: -1, sold: 1 } })
db.users.updateOne({ _id: uid }, { $inc: { points: 10 } })

// 乘法
db.orders.updateMany({}, { $mul: { amount: 1.13 } })   // 加 13% 税

// 取最大/最小
db.scores.updateOne({ _id: uid }, { $max: { highScore: 95 } })
db.sensors.updateOne({ _id: sid }, { $min: { minTemp: -5 } })

2.3 数组操作

javascript 复制代码
// 推到数组末尾
db.users.updateOne({ _id: uid }, { $push: { tags: "VIP" } })

// 推到数组末尾 (去重)
db.users.updateOne({ _id: uid }, { $addToSet: { tags: "VIP" } })

// 一次加多个
db.users.updateOne({ _id: uid }, { 
    $push: { tags: { $each: ["新客", "首单"], $slice: -20 } }  // 只保留最后 20
})

// 从数组移除
db.users.updateOne({ _id: uid }, { $pull: { tags: "VIP" } })
db.users.updateOne({ _id: uid }, { $pull: { tags: { $in: ["过期", "禁用"] } } })

// 移除数组首/尾
db.queue.updateOne({ _id: qid }, { $pop: { tasks: -1 } })  // 移除第一个
db.queue.updateOne({ _id: qid }, { $pop: { tasks: 1 } })   // 移除最后一个

// 更新数组中匹配的元素
db.orders.updateOne(
    { _id: oid, "items.sku": "SKU001" },
    { $set: { "items.$.status": "shipped" } }
)

2.4 upsert(存在则更新,不存在则插入)

javascript 复制代码
db.carts.updateOne(
    { userId: uid },
    { 
        $setOnInsert: { userId: uid, createdAt: new Date() },
        $push: { items: { sku: "SKU001", qty: 1 } }
    },
    { upsert: true }
)

三、聚合查询

3.1 分组统计

javascript 复制代码
// 按字段分组计数
db.orders.aggregate([
    { $group: { _id: "$status", count: { $sum: 1 } } }
])

// 按多字段分组
db.orders.aggregate([
    { $group: {
        _id: { channel: "$channel", status: "$status" },
        count: { $sum: 1 },
        totalAmount: { $sum: "$amount" }
    }},
    { $sort: { totalAmount: -1 } }
])

// 按时间粒度分组 (天)
db.orders.aggregate([
    { $group: {
        _id: { $dateToString: { format: "%Y-%m-%d", date: "$createdAt" } },
        revenue: { $sum: "$amount" },
        orders: { $sum: 1 }
    }},
    { $sort: { _id: -1 } },
    { $limit: 30 }
])

// 按时间粒度分组 (月)
db.orders.aggregate([
    { $group: {
        _id: {
            year:  { $year: "$createdAt" },
            month: { $month: "$createdAt" }
        },
        revenue: { $sum: "$amount" }
    }},
    { $sort: { "_id.year": 1, "_id.month": 1 } }
])

3.2 聚合运算符

javascript 复制代码
db.sales.aggregate([
    { $match: { date: { $gte: ISODate("2026-01-01") } } },
    { $group: {
        _id: "$productId",
        total:    { $sum: "$revenue" },        // 求和
        avgPrice: { $avg: "$price" },           // 平均
        minPrice: { $min: "$price" },           // 最小值
        maxPrice: { $max: "$price" },           // 最大值
        cnt:      { $sum: 1 },                  // 计数
        firstSale:{ $first: "$date" },          // 第一个
        lastSale: { $last: "$date" },           // 最后一个
        products: { $addToSet: "$sku" },        // 去重集合
        allPrices: { $push: "$price" }          // 不去重数组
    }}
])

3.3 过滤 → 展开 → 分组流水线

javascript 复制代码
// 典型三步: 过滤 → 展开数组 → 分组统计
db.articles.aggregate([
    // 1. 过滤: 最近一年
    { $match: { publishDate: { $gte: ISODate("2025-01-01") } } },
    // 2. 展开标签
    { $unwind: "$tags" },
    // 3. 统计
    { $group: { _id: "$tags", count: { $sum: 1 } } },
    { $sort: { count: -1 } },
    { $limit: 20 }
])

3.4 分桶统计

javascript 复制代码
// 手动分桶
db.users.aggregate([
    { $bucket: {
        groupBy: "$age",
        boundaries: [0, 18, 25, 35, 50, 100],
        default: "未知",
        output: { count: { $sum: 1 }, avgBalance: { $avg: "$balance" } }
    }}
])

// 自动分桶
db.users.aggregate([
    { $bucketAuto: {
        groupBy: "$balance",
        buckets: 5,
        output: { count: { $sum: 1 } }
    }}
])

3.5 多维度统计(单次查询)

javascript 复制代码
db.orders.aggregate([
    { $match: { createdAt: { $gte: ISODate("2026-01-01") } } },
    { $facet: {
        // 按状态
        byStatus: [
            { $group: { _id: "$status", count: { $sum: 1 } } }
        ],
        // 按渠道
        byChannel: [
            { $group: { _id: "$channel", count: { $sum: 1 } } }
        ],
        // Top 10 客户
        topCustomers: [
            { $group: { _id: "$userId", total: { $sum: "$amount" } } },
            { $sort: { total: -1 } },
            { $limit: 10 }
        ]
    }}
])

3.6 连表查询

javascript 复制代码
// 基础连表 (orders → users)
db.orders.aggregate([
    { $match: { status: "completed" } },
    { $lookup: {
        from: "users",
        localField: "userId",
        foreignField: "_id",
        pipeline: [
            { $project: { name: 1, tier: 1, _id: 0 } }
        ],
        as: "user"
    }},
    { $unwind: "$user" }
])

// 多表连查
db.orders.aggregate([
    { $lookup: { from: "users",    localField: "userId",    foreignField: "_id", as: "user" } },
    { $lookup: { from: "products", localField: "productId", foreignField: "_id", as: "product" } },
    { $unwind: "$user" },
    { $unwind: "$product" },
    { $project: {
        _id: 1, amount: 1,
        userName: "$user.name",
        productName: "$product.name"
    }}
])

3.7 去重取值

javascript 复制代码
// 查询某字段有哪些取值
db.orders.distinct("status")

// 带过滤条件的去重
db.orders.distinct("channel", { createdAt: { $gte: ISODate("2026-01-01") } })

// 聚合方式去重
db.orders.aggregate([
    { $group: { _id: "$channel" } }
])

3.8 结果输出

javascript 复制代码
// 输出为新集合
db.orders.aggregate([
    { $group: { _id: "$productId", total: { $sum: "$amount" } } },
    { $out: "product_summary" }              // 完全替换
])

// 合并到已有集合
db.orders.aggregate([
    { $group: { _id: "$userId", daily: { $sum: "$amount" } } },
    { $merge: {
        into: "user_stats",
        on: "_id",
        whenMatched: "merge",                // 合并
        whenNotMatched: "insert"             // 新文档插入
    }}
])

四、文本搜索

javascript 复制代码
// 创建文本索引
db.articles.createIndex({ title: "text", content: "text" })

// 搜索单个词
db.articles.find({ $text: { $search: "MongoDB" } })

// 搜索多个词 (OR 逻辑)
db.articles.find({ $text: { $search: "MongoDB 聚合" } })

// 精确短语 (双引号)
db.articles.find({ $text: { $search: "\"聚合管线\"" } })

// 排除词 (-)
db.articles.find({ $text: { $search: "MongoDB -MySQL" } })

// 按相关性排序
db.articles.find(
    { $text: { $search: "MongoDB" } },
    { score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })

五、统计分析

javascript 复制代码
// ===== 集合统计 =====
db.orders.countDocuments()                     // 文档总数
db.orders.countDocuments({ status: "completed" }) // 带条件
db.orders.estimatedDocumentCount()             // 估算 (基于元数据,快)

// ===== 聚合统计 =====
db.orders.aggregate([
    { $match: { status: "completed" } },
    { $group: { _id: null,
        totalRevenue: { $sum: "$amount" },
        avgOrder:     { $avg: "$amount" },
        maxOrder:     { $max: "$amount" },
        orderCount:   { $sum: 1 }
    }}
])

// ===== 按小时/星期分布 =====
db.orders.aggregate([
    { $group: {
        _id: { $hour: "$createdAt" },          // 小时 (0-23)
        // _id: { $dayOfWeek: "$createdAt" },  // 星期 (1=周日)
        count: { $sum: 1 }
    }},
    { $sort: { _id: 1 } }
])

六、索引管理

javascript 复制代码
// 创建索引
db.orders.createIndex({ status: 1 })                    // 单字段
db.orders.createIndex({ status: 1, createdAt: -1 })     // 复合
db.orders.createIndex({ userId: 1 }, { unique: true })  // 唯一
db.articles.createIndex({ title: "text" })              // 文本
db.locations.createIndex({ geo: "2dsphere" })           // 地理

// TTL 索引 (自动过期)
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

// 查看索引
db.orders.getIndexes()

// 删除索引
db.orders.dropIndex("status_1_createdAt_-1")
db.orders.dropIndexes()   // 删除所有非 _id 索引

// 查看索引使用情况
db.orders.aggregate([{ $indexStats: {} }])

// 强制使用索引
db.orders.find({ status: "completed" }).hint({ status: 1 })

七、管理命令

bash 复制代码
# ===== 查看 =====
show dbs                          # 所有数据库
show collections                  # 当前库所有集合
db.stats()                        # 库统计
db.orders.stats()                 # 集合统计

# ===== 复制 =====
db.orders.find().forEach(function(d) { db.orders_bak.insert(d) })

# ===== 删除 =====
db.users.deleteOne({ _id: uid })
db.users.deleteMany({ status: "banned" })
db.temp.drop()                    # 删除集合

# ===== explain =====
db.orders.find({ status: "completed" }).explain("executionStats")

# ===== 慢查询 =====
db.setProfilingLevel(1, { slowms: 100 })   # 记录 > 100ms 的查询
db.system.profile.find().sort({ ts: -1 }).limit(5).pretty()
相关推荐
一叶龙洲5 小时前
wslg打开Ubuntu24.04默认打开图形界面
linux·服务器·数据库·ubuntu
CCPC不拿奖不改名5 小时前
大模型推理架构与开源生态知识整理
数据库·windows·python·架构·langchain·开源·github
爬也要爬着前进6 小时前
redis主从搭建
数据库·redis·缓存
@Mike@7 小时前
02-数据库学习笔记(SQL引擎)
数据库·笔记·学习
踏月的造梦星球8 小时前
达梦数据库执行计划与性能分析入门:EXPLAIN、AUTOTRACE 与 ET
服务器·数据库·oracle
笃行3508 小时前
国产化落地避坑 · 干货向|Oracle 迁金仓 KES,我把外连接消除排在隐性陷阱第一位
数据库
老纪的技术唠嗑局8 小时前
花一年时间整理出的:AI 数据库混合搜索入门实践
数据库
川石课堂软件测试9 小时前
安全测试|常见SQL注入攻击方式、实例及预防
服务器·数据库·sql·功能测试·测试工具·安全·单元测试
笃行3509 小时前
国产化落地避坑 · 干货向|迁移后那条「测试能过、一上生产就查空」的 SQL,多半栽在 WHERE 函数顺序上
数据库