Skip to content

MongoDB summary parsing

bondi.mongodb.summarize(raw)

Summarize a successful MongoDB explain without a connection or source mutation.

Supports standalone classic/SBE structured winning plans, top-level execution statistics, and aggregation stages beginning with $cursor. For split pipelines, final-stage nReturned is used; execution time is unavailable. Cursor examination totals and index names are retained only for explicitly supported stages that introduce no additional reads. Facets, lookups and unknown pipeline stages leave those fields unavailable. Sharded explains currently return an empty summary.

Planner-only explains have no execution metrics. Unsupported layouts return None fields; malformed supported structures/metrics and failed commands raise ValueError. This is structural validation of the fields consumed, not the entire MongoDB schema.

Parameters:

Name Type Description Default
raw dict[str, Any] | None

ExecutionResult.raw from explain/profile, or None from ordinary run. None returns an empty summary. Check result.status first: failed workload entries also have raw=None.

required

Returns:

Type Description
QuerySummary

A frozen summary; keep the raw document for project-specific analysis.

Raises:

Type Description
ValueError

Input is not an explain document, reports failure, or contains malformed fields in a supported layout.

Source code in src/bondi/mongodb/explain.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
def summarize(raw: dict[str, Any] | None) -> QuerySummary:
    """Summarize a successful MongoDB explain without a connection or source mutation.

    Supports standalone classic/SBE structured winning plans, top-level execution
    statistics, and aggregation stages beginning with $cursor. For split pipelines,
    final-stage nReturned is used; execution time is unavailable. Cursor examination
    totals and index names are retained only for explicitly supported stages that
    introduce no additional reads. Facets, lookups and unknown pipeline stages leave
    those fields unavailable. Sharded explains currently return an empty summary.

    Planner-only explains have no execution metrics. Unsupported layouts return None
    fields; malformed supported structures/metrics and failed commands raise ValueError.
    This is structural validation of the fields consumed, not the entire MongoDB schema.

    Args:
        raw: ExecutionResult.raw from explain/profile, or None from ordinary run.
            None returns an empty summary. Check result.status first: failed workload
            entries also have raw=None.

    Returns:
        A frozen summary; keep the raw document for project-specific analysis.

    Raises:
        ValueError: Input is not an explain document, reports failure, or contains
            malformed fields in a supported layout.
    """
    if raw is None:
        return QuerySummary()
    raw = _document(raw, "raw")
    if not raw or not any(k in raw for k in ("queryPlanner", "stages", "shards", "ok")):
        raise ValueError("Expected a MongoDB explain document")
    if "ok" in raw and raw["ok"] != 1:
        raise ValueError("Explain command did not succeed")
    if "shards" in raw:
        return QuerySummary()

    source = raw
    pipeline = None
    safe_reads = True
    if "stages" in raw:
        pipeline = raw["stages"]
        if not isinstance(pipeline, list):
            raise ValueError("stages must be a list")
        for stage in pipeline:
            _document(stage, "pipeline stage")
            if len([k for k in stage if k.startswith("$")]) != 1:
                raise ValueError("pipeline stage must contain one operator")
        if not pipeline or "$cursor" not in pipeline[0]:
            return QuerySummary()
        source = _document(pipeline[0]["$cursor"], "$cursor")
        safe_reads = all(
            next(k for k in stage if k.startswith("$")) in _CURSOR_ONLY_READS
            for stage in pipeline[1:]
        )

    planner = _document(source.get("queryPlanner", {}), "queryPlanner")
    stages, indexes = _plan(planner)
    # Distributed plan statistics have different scope; do not interpret them as local totals.
    if stages is None and "winningPlan" in planner:
        return QuerySummary()
    stats = _document(source.get("executionStats", {}), "executionStats")
    if stats.get("executionSuccess") is False:
        raise ValueError("Explained execution did not succeed")
    elapsed = _metric(stats, "executionTimeMillis", time=True)
    returned = _metric(stats, "nReturned")
    documents = _metric(stats, "totalDocsExamined")
    keys = _metric(stats, "totalKeysExamined")
    if pipeline is not None and len(pipeline) > 1:
        elapsed = None
        returned = _metric(pipeline[-1], "nReturned")
    if not safe_reads:
        documents, keys, indexes = None, None, None
    return QuerySummary(elapsed, returned, documents, keys, stages, indexes)

Supported layouts and conservative boundaries

The first implementation is tested against saved MongoDB 8.0.4 explains:

  • Standalone find and fully optimized aggregation explains: use top-level executionStats totals and the winning structured query plan.
  • Split aggregations beginning with $cursor: use the final stage's output count. Whole-pipeline execution time is None when stages follow the cursor. Stage executionTimeMillisEstimate values are never summed.
  • Cursor examination totals and index names are retained only when subsequent stages are explicitly known not to introduce more collection reads: $match, $project, $addFields, $set, $unset, $replaceRoot, $replaceWith, $limit, $skip, $sort, $group, $count, $unwind, $sample, and $sortByCount.
  • $lookup, $facet and unknown pipeline operators leave examination totals and index names as None. Even a facet that happens to contain no additional reads is treated conservatively for now. Its final output count can still be reported.
  • Sharded explains and other unsupported layouts return unavailable fields rather than guessed totals. No cross-shard summation or nested pipeline analysis yet.

Malformed supported structures, invalid metrics and reported command/execution failures raise ValueError. Validation covers fields the parser consumes, not the entire MongoDB explain schema. No parser can reliably infer semantics for arbitrary future server layouts; extend fixture coverage before relying on a new layout.

See MongoDB's explain reference for the source fields. The notebook notebooks/workload_demo.ipynb demonstrates planner-only and measured summaries alongside the raw response.