What each MongoDB release added to the aggregation language, from 5.0 on
The answer to "why does $percentile not work" is almost always the server version. Here is what arrived in each release from 5.0 to 8.3.
A pipeline that works on your laptop and fails on staging is usually not a pipeline problem. It is a
version problem, and MongoDB reports it in a way that sends people looking in the wrong place:
Unrecognized expression '$percentile' reads like a typo, not like “your server is two major
versions behind the documentation you were reading”.
The documentation does say which version each operator needs. It says it on the operator’s own page, one page at a time, which is the wrong shape for the question you actually have. The question is almost always “we are pinned to 6.0, what can I use”.
So here is the list the other way round.
5.0
The biggest single release for the aggregation language in years. Window functions arrived, and so did date arithmetic that does not involve doing sums on milliseconds.
Window operators, all of which need $setWindowFields: $expMovingAvg, $rank, $denseRank,
$documentNumber, $shift, $derivative, $integral, $covarianceSamp, $covariancePop.
Date arithmetic: $dateAdd, $dateSubtract, $dateDiff, $dateTrunc. Before these, “group by
week” meant $subtract against epoch milliseconds and hoping about time zones.
Field access by name: $getField, $setField, $unsetField. These are the answer to a field
whose name contains a dot or starts with a dollar, which was awkward to reach before.
Also the $count accumulator, for use inside $group. The $count stage is much older and is
a different thing, which the cheat sheet is careful to separate and which is easy to conflate. And
let as an option on the aggregate command itself, which keeps a parameter out of the pipeline
body so the shape stays cacheable. That is not $lookup’s let, which arrived in 3.6.
5.1, 5.2 and 5.3
Rapid releases, and this is where the version question gets sharp: these are Atlas-only in practice for most people, so a self-hosted cluster on 5.0 does not have them.
- 5.1:
$densify,$tsSecond,$tsIncrement - 5.2:
$top,$topN,$bottom,$bottomN,$firstN,$lastN,$minN,$maxN,$sortArray - 5.3:
$fill,$linearFill
The 5.2 accumulators are worth knowing about, because “the three highest scoring documents per
group” was genuinely awkward before $topN and is one line after it.
6.0
Quieter than its number suggests. $documents is the addition people actually use, and it is mostly
a testing convenience: a pipeline that starts from literal documents rather than a collection.
$shardedDataDistribution arrived in 6.0.3, which is a patch release, so “we are on 6.0” is not
enough to answer whether you have it.
6.3
Bitwise operators: $bitAnd, $bitOr, $bitXor, $bitNot. Late, and useful precisely once, when
somebody stored flags in an integer.
7.0
$median and $percentile, which is the pair most often reached for and most often missing. If you
are on 6.0 and want a percentile, you are computing it in application code or with $sortArray and
arithmetic.
Also $listSampledQueries and the $$USER_ROLES system variable.
8.0 and later
- 8.0:
$querySettings,$toUUID,$toHashedIndexKey - 8.2:
$score,$minMaxScaler,$sigmoid, and the encrypted string predicates$encStrStartsWith,$encStrEndsWith,$encStrContains,$encStrNormalizedEq - 8.3:
$scoreFusion,$toArray,$toObject,$createObjectId,$hash,$hexHash,$similarityCosine,$similarityDotProduct,$similarityEuclidean
The 8.2 and 8.3 additions are mostly about search scoring and vector similarity, which is where the server has been putting its effort.
What this list does not cover
It starts at 5.0 and it lists the releases the reference carries entries for, so the rapid releases
in between with nothing new in the aggregation language do not get a heading. If an operator you are
looking for is not here, that is not the same as it not existing: check the
cheat sheet, which carries a since marker on every entry from 3.2
onward and is where the versions in this piece come from.
The ones that are not a version at all
Four things in the reference are gated on the deployment rather than the release, and this catches people out because the error looks identical:
$searchand$searchMetaneed Atlas. They do not exist on a self-hosted server at any version.$vectorSearchneeds Atlas 6.0.11 or 7.0.2 and later.$queryStatsneeds Atlas M10 or larger.$listSearchIndexesis 7.0, backported to 6.0.7.
That last pattern, a feature backported into a patch release of the previous major, appears more
than once: $changeStreamSplitLargeEvent is 7.0 and 6.0.9, $listClusterCatalog is 8.0.10. So the
honest answer to “do we have it” is db.version(), not the major number somebody remembers.
Checking without guessing
db.version();
Then read the list above. If you want the other direction, an operator and what it needs, the
aggregation cheat sheet carries a since marker on every entry from
3.2 through 8.3, which is where the version data in this piece comes from.
One habit worth having on a team that runs more than one cluster: pin the version you develop against to the oldest version you deploy to. The alternative is finding out at the point where it is most expensive to find out.