Definition
$bottomNNew in version 5.2.
Returns an aggregation of the bottom
nelements within a group, according to the specified sort order. If the group contains fewer thannelements,$bottomNreturns all elements in the group.
Note
Disambiguation
This page describes $bottomN when used as an accumulator. Accumulators return an aggregated value across a group of input documents.
You can also use bottomN in these other contexts:
$bottomN (window function)returns the bottomnelements from documents in a particular window according to the specified sort order.$bottomN (expression operator)returns the bottomnelements from an array of input values according to the specified sort order.
Syntax
{ $bottomN: { n: <expression>, output: <expression>, sortBy: { <field1>: <sort order>, <field2>: <sort order> ... } } }
Options
Field | Necessity | Description |
|---|---|---|
| Required | The number of elements that |
| Required | Determines the output for each element in the group. Can be any expression. |
| Required | Defines the ranking order of elements within each group, with syntax similar to |
Behavior
Null and Missing Values
$bottomNdoes not filter out null values.$bottomNconverts missing values to null which are preserved in the output.
db.aggregate( [ { $documents: [ { playerId: "PlayerA", gameId: "G1", score: 1 }, { playerId: "PlayerB", gameId: "G1", score: 2 }, { playerId: "PlayerC", gameId: "G1", score: 3 }, { playerId: "PlayerD", gameId: "G1"}, { playerId: "PlayerE", gameId: "G1", score: null } ] }, { $group: { _id: "$gameId", playerId: { $bottomN: { output: [ "$playerId", "$score" ], sortBy: { "score": -1 }, n: 3 } } } } ] )
In this example:
$documentscreates the literal documents that contain player scores.$groupgroups the documents bygameId. This example has only onegameId,G1.PlayerDhas a missing score andPlayerEhas a nullscore. These values are both considered as null.The
playerIdandscorefields are specified asoutput : ["$playerId"," $score"]and returned as array values.Because of the
sortBy: { "score" : -1 }, the null values are sorted to the end of the returnedplayerIdarray.
[ { _id: "G1", playerId: [ [ "PlayerA", 1 ], [ "PlayerD", null ], [ "PlayerE", null ] ] } ]
BSON Data Type Sort Ordering
When sorting different types, the order of BSON data types is used to determine ordering. As an example, consider a collection whose values consist of strings and numbers.
In an ascending sort, string values are sorted after numeric values.
In a descending sort, string values are sorted before numeric values.
db.aggregate( [ { $documents: [ { playerId: "PlayerA", gameId: "G1", score: 1 }, { playerId: "PlayerB", gameId: "G1", score: "2" }, { playerId: "PlayerC", gameId: "G1", score: "" } ] }, { $group: { _id: "$gameId", playerId: { $bottomN: { output: ["$playerId","$score"], sortBy: {"score": -1}, n: 3 } } } } ] )
In this example:
PlayerAhas an integer score.PlayerBhas a string"2"score.PlayerChas an empty string score.
Because the sort is in descending { "score" : -1 }, the string literal values are sorted before PlayerA's numeric score:
[ { _id: "G1", playerId: [ [ "PlayerB", "2" ], [ "PlayerC", "" ], [ "PlayerA", 1 ] ] } ]
Examples
The examples on this page use data from the sample_mflix dataset. For details on how to load this dataset into your self-managed MongoDB deployment, see Load the Sample Dataset. If you made any modifications to the sample databases, you may need to drop and recreate the databases to run the examples on this page.
Find the Three Lowest Rated Movies in a Single Genre
You can use the $bottomN accumulator to find the three lowest-rated movies in the Short genre.
db.movies.aggregate( [ { $match: { genres: "Short", "imdb.rating": { $exists: true } } }, { $group: { _id: "Short", lowestRatedMovies: { $bottomN: { output: [ "$title", "$imdb.rating" ], sortBy: { "imdb.rating": -1, title: 1 }, n: 3 } } } } ] )
The example pipeline:
Uses
$matchto restrict the input toShortmovies that include animdb.ratingvalue.Uses
$groupto place the matched movies into a singleShortgroup.Uses
sortBy: { "imdb.rating": -1, title: 1 }to rank movies by rating and usetitleas a tie-breaker.Specifies the fields returned by
$bottomNwithoutput: [ "$title", "$imdb.rating" ].Uses
$bottomNto return the bottom three matching movies withn: 3.
Find the Lowest Rated Movies for Each Genre
You can use the $bottomN accumulator to find the lowest-rated movies for each genre.
db.movies.aggregate( [ { $unwind: "$genres" }, { $match: { "imdb.rating": { $exists: true } } }, { $group: { _id: "$genres", lowestRatedMovie: { $bottomN: { output: [ "$title", "$imdb.rating" ], sortBy: { "imdb.rating": -1, title: 1 }, n: 3 } } } }, { $sort: { _id: 1 } }, { $limit: 5 } ] )
The example pipeline:
Uses
$unwindto expand each movie'sgenresarray.Uses
$matchto keep only documents that include animdb.ratingvalue.Uses
$groupto group the results by genre.Specifies the fields returned by
$bottomNwithoutput: [ "$title", "$imdb.rating" ].Uses
sortBy: { "imdb.rating": -1, title: 1 }to rank movies by rating and usetitleas a deterministic tie-breaker.Uses
$bottomNto return the bottom three movies for each genre withn: 3.
Set n Dynamically Based on the Group Key
You can assign the value of n dynamically. The following example uses the $cond expression to return different numbers of movies based on content rating.
db.movies.aggregate([ { $match: { rated: { $in: [ "G", "PG", "PG-13", "R" ] }, "imdb.rating": { $exists: true } } }, { $group: { _id: { rated: "$rated" }, movies: { $bottomN: { output: { title: "$title", rating: "$imdb.rating" }, n: { $cond: { if: { $eq: [ "$rated", "PG" ] }, then: 3, else: 1 } }, sortBy: { "imdb.rating": -1 } } } } }, { $sort: { "_id.rated": 1 } } ] )
The example pipeline:
Uses
$matchto keep only movies withG,PG,PG-13, orRcontent ratings that include animdb.ratingvalue.Uses
$groupto group the results by content rating with_id: { rated: "$rated" }.Specifies the fields returned by
$bottomNwithoutput: { title: "$title", rating: "$imdb.rating" }.If the content rating is
PGthennis 3. Otherwise,nis 1.Uses
sortBy: { "imdb.rating": -1 }to find the bottomnmovies based on IMDb score.Sorts the results alphabetically by content rating.