Skip to content

MongoDB Fundamentals

ObjectId and _id

What _id is for, how ObjectId is built, and why you should almost never invent your own.

BeginnerAbout 5 minutes

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"
}
_id is a field like any other — typed as ObjectId

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")
})
The stored type is ObjectId, so the filter must be ObjectId
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c90001"), name: "Rahul", city: "Bangalore", ... }
One match — Rahul
// Matches nothing. The field is not a string.
db.users.find({
  _id: "64a1b2c3d4e5f6a7b8c90001"
})
Wrong: a string does not equal an ObjectId

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)
});
Node.js driver

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?

Think about it first.

Interview question

Does every MongoDB document need an _id?

Think about it first.