Chapter 02 · BSON, Documents, Collections, Flexible Schema, and Data Types

Inspect Documents and Collection Metadata with mongosh and Database Commands

Use mongosh and database commands to audit the server’s actual document types, sizes, collection options, indexes, and validation/storage metadata.

Beginner100–125 minutesmongosh document-contract inspection capstoneMongoDB Community Server 8.3.8 · mongosh 2.10.0 · PyMongo 4.17.0Last reviewed: September 2026

Learning outcomes

The chapter ends with an inspection workflow. AtlasMart receives a bug report: some product prices are decimals, one legacy row is a double, one seller field is missing, and the team is unsure whether the collection validator currently running in production matches the configuration in source control. Rather than guessing from application models, use mongosh and database commands to inspect the documents and collection metadata that the server actually sees.

01

Inspect documents with Extended JSON so BSON-specific values remain visible.

02

Use $type, $bsonSize, and field-existence checks to profile actual document shapes.

03

Inspect collection options/validators with listCollections or collection-info helpers.

04

Use dbStats, collStats, indexes, and validate as evidence while respecting their scope/cost.

05

Build a compact AtlasMart “document contract report” before later CRUD/modeling/index chapters modify the collection.

Chapter 02 reproducible baseline

Mandatory server examples use a disposable loopback-only standalone mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim. Driver examples pin pymongo==4.17.0. The lab is intentionally unauthenticated only because it is short-lived and published to 127.0.0.1; Chapter 01 already demonstrated the authenticated reusable lab. Do not expose this container on an untrusted interface. Atlas is optional and not required.

Generation-time execution note

The build environment does not provide Docker, mongod, or mongosh, and cannot install PyMongo from the network. Product/driver commands were reviewed against current official documentation but were not executed here. Expected-output blocks describe stable evidence shape, not fabricated captured output. Learners should record their actual versions and outputs.

1. Seed a fixture that intentionally contains multiple valid shapes

A useful inspection lab needs variation. The fixture below contains an ObjectId, Decimal128 and legacy double prices, dates, arrays, embedded seller data, explicit null, and a missing field. This is controlled heterogeneity, not random data. Tag every lab document so cleanup cannot accidentally delete unrelated AtlasMart records.

shell · start disposable inspection server
docker rm -f atlasmart-mongo-ch02-l5 2>/dev/null || truedocker run --name atlasmart-mongo-ch02-l5 -p 127.0.0.1:27026:27017 -d mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim
mongosh · deterministic mixed-type fixture
mongosh "mongodb://127.0.0.1:27026/atlasmart?directConnection=true" --quiet --eval 'db.inspect_products.drop();db.createCollection("inspect_products", {validator:{$jsonSchema:{ bsonType:"object", required:["lab","sku","schemaVersion"], properties:{lab:{bsonType:"string"},sku:{bsonType:"string"},schemaVersion:{bsonType:"int"}}}}});db.inspect_products.insertMany([ {lab:"ch02",schemaVersion:Int32(2),sku:"sku-laptop",price:Decimal128("899.00"),createdAt:ISODate("2026-09-02T05:00:00Z"),tags:["usb-c","portable"],seller:{id:"s-7",rating:Decimal128("4.80")}}, {lab:"ch02",schemaVersion:Int32(1),sku:"sku-legacy",price:18.5,createdAt:ISODate("2025-12-01T10:00:00Z"),tags:["legacy"],seller:null}, {lab:"ch02",schemaVersion:Int32(2),sku:"sku-missing-seller",price:Decimal128("35.00"),createdAt:ISODate("2026-08-30T10:00:00Z"),tags:[]}]);print("seeded", db.inspect_products.countDocuments({lab:"ch02"}));' 

2. Display documents without erasing their BSON types

find()/findOne() in mongosh already use BSON-aware display forms, but when copying evidence into logs/tests use Extended JSON deliberately. Canonical EJSON is particularly useful when you need to see whether a numeric value is an Int32, Int64, double, or Decimal128 rather than relying on visual formatting.

mongosh · Canonical Extended JSON evidence
const docs = db.inspect_products.find({lab:"ch02"}).sort({sku:1}).toArray();print(EJSON.stringify(docs, null, 2, {relaxed:false}));

Store this report only in a safe test environment; real production documents may contain personal or secret data. Observability must respect data classification and redaction policies.

3. Profile types, missing fields, and BSON sizes

Aggregation expressions turn an inspection question into reproducible evidence. $type reports the BSON type; when an aggregation expression references a missing field, it reports "missing". $bsonSize reports BSON bytes for a document. Together they expose exactly the drift this chapter has taught.

mongosh · contract/profile query
db.inspect_products.aggregate([ {$match:{lab:"ch02"}}, {$project:{   _id:0, sku:1, schemaVersion:1,   priceType:{$type:"$price"},   sellerType:{$type:"$seller"},   tagType:{$type:"$tags"},   docBytes:{$bsonSize:"$$ROOT"} }}, {$sort:{sku:1}}]).toArray();print("seller explicit/missing together:", db.inspect_products.countDocuments({seller:null}));print("seller explicit null only:", db.inspect_products.countDocuments({seller:{$type:10}}));print("seller missing only:", db.inspect_products.countDocuments({seller:{$exists:false}}));

Expected shape: sku-laptop and sku-missing-seller report price type decimal; sku-legacy reports double. Seller type is object, null, or missing. The exact byte counts differ by generated ObjectIds and field values; compare distributions, not a hard-coded screenshot number.

4. Inspect collection metadata—not just documents

A collection carries state beyond its documents: options such as validators, indexes, UUID/catalog identity, and storage statistics. Use official database commands when you need stable machine-readable evidence. listCollections can show the validator/options the server actually has; getIndexes() shows maintained index definitions; collStats/dbStats report current storage/catalog metrics; validate checks collection/index structural consistency and can be more expensive, especially with full validation, so treat it as an operational command rather than a harmless UI refresh.

mongosh · collection/catalog/storage evidence
const info = db.runCommand({listCollections:1, filter:{name:"inspect_products"}});printjson(info.cursor.firstBatch[0]);printjson(db.inspect_products.getIndexes());printjson(db.runCommand({collStats:"inspect_products", scale:1}));printjson(db.runCommand({dbStats:1, scale:1}));// Disposable lab only: structural validation evidence.printjson(db.runCommand({validate:"inspect_products", full:false}));

Interpret each command narrowly. A successful validate does not prove application semantics are correct; it checks storage/index consistency according to the server's validation logic. collStats does not prove an index is useful. A validator in metadata does not prove every historical document matches it. Evidence is only meaningful when its scope is stated.

5. Build a document-contract report before changing the collection

Before Chapter 03 starts CRUD work, capture a compact baseline: server version/FCV, collection options, indexes, counts by schemaVersion, counts by BSON type for critical fields, missing/null counts, and BSON-size percentiles or at least min/max/sample values. This report creates a before-state for later migrations and performance work.

mongosh · compact Chapter 02 baseline report
// Small deterministic lab report; for huge production collections, sample/aggregate carefully.printjson({  server: db.serverBuildInfo().version,  fcv: db.adminCommand({getParameter:1,featureCompatibilityVersion:1}).featureCompatibilityVersion,  docs: db.inspect_products.countDocuments({lab:"ch02"}),  schemaVersions: db.inspect_products.aggregate([    {$match:{lab:"ch02"}}, {$group:{_id:"$schemaVersion",n:{$sum:1}}}, {$sort:{_id:1}}  ]).toArray(),  priceTypes: db.inspect_products.aggregate([    {$match:{lab:"ch02"}}, {$group:{_id:{$type:"$price"},n:{$sum:1}}}, {$sort:{_id:1}}  ]).toArray()});

The deliberately wrong approach is to run a one-off find(), visually inspect three documents, and declare the schema understood. Sampling can miss rare oversized documents, old schema versions, or type drift. In production, use bounded/scalable aggregation strategies, metrics, backups, and privacy-aware sampling rather than dumping entire collections to logs.

Chapter 03 now builds CRUD operations on this exact mental model: inserts create BSON documents and identities; finds operate on typed fields; projection/sort/limit change response shape and work; deletes must be scoped and verified.

Cleanup

shell · scoped cleanup and container removal
mongosh "mongodb://127.0.0.1:27026/atlasmart?directConnection=true" --quiet --eval 'db.inspect_products.deleteMany({lab:"ch02"})'docker rm -f atlasmart-mongo-ch02-l5

Verification checklist

  • You can export Canonical Extended JSON without silently stringifying BSON-specific values.
  • You can identify type drift with $type.
  • You can distinguish explicit null from missing with type/existence predicates.
  • You can measure BSON bytes and inspect collection options/indexes.
  • You state what each command proves and what it does not prove.

Check your understanding

  1. Why prefer Canonical EJSON for a type-audit report?
  2. What does aggregation $type return for a missing field?
  3. What does $bsonSize measure?
  4. What does listCollections add beyond find()?
  5. Does validate:true prove the schema/business rules are correct?
Review the answers

It exposes BSON type wrappers explicitly, making distinctions such as Decimal128 versus double and Int64 versus other numeric forms visible.

The string "missing", which is useful for separating absent fields from explicit BSON null.

The number of bytes the supplied object uses when encoded as BSON. It is not the size of pretty JSON text or total collection storage including indexes/compression.

It exposes collection metadata/options such as validation configuration and catalog information that are not stored as ordinary user documents.

No. Collection validation checks storage/index structural consistency. Business/schema correctness requires validators, application tests, type/shape analysis, and domain invariants.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.