Definition
New in version 5.0.
Returns the document position (known as the rank) relative to other
documents in the $setWindowFields stage partition.
The $setWindowFields stage sortBy field value determines the document rank. For
more information on how MongoDB compares fields with different types,
see BSON comparison order.
If multiple documents occupy the same rank, $denseRank places
the document with the subsequent value at the next rank without any gaps
(see Behavior).
$denseRank is only available in the
$setWindowFields stage.
$denseRank syntax:
{ $denseRank: { } }
$denseRank does not accept any parameters.
Tip
Behavior
$rankand$denseRankdiffer in how they rank duplicate sortBy field values. For example, with sortBy field values of 7, 9, 9, and 10:$denseRankranks the values as 1, 2, 2, and 3. The duplicate 9 values have a rank of 2, and 10 has a rank of 3. There is no gap in the ranks.$rankranks the values as 1, 2, 2, and 4. The duplicate 9 values have a rank of 2, and 10 has a rank of 4. There is a gap in the ranks for 3.
Documents with a
nullvalue for a sortBy field or documents missing the sortBy field are assigned a rank based on the BSON comparison order. See the example in Rank Partitions Containing Duplicate Values, Nulls, or Missing Data.Starting in MongoDB 8.0,
nulland missing field values in$denseRankand$ranksortBy operations are treated the same when calculating rankings. This change makes the behavior ofdenseRankandrankconsistent with$sort.
See the example in Dense Rank for Duplicate, Null, and Missing Values.
Examples
Dense Rank Partitions by an Integer Field
Create a cakeSales collection that contains cake sales in the states
of California (CA) and Washington (WA):
db.cakeSales.insertMany( [ { _id: 0, type: "chocolate", orderDate: new Date("2020-05-18T14:10:30Z"), state: "CA", price: 13, quantity: 120 }, { _id: 1, type: "chocolate", orderDate: new Date("2021-03-20T11:30:05Z"), state: "WA", price: 14, quantity: 140 }, { _id: 2, type: "vanilla", orderDate: new Date("2021-01-11T06:31:15Z"), state: "CA", price: 12, quantity: 145 }, { _id: 3, type: "vanilla", orderDate: new Date("2020-02-08T13:13:23Z"), state: "WA", price: 13, quantity: 104 }, { _id: 4, type: "strawberry", orderDate: new Date("2019-05-18T16:09:01Z"), state: "CA", price: 41, quantity: 162 }, { _id: 5, type: "strawberry", orderDate: new Date("2019-01-08T06:12:03Z"), state: "WA", price: 43, quantity: 134 } ] )
This example uses $denseRank in the
$setWindowFields stage to output the quantity dense rank
of the cake sales for each state:
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: "$state", sortBy: { quantity: -1 }, output: { denseRankQuantityForState: { $denseRank: {} } } } } ] )
In the example:
partitionBy: "$state"partitions the documents in the collection bystate. There are partitions forCAandWA.sortBy: { quantity: -1 }sorts the documents in each partition byquantityin descending order (-1), so the highestquantityis first.
outputsets thedenseRankOrderDateForStatefield to theorderDatedense rank using$denseRank, as shown in the following results.
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"), "state" : "CA", "price" : 41, "quantity" : 162, "denseRankQuantityForState" : 1 } { "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"), "state" : "CA", "price" : 12, "quantity" : 145, "denseRankQuantityForState" : 2 } { "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"), "state" : "CA", "price" : 13, "quantity" : 120, "denseRankQuantityForState" : 3 } { "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"), "state" : "WA", "price" : 14, "quantity" : 140, "denseRankQuantityForState" : 1 } { "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"), "state" : "WA", "price" : 43, "quantity" : 134, "denseRankQuantityForState" : 2 } { "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"), "state" : "WA", "price" : 13, "quantity" : 104, "denseRankQuantityForState" : 3 }
Dense Rank Partitions by a Date Field
This example shows how to use dates with $denseRank in the
$setWindowFields stage to output the orderDate dense
rank of the cake sales for each state:
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: "$state", sortBy: { orderDate: 1 }, output: { denseRankOrderDateForState: { $denseRank: {} } } } } ] )
In the example:
partitionBy: "$state"partitions the documents in the collection bystate. There are partitions forCAandWA.sortBy: { orderDate: 1 }sorts the documents in each partition byorderDatein ascending order (1), so the earliestorderDateis first.
outputsets thedenseRankOrderDateForStatefield to theorderDaterank using$denseRank, as shown in the following results.
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"), "state" : "CA", "price" : 41, "quantity" : 162, "denseRankOrderDateForState" : 1 } { "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"), "state" : "CA", "price" : 13, "quantity" : 120, "denseRankOrderDateForState" : 2 } { "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"), "state" : "CA", "price" : 12, "quantity" : 145, "denseRankOrderDateForState" : 3 } { "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"), "state" : "WA", "price" : 43, "quantity" : 134, "denseRankOrderDateForState" : 1 } { "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"), "state" : "WA", "price" : 13, "quantity" : 104, "denseRankOrderDateForState" : 2 } { "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"), "state" : "WA", "price" : 14, "quantity" : 140, "denseRankOrderDateForState" : 3 }
Dense Rank for Duplicate, Null, and Missing Values
Create a cakeSalesWithDuplicates collection where:
Cake sales are placed in the state of California (
CA) and Washington (WA).Documents 6 to 8 have the same
quantityandstateas document 5.Document 9 has the same
quantityandstateas document 4.Document 10 has a
nullquantity.Document 11 is missing the
quantity.
db.cakeSalesWithDuplicates.insertMany( [ { _id: 0, type: "chocolate", orderDate: new Date("2020-05-18T14:10:30Z"), state: "CA", price: 13, quantity: 120 }, { _id: 1, type: "chocolate", orderDate: new Date("2021-03-20T11:30:05Z"), state: "WA", price: 14, quantity: 140 }, { _id: 2, type: "vanilla", orderDate: new Date("2021-01-11T06:31:15Z"), state: "CA", price: 12, quantity: 145 }, { _id: 3, type: "vanilla", orderDate: new Date("2020-02-08T13:13:23Z"), state: "WA", price: 13, quantity: 104 }, { _id: 4, type: "strawberry", orderDate: new Date("2019-05-18T16:09:01Z"), state: "CA", price: 41, quantity: 162 }, { _id: 5, type: "strawberry", orderDate: new Date("2019-01-08T06:12:03Z"), state: "WA", price: 43, quantity: 134 }, { _id: 6, type: "strawberry", orderDate: new Date("2020-01-08T06:12:03Z"), state: "WA", price: 41, quantity: 134 }, { _id: 7, type: "strawberry", orderDate: new Date("2020-01-01T06:12:03Z"), state: "WA", price: 34, quantity: 134 }, { _id: 8, type: "strawberry", orderDate: new Date("2020-01-02T06:12:03Z"), state: "WA", price: 40, quantity: 134 }, { _id: 9, type: "strawberry", orderDate: new Date("2020-05-11T16:09:01Z"), state: "CA", price: 39, quantity: 162 }, { _id: 10, type: "strawberry", orderDate: new Date("2020-05-11T16:09:01Z"), state: "CA", price: 39, quantity: null }, { _id: 11, type: "strawberry", orderDate: new Date("2020-05-11T16:09:01Z"), state: "CA", price: 39 } ] )
This example uses $denseRank in the
$setWindowFields stage to output the quantity dense rank
from the cakeSalesWithDuplicates collection for each state:
db.cakeSalesWithDuplicates.aggregate( [ { $setWindowFields: { partitionBy: "$state", sortBy: { quantity: -1 }, output: { denseRankQuantityForState: { $denseRank: {} } } } } ] )
In the example:
partitionBy: "$state"partitions the documents in the collection bystate. There are partitions forCAandWA.sortBy: { quantity: -1 }sorts the documents in each partition byquantityin descending order (-1), so the highestquantityis first.
outputsets thedenseRankQuantityForStatefield to thequantitydense rank using$denseRank.
In the following example output:
The documents with the same
quantityandstatehave the same rank and there is no gap between the ranks. This differs from$rankthat has a gap between the ranks (for an example, see Rank Partitions Containing Duplicate Values, Nulls, or Missing Data).The document with the
nullquantityand then the document with the missingquantityare ranked the lowest in the output for theCApartition. This sorting is the result of the BSON comparison order, which sortsnulland missing values after number values in this example.
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"), "state" : "CA", "price" : 41, "quantity" : 162, "denseRankQuantityForState" : 1 } { "_id" : 9, "type" : "strawberry", "orderDate" : ISODate("2020-05-11T16:09:01Z"), "state" : "CA", "price" : 39, "quantity" : 162, "denseRankQuantityForState" : 1 } { "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"), "state" : "CA", "price" : 12, "quantity" : 145, "denseRankQuantityForState" : 2 } { "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"), "state" : "CA", "price" : 13, "quantity" : 120, "denseRankQuantityForState" : 3 } { "_id" : 10, "type" : "strawberry", "orderDate" : ISODate("2020-05-11T16:09:01Z"), "state" : "CA", "price" : 39, "quantity" : null, "denseRankQuantityForState" : 4 } { "_id" : 11, "type" : "strawberry", "orderDate" : ISODate("2020-05-11T16:09:01Z"), "state" : "CA", "price" : 39, "denseRankQuantityForState" : 5 } { "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"), "state" : "WA", "price" : 14, "quantity" : 140, "denseRankQuantityForState" : 1 } { "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"), "state" : "WA", "price" : 43, "quantity" : 134, "denseRankQuantityForState" : 2 } { "_id" : 6, "type" : "strawberry", "orderDate" : ISODate("2020-01-08T06:12:03Z"), "state" : "WA", "price" : 41, "quantity" : 134, "denseRankQuantityForState" : 2 } { "_id" : 7, "type" : "strawberry", "orderDate" : ISODate("2020-01-01T06:12:03Z"), "state" : "WA", "price" : 34, "quantity" : 134, "denseRankQuantityForState" : 2 } { "_id" : 8, "type" : "strawberry", "orderDate" : ISODate("2020-01-02T06:12:03Z"), "state" : "WA", "price" : 40, "quantity" : 134, "denseRankQuantityForState" : 2 } { "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"), "state" : "WA", "price" : 13, "quantity" : 104, "denseRankQuantityForState" : 3 }