MongoDB Fundamentals
ObjectId and _id
What _id is for, how ObjectId is built, and why you should almost never invent your own.
Every document needs a unique _id inside its collection. If you do not set one on insert, MongoDB generates an ObjectId. That is the default, and it is the right default for almost every collection.
{
_id: ObjectId("64a1b2c3d4e5f6a7b8c90001"),
name: "Rahul",
city: "Bangalore"
}What an ObjectId is
A 12-byte value, usually shown as 24 hex characters. At a high level it carries a timestamp, some randomness, and a counter. You can roughly tell when it was created. You do not need a central ID service. You do not need to remember the byte layout in an interview — timestamp plus uniqueness is enough.
Querying by _id
db.users.find({
_id: ObjectId("64a1b2c3d4e5f6a7b8c90001")
}){ _id: ObjectId("64a1b2c3d4e5f6a7b8c90001"), name: "Rahul", city: "Bangalore", ... }// Matches nothing. The field is not a string.
db.users.find({
_id: "64a1b2c3d4e5f6a7b8c90001"
})In Node.js the driver gives you ObjectId from the mongodb package. Wrap the string from the URL before you query. In the shell, ObjectId("...") does the same.
import { ObjectId } from "mongodb";
await users.findOne({
_id: new ObjectId(req.params.id)
});You can set _id to a string (an email, a slug). Do that only when the value is already unique and stable and you will query it as a string everywhere. Mixing ObjectId documents and string _ids in one collection is how you get 'document not found' bugs.
Interview question
What is the difference between an ObjectId and a string ID?
ObjectId is a 12-byte BSON type, unique by construction, with a timestamp baked in. A string _id is just a string you chose. If the document stores ObjectId, a string filter will not match. I default to ObjectId unless I have a stable natural key.
Interview question
Does every MongoDB document need an _id?
Yes. If you omit it on insert, the server (or the driver) generates an ObjectId. Uniqueness is per collection.