Numeric BSON Types: Int32, Int64, Double, and Decimal128
MongoDB supports multiple numeric BSON types. Choosing the appropriate type matters for precision, range, arithmetic, validation, and interoperability with application languages.
The main numeric BSON types are:
- Int32: A signed 32-bit integer.
- Int64 (Long): A signed 64-bit integer.
- Double: A 64-bit IEEE 754 floating-point number.
- Decimal128: A decimal floating-point type designed for decimal precision and a wide numeric range.
MongoDB also has BSON-specific numeric representations and shell helpers for creating particular types.
Int32
Int32 is suitable for integers within the signed 32-bit range:
- Minimum: -2,147,483,648
- Maximum: 2,147,483,647
In mongosh, NumberInt() explicitly creates an Int32 value:
{ age: NumberInt(28) }
The standard JavaScript number type does not separately represent Int32 values, so the shell helper is useful when you need to demonstrate or create that BSON type explicitly.
Int64 (Long)
Int64 supports larger signed integers:
- Minimum: -9,223,372,036,854,775,808
- Maximum: 9,223,372,036,854,775,807
In mongosh:
{ totalViews: NumberLong("9000000000") }
The string form avoids accidentally passing an already-imprecise JavaScript number when constructing an integer outside JavaScript's safe integer range.
JavaScript's largest safe integer is 9007199254740991. A JavaScript number cannot represent every integer above that value exactly. If your application must handle large integers, use a driver-supported representation that preserves the intended BSON Int64 value.
Double
Double is a binary floating-point type. It supports a wide range of numeric values, but many decimal fractions cannot be represented exactly in binary floating-point.
For example, calculations involving 0.1 and 0.2 can produce representation effects in floating-point arithmetic.
Double is often appropriate for measurements, scientific values, and approximate numerical computations.
Decimal128
Decimal128 is designed for decimal floating-point values and is often appropriate for monetary calculations that require decimal precision.
In mongosh:
{
price: NumberDecimal("19.99")
}
Construct Decimal128 from a decimal string when exact decimal input matters. Converting an already-rounded binary floating-point value into Decimal128 cannot recover the decimal digits that were lost earlier.
Currency modeling
Two common strategies are:
Strategy A: Decimal128
{
price: NumberDecimal("1999.95"),
currency: "INR"
}
Strategy B: Integer minor units
{
pricePaise: NumberLong("199995"),
currency: "INR"
}
The integer-minor-unit approach can work well when the currency and its scale are clearly defined. Not every currency uses two decimal places, so do not assume that every currency can be represented as cents or paise using a universal factor of 100.
Numeric type conversion
Aggregation provides conversion operators such as $convert, $toInt, $toLong, $toDouble, and $toDecimal. Conversion may fail when a value cannot be represented in the requested type.
For inconsistent historical data, $convert can specify onError and onNull values to control conversion behavior.
Do not assume that converting every field to Double is safe. A conversion can lose precision, overflow the target type, or fail for invalid input.
Signed 32-bit integerSigned 64-bit integerBinary floating-pointDecimal floating-pointBinary floating-point cannot represent every decimal fraction exactly. Consider Decimal128 or integer minor units with a well-defined currency scale when financial correctness matters.
db.numericExamples.insertOne({
age: NumberInt(28),
totalViews: NumberLong("9000000000"),
temperature: 36.6,
price: NumberDecimal("1999.95")
});
// Inspect the stored numeric values.
db.numericExamples.findOne();
// Calculate a converted decimal value in aggregation.
db.numericExamples.aggregate([
{
$project: {
totalViews: 1,
price: 1,
priceAsDouble: { $toDouble: "$price" }
}
}
]);$toDouble converts the decimal price to Double for demonstration, but this conversion may lose decimal precision. Avoid converting monetary values to Double when exact decimal arithmetic is required.- MongoDB supports Int32, Int64, Double, and Decimal128.
- JavaScript numbers cannot represent every integer above the safe integer limit exactly.
- Double is appropriate for many approximate numerical calculations.
- Decimal128 is useful when decimal precision is important.
- Converting numeric types can introduce errors or fail for out-of-range values.
Which BSON numeric type is generally a strong candidate for storing decimal monetary values?