Skip to content

Document six missing aggregation pipeline stages - #64

Merged
guanzhousongmicrosoft merged 4 commits into
documentdb:mainfrom
GuanzhouSong:pr47-aggregation-stages
Aug 3, 2026
Merged

Document six missing aggregation pipeline stages#64
guanzhousongmicrosoft merged 4 commits into
documentdb:mainfrom
GuanzhouSong:pr47-aggregation-stages

Conversation

@GuanzhouSong

Copy link
Copy Markdown
Contributor

Continues @richardsimmonds' work in #47, which this supersedes. His original commit is preserved in this branch's history; the reference gap it identified was real, and six stages that were missing are documented here.

What this adds

$currentOp, $replaceRoot, $search, $setWindowFields, and $unionWith — five stages with no reference page today.

What changed from #47

Four files dropped.$graphLookup, $limit, $project, and $vectorSearch were documented in #59 while #47 was open, and were add/add conflicts against pages that now exist.

$search rewritten. The page documented Atlas-style full-text search over a text index. DocumentDB's $search is a vector search stage — SearchOperatorsList[] holds exactly cosmosSearch and knnBeta (deprecated), and there is no text operator in the search sources, so the original example failed with Unrecognized $search option: text rather than returning nothing. Rewritten against the stage's parsing: both operators, the options carried alongside them (index, count, returnStoredSource), and the operator spec (path, vector, k, filter, exact, oversampling, score), including which fields knnBeta rejects and which need server-side pre-filtering. count is noted as having no observable effect, since the engine parses it but does not yet emit the metadata.

$setWindowFields corrected. The syntax template put documents, range, and unit in one window block, a combination EnsureValidWindowSpec rejects; it now shows them as the alternatives they are, with both parse errors quoted. sortBy was described as plainly optional — a range window requires a single ascending sort field (so the -1 the table endorsed cannot be used with one), a bounded documents window requires one, and several operators require their own. Added as a table with the error each case raises.

$count dropped. It duplicated accumulators/$count.md, which already documents the stage including the same $unwind example, and the two disagreed on collection size. Removing the new page keeps the stage documented and ends the duplicate title. Filing $count under aggregation/ instead would be a move of the existing page, and belongs in its own change.

$replaceRoot examples made self-consistent. Both ended in { $limit: 2 } while showing a single document. The count was the error, so the limit now matches the output — true by inspection rather than dependent on collection size, which is what made the originals wrong.

Verification

Claims on the rewritten and corrected pages were derived from the engine source rather than from MongoDB's documentation, which is how the original divergences arose — everything wrong in #47 was accurate for MongoDB or Atlas. $currentOp was checked and left alone: its five options are real and its first-stage and admin-database requirements match the handler.

richardsimmondsand others added 4 commits June 3, 2026 11:20
Add documentation for aggregation stages that are implemented in
DocumentDB but were missing from the docs:
- $project — field inclusion/exclusion and expression projection
- $setWindowFields — window functions with partitioning
- $graphLookup — recursive graph traversal
- $replaceRoot — promote subdocument to top level
- $unionWith — combine pipeline results (UNION ALL)
- $vectorSearch — approximate nearest neighbor search
- $limit — restrict output document count
- $count — count documents in pipeline
- $currentOp — admin operation metadata
- $search — text search stage
Each doc follows the existing format: YAML frontmatter, syntax block,
parameters table, examples, and key takeaways. Validated against the
C source in bson_aggregation_pipeline.c for accuracy.
Signed-off-by: richardsimmonds <richardsimmonds314@gmail.com>
Rebasing this branch onto main will conflict: $graphLookup, $limit,
$project, and $vectorSearch were all documented in documentdb#59 while this pull
request was open, so those four files are add/add conflicts against
pages that already exist. Removed them here. The remaining six stages
are still missing from the reference and are what this branch adds.
$search needed more than a rebase - it documents the wrong feature. The
page describes full-text search over a text index, with an example
built on a text operator:
$search: { text: { query: "Beverage", path: "name" } }
DocumentDB's $search is a vector search stage. Its operator registry has
exactly two entries, cosmosSearch and knnBeta (deprecated), both vector
operators, and there is no text operator anywhere in the search sources.
The example above does not return no results - it fails outright with
"Unrecognized $search option: text", and the page's stated requirement
of a text index points at the wrong index type entirely.
Rewritten against the stage's actual parsing: the two operators, the
options carried alongside them (index, count, returnStoredSource), and
the operator spec itself (path, vector, k, filter, exact, oversampling,
score), including which of those knnBeta rejects and which require
server-side pre-filtering to be enabled. count is documented as having
no observable effect, since the engine parses it but does not yet emit
the metadata. The page now points at $vectorSearch as the stage to
prefer for new queries, and notes $text as the answer for the full-text
case the original page was reaching for.
The other five pages were checked against the engine and left alone.
$currentOp in particular is accurate: its five options are real, and its
first-stage and admin-database requirements match the handler.
Two review comments that were fixable from the source.
$setWindowFields showed a syntax template with no valid instantiation:
documents, range, and unit all appear inside one window block, and that
combination is rejected. EnsureValidWindowSpec accepts either documents
alone, or range with an optional unit, and nothing else - documents and
range together throw "Window bounds may only define either 'documents'
or 'unit', but never both", and a window carrying neither throws a
message naming the two valid shapes. The template now shows the choice,
and both errors are quoted so a reader who hits one can map it back.
The sortBy row said "Optional" without qualification, which is true of
the parser and misleading everywhere else. EnsureSortRequirements
requires exactly one ascending sort field for a range window - so the
-1 the row endorsed cannot be used with one - and requires a sort field
for any bounded document window, omissible only when the window is
unbounded at both ends. Several operators require their own, some
non-compound, and $shift requires one unconditionally. Added a table
covering the three cases with the error each raises.
$count claimed equivalence with $group plus $project. The two agree
whenever a document reaches the stage, and diverge on empty input:
HandleCountCore sets hasAggs without a groupClause, making an ungrouped
aggregate that always produces a row, so $count returns zero where
$group returns nothing. That distinction is the reason to reach for
$count, so it is now stated rather than flattened into an equivalence -
and it no longer contradicts the bullet directly above it.
…nsistent
Closes the last two review threads without needing the stores dataset.
$count duplicated accumulators/$count.md, which already documents the
stage across 392 lines including the same $unwind example, and the two
disagreed on the collection size. Removed the new page rather than
relocating the old one: the stage stays documented, no inbound link
breaks, and the repo stops carrying two pages with the same title. If
the reference should instead file $count under aggregation with the
stages, that is a move of the existing page and belongs in its own
change. Removing it also takes with it the promotionEvents example,
which unwound a field absent from that page's own sample document.
The $replaceRoot examples ended in $limit: 2 while showing a single
document. The count was the error, not the document - both outputs are
one document from the canonical dataset - so the limit now matches what
is shown. Setting it to 1 makes each example true by inspection instead
of depending on how many documents the collection happens to hold, which
is what made the original wrong.
The remaining $limit-bearing examples, all in $setWindowFields, print no
output blocks and so had nothing to contradict.

@guanzhousongmicrosoftguanzhousongmicrosoft left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The six pages fill a real gap, and the claims on the rewritten pages are derived from the engine source rather than from MongoDB's documentation - which is what the original divergences came from. Credit to @richardsimmonds for the original work in #47.

@guanzhousongmicrosoft
guanzhousongmicrosoft merged commit 4644040 into documentdb:mainAug 3, 2026
guanzhousongmicrosoft pushed a commit that referenced this pull request Aug 3, 2026
Seventeen links across six pages point at relative .md paths and every
one of them 404s. On $search the link to $vectorSearch renders as
href="./%24vectorsearch.md", which resolves against the page's own
directory - documentdb.io serves these with a trailing slash - and lands
at /operators/aggregation/$search/%24vectorsearch.md. Wrong depth and a
leaked extension, the two failure modes #57 catalogued, in the same
href.
They were introduced together. $vectorSearch, $project, $limit and
$graphLookup arrived in #59, $search in #64 following the convention it
found on the page next to it, and $meta links back to $vectorSearch the
same way. None of them render, so the pages read as cross-linked while
every cross-link is dead.
Rewritten to the absolute form the rest of the reference already uses -
https://documentdb.io/docs/reference/operators/aggregation/%24bucket/ -
which is what #57 settled on for exactly this reason: it does not depend
on how the site resolves a relative path, and it survives a page moving
between directories.
All thirteen distinct targets were requested against the live site and
return 200, and no relative .md link remains anywhere in the repository.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@GuanzhouSong@guanzhousongmicrosoft@richardsimmonds