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.

Numeric BSON types
Int32: Signed 32-bit integer
Suitable for integers within the signed 32-bit range.
Int64: Signed 64-bit integer
Supports much larger integer values; JavaScript applications must preserve values beyond the safe integer range.
Double: Binary floating-point
Useful for approximate numerical calculations but not ideal for exact decimal currency arithmetic.
Decimal128: Decimal floating-point
Useful for decimal values where decimal precision is important, including many financial applications.
Do not use Double blindly for money

Binary floating-point cannot represent every decimal fraction exactly. Consider Decimal128 or integer minor units with a well-defined currency scale when financial correctness matters.

Store and inspect different numeric types
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" }
 }
 }
]);
💡 The document illustrates Int32, Int64, Double, and Decimal128. $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.
Key Takeaways
  • 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.
Knowledge Check

Which BSON numeric type is generally a strong candidate for storing decimal monetary values?