MongoDB $round

In MongoDB, the $round aggregation pipeline operator rounds a number to a whole integer or to a specified decimal place.

You have the option of specifying how many decimal places for which to round the number. To do this, pass a second argument. The first argument is the number to round, and the second (optional) argument is the number of decimal places to round it to.

Example

Suppose we have a collection called test with the following documents:

{ "_id" : 1, "data" : 8.99 }
{ "_id" : 2, "data" : 8.45 }
{ "_id" : 3, "data" : 8.451 }
{ "_id" : 4, "data" : -8.99 }
{ "_id" : 5, "data" : -8.45 }
{ "_id" : 6, "data" : -8.451 }
{ "_id" : 7, "data" : 8 }
{ "_id" : 8, "data" : 0 }

We can use the $round operator to round the values in the data field:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data" ] }
          }
     }
   ]
)

Result:

{ "data" : 8.99, "rounded" : 9 }
{ "data" : 8.45, "rounded" : 8 }
{ "data" : 8.451, "rounded" : 8 }
{ "data" : -8.99, "rounded" : -9 }
{ "data" : -8.45, "rounded" : -8 }
{ "data" : -8.451, "rounded" : -8 }
{ "data" : 8, "rounded" : 8 }
{ "data" : 0, "rounded" : 0 }

Specify a Decimal Place

We have the option of using a second argument to specify how many decimal places for which to round the number.

Example:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data", 1 ] }
          }
     }
   ]
)

Result:

{ "data" : 8.99, "rounded" : 9 }
{ "data" : 8.45, "rounded" : 8.4 }
{ "data" : 8.451, "rounded" : 8.5 }
{ "data" : -8.99, "rounded" : -9 }
{ "data" : -8.45, "rounded" : -8.4 }
{ "data" : -8.451, "rounded" : -8.5 }
{ "data" : 8, "rounded" : 8 }
{ "data" : 0, "rounded" : 0 }

Negative Decimal Places

The second argument can be any valid expression that resolves to an integer between -20 and 100, exclusive. Therefore, you can specify a negative decimal place.

When you do this, the number is rounded to the left of the decimal place. If the absolute value of the negative integer is greater than the number, the result is 0.

Suppose we add the following documents to our collection:

{ "_id" : 9, "data" : 8111.32 }
{ "_id" : 10, "data" : 8514.321 }
{ "_id" : 11, "data" : 8999.454 }

Here’s an example of using various negative decimal places when applying $round to those documents:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 9, 10, 11 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            a: { $round: [ "$data", -1 ] },
            b: { $round: [ "$data", -2 ] },
            c: { $round: [ "$data", -3 ] },
            d: { $round: [ "$data", -4 ] },
            e: { $round: [ "$data", -5 ] }
          }
     }
   ]
).pretty()

Result:

{
	"data" : 8111.32,
	"a" : 8110,
	"b" : 8100,
	"c" : 8000,
	"d" : 10000,
	"e" : 0
}
{
	"data" : 8514.321,
	"a" : 8510,
	"b" : 8500,
	"c" : 9000,
	"d" : 10000,
	"e" : 0
}
{
	"data" : 8999.454,
	"a" : 9000,
	"b" : 9000,
	"c" : 9000,
	"d" : 10000,
	"e" : 0
}

Decimal Place of Zero

When you provide a decimal place of 0, the $round operator rounds using the first digit to the right of the decimal and returns the rounded integer value.

Example:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data", 0 ] }
          }
     }
   ]
)

Result:

{ "data" : 8.99, "rounded" : 9 }
{ "data" : 8.45, "rounded" : 8 }
{ "data" : 8.451, "rounded" : 8 }
{ "data" : -8.99, "rounded" : -9 }
{ "data" : -8.45, "rounded" : -8 }
{ "data" : -8.451, "rounded" : -8 }
{ "data" : 8, "rounded" : 8 }
{ "data" : 0, "rounded" : 0 }
{ "data" : 8111.32, "rounded" : 8111 }
{ "data" : 8514.321, "rounded" : 8514 }
{ "data" : 8999.454, "rounded" : 8999 }

Number Types

The number to round can be any valid expression that resolves to an integer, double, decimal, or long. The return value matches the data type of the input value.

So if we add the following documents to our collection:

{ "_id" : 12, "data" : NumberDecimal("128.4585") }
{ "_id" : 13, "data" : NumberDecimal("128.12345678912") }

We can apply $round to the data field:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 12, 13 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            a: { $round: [ "$data", -1 ] },
            b: { $round: [ "$data", 0 ] },
            c: { $round: [ "$data", 3 ] },
            d: { $round: [ "$data", 4 ] },
            e: { $round: [ "$data", 5 ] }
          }
     }
   ]
).pretty()

Result:

{
	"data" : NumberDecimal("128.4585"),
	"a" : NumberDecimal("1.3E+2"),
	"b" : NumberDecimal("128"),
	"c" : NumberDecimal("128.458"),
	"d" : NumberDecimal("128.4585"),
	"e" : NumberDecimal("128.45850")
}
{
	"data" : NumberDecimal("128.12345678912"),
	"a" : NumberDecimal("1.3E+2"),
	"b" : NumberDecimal("128"),
	"c" : NumberDecimal("128.123"),
	"d" : NumberDecimal("128.1235"),
	"e" : NumberDecimal("128.12346")
}

Rounding to Null Decimal Places

If the second argument is null, the result is null.

Example:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 1, 2, 3 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data", null ] }
          }
     }
   ]
)

Result:

{ "data" : 8.99, "rounded" : null }
{ "data" : 8.45, "rounded" : null }
{ "data" : 8.451, "rounded" : null }

Rounding a Null Value

If the value to be rounded is null, the result is null.

Suppose we add the following document to the collection:

{ "_id" : 14, "data" : null }

And we use $round to round the null value:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 14 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data", null ] }
          }
     }
   ]
)

Result:

{ "data" : null, "rounded" : null }

Rounding Infinity

If the number to be rounded is Infinity, the result is Infinity. Likewise, if it’s -Infinity, the result is -Infinity.

Let’s add two documents with such values:

{ "_id" : 15, "data" : Infinity }
{ "_id" : 16, "data" : -Infinity }

And let’s round them:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 15, 16 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data", 2 ] }
          }
     }
   ]
)

Result:

{ "data" : Infinity, "rounded" : Infinity }
{ "data" : -Infinity, "rounded" : -Infinity }

Rounding NaN

Rounding NaN results in NaN.

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 1, 2 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data" * 2 ] }
          }
     }
   ]
)

Result:

{ "data" : 8.99, "rounded" : NaN }
{ "data" : 8.45, "rounded" : NaN }

Non-Numeric Types

If you try to round a value that’s the wrong data type (i.e. it isn’t an integer, double, decimal, or long), an error is returned.

Suppose we add the following document to our collection:

{ "_id" : 17, "data" : "Thirty five" }

And now we try to round the data field:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 17 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data" ] }
          }
     }
   ]
)

Result:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$round only supports numeric types, not string",
	"code" : 51081,
	"codeName" : "Location51081"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:639:17
assert.commandWorked@src/mongo/shell/assert.js:729:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1058:12
@(shell):1:1