Course outline

MongoDB / Basic: document foundations / Lesson 3

BSON types, dates and exact numbers

Preserve types across shell, driver and API boundaries. Distinguish exact decimal money, integer identifiers, UTC dates and missing or explicit null fields.

About 4 min readContent reviewed
On this page

Lesson goals

  • Choose BSON numeric and date representations deliberately.
  • Predict type-aware query and conversion behavior.

JavaScript numbers do not represent every BSON number

MongoDB supports integer, long, double and Decimal128 numeric values. A JavaScript Number has precision limits, so large integer identifiers must not be silently converted through an imprecise number before BSON encoding. Use the driver’s appropriate Long or BigInt support according to its documented options. Decimal128 is useful for exact decimal amounts, but application arithmetic must also preserve decimal semantics. A string such as "12.30" is text, not a decimal price, even though a user interface displays it similarly.

Construct explicit shell values

These mongosh helpers construct an integer quantity, a Decimal128 fee and a BSON date with an explicit UTC suffix. The helpers are not general JavaScript globals outside mongosh. The example’s meaningful expectation is quantity three, decimal 12.30 and the stated instant; Extended JSON or shell display can represent those types differently. Do not compare serialized presentation alone to decide whether a driver round trip preserved the type. Record the intended BSON type at the model boundary and inspect stored data using type-aware tools.

javascript Illustrative mongosh; results are reasoned, not measured.
const values = {
  qty: NumberInt(3),
  fee: NumberDecimal('12.30'),
  acceptedAt: ISODate('2026-10-01T09:00:00.000Z')
};
print(values.fee.toString());
print(values.acceptedAt.toISOString());
Expected output
12.30
2026-10-01T09:00:00.000Z

The fee and instant are derived from explicit literals, not measured server records.

Absent fields are not explicit null values

Documents can omit a field entirely or include it with BSON null. The query { deliveredAt: null } matches both conditions, which surprises learners coming from SQL. Use a suitable $type test for explicit null or $exists to reason about presence. Decide whether missing means an old schema version, incomplete ingestion or the same business absence as null. Different meanings should not be erased automatically by conversion or reporting defaults. A field present with zero or an empty string is another distinct state.

Inspect stored types before casting

This read-only aggregation reports the type of each fee under the training namespace. $type in an aggregation expression can distinguish missing from null and numeric types, making it useful during a migration inventory. The query does not repair inconsistent documents. Exact output depends on the fixture; a mixture of string and decimal is evidence to investigate rather than permission to cast every value blindly. Invalid numeric text needs an explicit error or quarantine policy so a report does not silently lose records.

javascript Illustrative mongosh; results are reasoned, not measured.
db.getSiblingDB('quay_lab').parcels.aggregate([
  { $project: { fee: 1, feeType: { $type: '$fee' } } },
  { $sort: { _id: 1 } },
  { $limit: 20 }
]);

Inspect the feeType labels alongside values. No actual collection or type distribution is asserted.

Match semantics rather than printed appearance

Comparison predicates generally apply type-bracketing rules, with documented numeric equivalences; a numeric query should not be assumed to match numeric-looking strings. Dates stored as strings do not gain BSON date behavior. Use half-open instant intervals for date queries and retain a source time-zone label separately when the business needs it. MongoDB string comparison uses simple binary comparison by default unless a collation applies; collation settings can affect matching, sorting and index eligibility. Check the same policy across collection, query and indexes.

Common errors and fixes

A large identifier changes after a JavaScript round trip

Why it happens
It passed through Number beyond safe integer precision.
How to fix it
Use supported exact integer BSON representation at the boundary.
Prevent it next time
Test values beyond the safe integer range and JSON export behavior.

A null query includes documents with no field

Why it happens
Equality to null also matches missing fields.
How to fix it
Use explicit presence/type logic matching the business distinction.
Prevent it next time
Include missing, null, zero and empty text in fixtures.

A date range misses text-form dates

Why it happens
Stored strings were assumed equivalent to BSON date values.
How to fix it
Inventory types and migrate accepted values through a reviewed conversion.
Prevent it next time
Enforce date types at driver and collection validation boundaries.

Check your understanding

1. Two documents have fee NumberDecimal("9.00") and fee "100.00". Is a numeric fee comparison a reliable report over both?

Show worked solution

No. The second value violates the expected numeric type even though its text looks numeric. Inventory the types, validate conversion rules and preserve rejected records for investigation before migrating. Keep report behavior explicit during the transition. A query that simply excludes the bad type can make totals look plausible while omitting legitimate business events.

2. What is lost when an original local timestamp is stored only as a BSON date?

Show worked solution

The original time-zone label and local-input context are not retained merely by storing the instant. Preserve them separately if future business interpretation requires them. Use explicit offsets when converting source times, then verify the resulting instant. Do not reconstruct a named zone from a displayed UTC value or assume all civil days have the same duration around clock changes.

Key takeaways

  • BSON types are part of the data contract, not presentation decoration.
  • Presence, null and conversion failures need explicit policies.

Official references