A rough mapping:
| PostgreSQL | MongoDB | Important difference |
|---|---|---|
| Table | Collection | Collection does not require every record to have identical fields |
| Row | Document | Document can contain nested objects and arrays |
| Column | Field | Fields may differ between documents |
| Primary key | _id |
Every normal document has one; uniquely indexed by default |
| JSONB | BSON document | MongoDB's entire primary data model is document-oriented |
In PostgreSQL, you normally start by thinking:
What are my entities and relationships? How should I normalize them?
In MongoDB, you more often start with:
What data does the application usually read and modify together?
Imagine an asset-heavy product:
MongoDB stores documents as BSON, not plain JSON. BSON supports nested documents/arrays and database-oriented types such as ObjectId, Date, int64, Decimal128, and binary data.
type Product struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
SKU string `bson:"sku"`
Name string `bson:"name"`
Assets []Asset `bson:"assets"`
}
{
"_id": ObjectId("..."),
"sku": "TSHIRT-001",
"name": "Black T-Shirt",
"assets": [
{
"asset_id": "asset-101",
"position": 1,
"status": "ready",
"variants": {
"thumbnail": {
"width": 200,
"height": 200,
"s3_key": "products/101/thumb.webp"
},
"large": {
"width": 1600,
"height": 1600,
"s3_key": "products/101/large.webp"
}
}
}
]
}
_idEvery document in a normal MongoDB collection has an _id that uniquely identifies it. If you don't provide one, drivers normally generate an ObjectId.
MongoDB has a flexible document schema rather than an absence of schema.
Without discipline, flexibility can actually create bugs:
{ "status": "ready" }
{ "status": 1 }
{ "processing_status": "READY" }
If these things are normally: