Data Types
Learn all the data types MongoDB supports — with real examples from the school management system.
Data Types
Every piece of data you store in MongoDB has a type. Knowing the available types helps you model your data correctly and avoid common mistakes — like storing a number as a string and then wondering why your math queries are not working.
MongoDB supports all the types you would expect — strings, numbers, booleans, dates — plus some special types unique to MongoDB like ObjectId.
String
A string is text. Any value wrapped in quotes is a string.
db.students.insertOne({
name: "Ali Hassan",
grade: "10th",
city: "Lahore"
})Strings in MongoDB are UTF-8 encoded — which means they support all languages, including Arabic, Urdu, Chinese, and others.
Be careful not to store numbers as strings. If you store age: "16" instead of age: 16, queries like age > 15 will not work correctly. Always store numbers as numbers.
Number
MongoDB has three number types:
Integer (int32) — whole numbers up to about 2 billion.
Long (int64) — whole numbers larger than 2 billion. Use this for things like total milliseconds or very large counts.
Double — decimal numbers. This is the default when you write a number with a decimal point.
In practice, when you write a number in mongosh or a Node.js app, MongoDB stores it as a double by default:
db.students.insertOne({
name: "Sara Ahmed",
age: 15, // stored as double by default
gpa: 3.8, // double
rollNumber: 1021 // stored as double by default
})If you specifically need an integer, you can use:
db.students.insertOne({
name: "Sara Ahmed",
age: Int32(15),
rollNumber: Int32(1021)
})For most applications, the default double works fine and you do not need to think about this.
Boolean
A boolean is either true or false. No quotes — just the raw value.
db.students.insertOne({
name: "Umar Farooq",
age: 17,
grade: "11th",
enrolled: true,
hasPaidFees: false
})Booleans are useful for simple flags — is this student enrolled, is this teacher active, is this course available.
Date
Dates in MongoDB are stored as UTC timestamps — the number of milliseconds since January 1, 1970. When you read them back, they display as a readable date.
Always use the new Date() constructor to store dates:
db.students.insertOne({
name: "Ayesha Khan",
age: 16,
grade: "10th",
enrollmentDate: new Date("2024-09-01"),
dateOfBirth: new Date("2008-03-15")
})You can also use new Date() without arguments to store the current date and time:
db.admissions.insertOne({
studentName: "Ayesha Khan",
admittedAt: new Date() // right now
})Always store dates as Date type — not as strings like "2024-09-01". Storing dates as strings means you cannot sort them correctly or run date range queries on them.
ObjectId
Every document in MongoDB automatically gets an _id field. By default, this is an ObjectId — a special 12-byte unique identifier that MongoDB generates automatically.
{
_id: ObjectId("64a1f2c3e4b0a1b2c3d4e5f6"),
name: "Ali Hassan"
}An ObjectId contains:
- A 4-byte timestamp — the exact second it was created
- A 5-byte random value — unique to the machine and process
- A 3-byte incrementing counter — ensures uniqueness even if two are created at the same second
This means ObjectIds are always unique and they are sortable by creation time — newer documents have larger ObjectIds.
You can also create an ObjectId manually:
const { ObjectId } = require('mongodb');
const id = new ObjectId();Or use one to query a specific document:
const { ObjectId } = require('mongodb');
db.students.findOne({
_id: new ObjectId("64a1f2c3e4b0a1b2c3d4e5f6")
})When querying by _id, always wrap the string in new ObjectId(). If you pass a plain string, MongoDB will not find the document because a string and an ObjectId are different types.
Array
An array stores multiple values in a single field. The values inside can be strings, numbers, objects — anything.
db.students.insertOne({
name: "Ali Hassan",
age: 16,
subjects: ["Math", "Physics", "English"],
examScores: [88, 92, 79, 95]
})Arrays are one of the most powerful features of MongoDB. Instead of creating a separate table for a student's subjects, you just store them directly in the student document.
You can also store arrays of objects:
db.students.insertOne({
name: "Sara Ahmed",
grades: [
{ subject: "Math", score: 92 },
{ subject: "Physics", score: 87 },
{ subject: "English", score: 95 }
]
})Object (Embedded Document)
An object — also called an embedded document — is a nested document inside another document. Use it to group related fields together.
db.students.insertOne({
name: "Umar Farooq",
age: 17,
address: {
street: "12 Garden Road",
city: "Karachi",
country: "Pakistan"
},
guardian: {
name: "Mr. Farooq Senior",
phone: "0300-1234567",
relation: "Father"
}
})Instead of creating a separate addresses table like you would in SQL, the address lives right inside the student document. This makes reading the full student record very fast — one query gets everything.
Null
Null means a field exists but has no value. It is different from a field not existing at all.
db.students.insertOne({
name: "Ayesha Khan",
age: 16,
transferredFrom: null // field exists but has no value
})Use null when you know a field belongs to a document but does not have a value yet — for example, a graduationDate that is null until the student graduates.
All Types at a Glance
Here is a complete student document using all the types we covered:
db.students.insertOne({
// ObjectId — auto-generated
// _id: ObjectId("..."),
// String
name: "Ali Hassan",
grade: "10th",
// Number
age: 16,
gpa: 3.75,
rollNumber: Int32(1021),
// Boolean
enrolled: true,
hasPaidFees: false,
// Date
enrollmentDate: new Date("2024-09-01"),
dateOfBirth: new Date("2008-05-20"),
// Array of strings
subjects: ["Math", "Physics", "English"],
// Array of objects
grades: [
{ subject: "Math", score: 88 },
{ subject: "Physics", score: 92 },
{ subject: "English", score: 79 }
],
// Embedded object
address: {
city: "Lahore",
country: "Pakistan"
},
// Null
graduationDate: null
})This is what a real, well-structured student document looks like. We will keep building on this structure throughout the guide.
Quick Reference
| Type | Example | Use it for |
|---|---|---|
| String | "Ali Hassan" | Names, text, labels |
| Double | 3.75 | Decimal numbers |
| Integer | Int32(16) | Whole numbers when precision matters |
| Boolean | true / false | Flags, yes/no fields |
| Date | new Date("2024-09-01") | Dates and timestamps |
| ObjectId | ObjectId("64a1...") | Unique IDs, references to other documents |
| Array | ["Math", "Physics"] | Multiple values in one field |
| Object | { city: "Lahore" } | Grouped related fields |
| Null | null | Field exists but has no value |
When in doubt about which type to use — ask yourself how you will query this field later. If you will do math on it, use a number. If you will sort by it as a date, use Date. Choosing the right type upfront saves you painful data migrations later.