dump() 输出当前阶段的原始 MQL 语句,用于验证条件翻译是否正确;tapStage() 捕获中间管道结果为 Collection 供调试;Robo 3T 分步执行可验证各阶段真实输出。

用 dump() 打印当前阶段的 MQL 语句
在 Laravel + laravel-mongodb 环境下,dump() 是最轻量、最直接的调试入口。它不执行查询,只输出当前构建到该位置的原始 MongoDB 查询语句(MQL),帮你确认条件是否被正确翻译。
常见错误现象:明明写了 Query::eq('status', 'active'),结果查出来一堆 inactive 数据——很可能是 match() 被漏写,或嵌套逻辑括号错位导致条件未生效。
- 必须链式调用在目标阶段之后,比如
->match(...)->dump()->group(...),否则打印的是前一阶段的语句 -
dump()输出的是纯 JSON-like 字符串,注意检查字段名拼写、引号是否闭合、操作符大小写(如$eq不是eq) - 若使用
Query::or()或Query::and(),输出中会看到$or数组,务必核对每个子条件的结构是否合法
用 tapStage() 拦截并查看中间阶段输出
仅看 MQL 不够?你需要知道「这个 $match 真的筛掉了多少文档」、「$group 后的 _id 是不是你预期的字段值」——这时就得用 tapStage() 宏捕获实际数据流。
它的本质是在指定阶段后插入一个 $project + 回调,把当前管道输出转成 Laravel Collection 交给你处理。
- 回调函数接收
Collection,可直接dd($results->take(5)->toArray())查前 5 条,避免全量 dump 崩掉内存 - 不要在生产环境保留
tapStage(),它会强制 materialize 整个中间结果,可能触发allowDiskUse:true或 OOM - 如果某阶段输出为空,先确认上游
$match是否太严格,再检查字段是否存在(MongoDB 对缺失字段默认返回null,$group时_id: null很容易被忽略)
在 Robo 3T 中分步执行管道阶段
脱离应用代码,在 GUI 工具里「逐帧播放」聚合过程,是最接近数据库真实行为的验证方式。Robo 3T 的 Execute up to this stage 功能就是为此设计的。
适用场景:后端逻辑没问题,但最终结果仍异常;或者你想快速验证某个表达式(比如 $dateToString 格式是否正确)。
- 光标必须精准停在
{$stage: {...}}的{或$上,右键才出现分步执行选项 - 注意 Robo 3T 默认只显示前 50 行结果,若某阶段输出远超此数,需手动点击「Load More」或加
{$limit: 100}辅助观察 - 对比各阶段文档数量变化:比如
$match后从 10000→800,但$lookup后变成 0,大概率是localField/foreignField类型不匹配(ObjectId vs 字符串)
警惕表达式中的字段路径和空值陷阱
90% 的逻辑偏差来自字段引用错误或对 null 的误判,而不是聚合语法本身。
例如写 $sum: "$items.price",但部分文档的 items 是空数组或缺失,MongoDB 会把 $items.price 解析为 null,而 $sum 遇到 null 默认跳过——这导致统计值偏低,却不易察觉。
- 用
$ifNull显式兜底:$sum: { $ifNull: ["$items.price", 0] } - 嵌套字段必须用完整路径:
$name.first有效,$first无效(除非顶层真有叫first的字段) - 区分
$field(取值)和$$CURRENT.field(在$cond等上下文中显式引用当前文档)
复杂点永远不在语法有多难,而在你是否假设了数据形态——实际集合里总有几条文档不按套路出牌。

















