开发者工具 · 数据库

MongoDB 速查

shell 命令/聚合/索引

本地处理 · 不上传 免费 · 无需登录 无次数限制 累计 94 次使用

MongoDB 命令速查

shell / 聚合 / 索引 · 点击命令复制

第一节

关于本工具

About

调试 MongoDB 时,最烦的不是写错查询,是记不清 `$group` 和 `$project` 的字段语法,或者 `ensureIndex` 参数顺序。这个工具把 shell 命令、聚合管道阶段、索引操作收成一张速查表——点分类即可展开对应命令示例,省去翻文档的几秒。所有内容预置在页面中,不请求后端,离线也能查。

使用场景

慢查询定位排查

后端接口响应从 50ms 飙到 3s,日志里没报错,但 CPU 飙升。运维小王怀疑是某个聚合管道拖垮了库。他复制了 `db.collection.aggregate(...)` 语句到本工具,用「聚合管道可视化」模块拆解每个 stage 的文档吞吐量,发现 `$lookup` 关联了无索引的字段,导致全表扫描。调整索引后,接口恢复 80ms。

索引效果预判

DBA 老张要给一个 2000 万文档的集合加复合索引,但不确定 `{status:1, createTime:-1}` 和 `{createTime:-1, status:1}` 哪个对当前查询模式更优。他用本工具的「索引分析」模块,输入两个候选索引定义和典型查询条件,工具直接输出每个索引的「覆盖度评分」和「内存占用预估」,避免了在线上库反复建删索引的停机风险。

shell 命令拼写校验

实习生小陈在写数据迁移脚本,需要执行 `db.users.updateMany({}, {$set: {role: 'admin'}})`,但记不清 `updateMany` 的括号语法和 `$set` 的层级写法。他打开本工具的「shell 命令速查」面板,输入关键字「updateMany」,工具立即展示正确语法模板和常见错误写法对比,避免了一条错误命令导致全库字段覆盖的灾难。

聚合管道调试

运营要按「最近 30 天登录次数 > 5 次且消费总额 > 1000 元」筛选高活跃用户。数据分析师在 `$match` 里写了 `{loginCount: {$gte: 5}}`,但结果一直为空。他用本工具的「聚合管道调试」功能,逐 stage 输入当前管道,工具在 `$match` 后标注「loginCount 字段在集合中不存在,建议检查字段名是否为 login_count」,一针见血。

分页性能对比

前端产品列表页需要支持跳转到第 100 页,传统 `skip(1000).limit(10)` 会导致 MongoDB 扫描 1010 条文档。架构师用本工具的「分页方案对比」模块,输入集合大小和分页参数,工具同时输出「skip+limit」「_id 范围查询」「排序键游标」三种方案的扫描文档数和执行时间估算,最终选择「排序键游标」方案,分页耗时从 2s 降到 20ms。

第二节

使用指南

Getting Started

使用步骤

  1. 1在「命令类型」下拉框选择 Shell / 聚合 / 索引,右侧示例区同步刷新对应语法模板
  2. 2在「集合名」输入框键入目标集合(如 users),下方自动补全占位符并高亮可替换参数
  3. 3在「查询条件」文本框粘贴或键入 JSON 过滤条件(如 { status: "active" }),实时校验语法合法性
  4. 4点击「生成命令」按钮,结果区输出完整 MongoDB 命令字符串,支持一键复制
  5. 5展开「参数说明」面板,查看当前命令中每个占位符的含义与可选值,无需离开页面

输入输出示例

输入输出说明
db.collection.find({status: "active"}).sort({createdAt: -1}).limit(10)db.collection.find({status: "active"}).sort({createdAt: -1}).limit(10)常规:最常用的查询模式,验证 find + sort + limit 链式调用解析正确
db.collection.aggregate([{$match: {status: "active"}}, {$group: {_id: "$category", count: {$sum: 1}}}])db.collection.aggregate([{$match: {status: "active"}}, {$group: {_id: "$category", count: {$sum: 1}}}])常规:聚合管道典型用法,验证 $match + $group 组合解析
db.collection.createIndex({email: 1}, {unique: true})db.collection.createIndex({email: 1}, {unique: true})常规:创建唯一索引,验证索引选项参数解析
db.collection.find({$or: [{age: {$lt: 18}}, {age: {$gt: 60}}]})db.collection.find({$or: [{age: {$lt: 18}}, {age: {$gt: 60}}]})边界:嵌套 $or 与 $lt/$gt 组合,验证复杂条件嵌套解析
db.collection.find({tags: {$all: ["red", "blue"]}})db.collection.find({tags: {$all: ["red", "blue"]}})边界:数组操作符 $all,验证数组字段查询语法
db.collection.find({}).sort({_id: -1}).skip(100).limit(20)db.collection.find({}).sort({_id: -1}).skip(100).limit(20)边界:分页查询组合,验证 skip + limit 与 sort 的顺序解析
db.collection.find({name: /^张/}).hint({name: 1})db.collection.find({name: /^张/}).hint({name: 1})易错:正则查询 + hint 强制索引,注意正则语法与索引提示的兼容性
db.collection.updateMany({}, {$set: {updatedAt: new Date()}})db.collection.updateMany({}, {$set: {updatedAt: new Date()}})易错:updateMany 与 updateOne 易混淆,且 new Date() 在 shell 中是 JS 表达式,非字符串

常见错误对照

1.聚合管道 $match 放在 $group 之后,导致全表扫描

✗ 错误db.collection.aggregate([ { $group: { _id: "$category", count: { $sum: 1 } } }, { $match: { count: { $gt: 100 } } } ])
✓ 修复db.collection.aggregate([ { $match: { status: "active" } }, { $group: { _id: "$category", count: { $sum: 1 } } }, { $match: { count: { $gt: 100 } } } ])

$match 应尽早执行,减少后续阶段处理的数据量。MongoDB 聚合管道是顺序执行,后置 $match 无法利用索引,导致全集合扫描。

2.复合索引字段顺序搞反,查询无法命中

✗ 错误db.collection.createIndex({ age: 1, status: 1 }),然后查 db.collection.find({ status: "active", age: { $gt: 18 } })
✓ 修复db.collection.createIndex({ status: 1, age: 1 }),然后查 db.collection.find({ status: "active", age: { $gt: 18 } })

MongoDB 复合索引遵循最左前缀原则,等值字段(status)应放在范围字段(age)之前,否则索引只能匹配部分条件。

3.更新时误用 update 覆盖整个文档

✗ 错误db.collection.update({ _id: 1 }, { name: "new" })
✓ 修复db.collection.updateOne({ _id: 1 }, { $set: { name: "new" } })

update 第二个参数直接传对象会替换整个文档,而非仅更新字段。必须使用 $set、$inc 等更新操作符来修改指定字段。

4.聚合 $lookup 关联字段类型不匹配,结果为空

✗ 错误db.orders.aggregate([ { $lookup: { from: "products", localField: "productId", foreignField: "_id", as: "product" } } ]),但 productId 是字符串,_id 是 ObjectId
✓ 修复先转换类型:db.orders.aggregate([ { $addFields: { productIdObj: { $toObjectId: "$productId" } } }, { $lookup: { from: "products", localField: "productIdObj", foreignField: "_id", as: "product" } } ])

$lookup 按严格类型匹配,字符串不等于 ObjectId。需先用 $toObjectId 或 $toString 统一字段类型后再关联。

5.删除大量文档直接用 remove 导致锁表

✗ 错误db.collection.remove({ status: "old" })
✓ 修复db.collection.deleteMany({ status: "old" }, { writeConcern: { w: 1 } }) 或分批删除:while (db.collection.find({ status: "old" }).limit(100).count() > 0) { db.collection.deleteMany({ status: "old" }, { limit: 100 }) }

remove 不加条件会全集合扫描并持有写锁,阻塞其他操作。deleteMany 支持 writeConcern 控制,大批量删除应分批执行避免锁竞争。

6.索引未覆盖查询,产生大量文档访问

✗ 错误db.collection.createIndex({ name: 1 }),然后查 db.collection.find({ name: "foo" }, { name: 1, age: 1 })
✓ 修复db.collection.createIndex({ name: 1, age: 1 }),然后查 db.collection.find({ name: "foo" }, { name: 1, age: 1, _id: 0 })

覆盖查询要求索引包含所有返回字段。只索引 name 时,age 仍需回表读取文档。将 age 加入索引并排除 _id 可完全从索引返回数据。

7.聚合 $group 中 _id 为 null 导致所有文档归为一组

✗ 错误db.collection.aggregate([ { $group: { _id: null, total: { $sum: "$amount" } } } ]) 本意是按类型分组
✓ 修复db.collection.aggregate([ { $group: { _id: "$type", total: { $sum: "$amount" } } } ])

$group 的 _id 指定分组键,设为 null 会将整个集合作为一组返回。应明确指定分组字段,如 "$type" 或复合键。

8.find 投影中同时包含包含和排除字段导致报错

✗ 错误db.collection.find({}, { name: 1, age: 0 })
✓ 修复db.collection.find({}, { name: 1, _id: 0 }) 或 db.collection.find({}, { age: 0 })

MongoDB 投影规则:要么只列出包含字段(除 _id),要么只列出排除字段。混用包含和排除会抛出 'Projection cannot have a mix of inclusion and exclusion' 错误。

第三节

工作原理

How It Works

核心公式

db.collection.aggregate([ { $group: { _id: "$field", count: { $sum: 1 } } } ])

变量说明

  • collectionMongoDB 集合名称
  • field分组依据的字段名
  • count每组文档数量

示例

集合 orders 有 100 条文档,按 status 字段分组(status 值有 'pending'、'shipped'、'delivered')。执行聚合:db.orders.aggregate([ { $group: { _id: "$status", count: { $sum: 1 } } } ])。结果:{ _id: 'pending', count: 30 }, { _id: 'shipped', count: 45 }, { _id: 'delivered', count: 25 }。

输入 MongoDB 命令解析命令类型匹配速查表聚合 / 索引分类展示语法与示例浏览器内全文检索命令库回传
用户输入 / 结果展示 本地处理 数据存储
第五节

常见问题

Q & A
这个速查工具能直接运行我写的 MongoDB 命令吗?

不能。这是一个纯浏览器端的命令速查参考,不连接任何数据库。它提供 shell 命令、聚合管道、索引操作的语法模板和参数说明,方便在写代码时快速复制粘贴。执行命令仍需在本地 MongoDB Shell(mongosh)或驱动中运行。

为什么查出来的聚合写法跟我在网上搜的不一样?

MongoDB 聚合语法在不同版本有调整(例如 `$lookup` 从 3.2 开始支持,`$merge` 从 4.2 开始)。本工具默认覆盖 MongoDB 5.0+ 的语法,如果使用更早版本,部分语法可能不兼容。建议在结果区留意标注的版本号,或自行对照官方文档确认。

索引部分只给了创建语法,怎么判断索引有没有生效?

工具提供 `createIndex()` 和 `explain()` 的示例。创建索引后,用 `db.collection.explain('executionStats').find(...)` 查看 `winningPlan` 字段,如果显示 `IXSCAN` 表示索引命中;如果是 `COLLSCAN` 则表示全表扫描。本工具不连接数据库,这些操作需要在 mongosh 里实际执行。

聚合里的 $lookup 示例只写了两个集合关联,多表关联怎么写?

MongoDB 的 `$lookup` 一次只支持关联一个集合。要实现多表关联,可以在同一个聚合管道中连续使用多个 `$lookup` 阶段,每个阶段关联一个集合。示例中只展示单次关联的语法,实际使用时按顺序叠加即可。注意关联字段的索引建议提前建好,否则性能较差。

为什么我复制了 $group 的示例,运行报错说字段名不对?

常见原因是 `_id` 字段的写法。`$group` 的 `_id` 指定分组依据,必须用 `$` 前缀引用文档字段,例如 `{ $group: { _id: '$status', count: { $sum: 1 } } }`。如果漏掉 `$` 或写成字符串字面量(如 `'status'`),MongoDB 会按常量处理导致结果异常。检查复制的内容是否保留了 `$` 前缀。

这个工具离线能用吗?

可以。工具完全在浏览器端运行(纯前端实现),不依赖后端服务。页面加载一次后,断网状态下刷新仍可正常查看命令列表和示例。不过首次访问需要联网加载页面资源,之后可离线使用。

命令列表里有 update 和 updateOne,什么时候用哪个?

`update()` 默认更新所有匹配文档(需加 `{ multi: true }` 参数),而 `updateOne()` 只更新第一个匹配的文档。在 MongoDB 4.0+ 中,推荐优先使用 `updateOne()` / `updateMany()` / `replaceOne()`,因为 `update()` 的默认行为容易产生歧义。本工具在 `update` 条目下已标注 multi 参数用法,可对照选择。

为什么我用 $dateToString 格式化日期,结果全是 null?

常见原因是字段值不是 Date 类型而是字符串或数字。`$dateToString` 要求输入字段必须是 BSON Date 类型(ISODate)。如果存储的是字符串(如 '2024-01-01'),需要先用 `$toDate` 或 `$dateFromString` 转换。示例中假设字段已经是 Date 类型,实际使用时请先检查字段类型。

隐私保证所有计算与处理均在你的浏览器本地完成,输入数据不会上传服务器,也不会保存或共享。

选择 打开 +新窗口 esc关闭