1001Ferramentas
๐ŸƒValidators

MongoDB ObjectId Validator

Validate that a string is a valid MongoDB ObjectId: 24 hex chars. Shows embedded timestamp (first 4 bytes).

โ€”

MongoID in Mongoose: validating the _id field beyond plain ObjectId

MongoID is the informal name often used for the _id identifier in Mongoose, the most popular ODM (Object Data Modeling) library for MongoDB on Node.js. Created by Valeri Karpov at LearnBoost in 2010, Mongoose adds schemas, validation, hooks, virtuals and population on top of the native MongoDB driver โ€” and the way it handles document identifiers is one of its most distinctive features.

By default, every Mongoose document gets an auto-generated _id field of type ObjectId: a 12-byte BSON value rendered as a 24-character hexadecimal string like 507f1f77bcf86cd799439011. Mongoose injects this field implicitly unless you opt out with _id: false in the schema options.

Defining and customizing _id in a Mongoose schema

Although ObjectId is the default, Mongoose lets you swap _id for any other type โ€” UUIDs, integers, slug strings or composite keys are all valid choices when business logic requires them.

const userSchema = new Schema({
  _id: { type: Schema.Types.ObjectId, default: () => new mongoose.Types.ObjectId() },
  email: String
});

// Custom string _id (e.g. slug):
const articleSchema = new Schema({ _id: String, title: String });

Use ref: 'User' on a referenced field to declare a relationship, then .populate('user') at query time to resolve the foreign _id into the full referenced document โ€” the canonical Mongoose pattern for cross-collection joins.

Validating a MongoID: ObjectId.isValid() and its pitfalls

The official check is mongoose.Types.ObjectId.isValid(str), which returns true when the input could be coerced into an ObjectId. Watch out for the classic gotcha: isValid() also returns true for any 12-character string (because 12 bytes is also a legal ObjectId binary length). Production code that only accepts the 24-hex format should add an explicit regex check:

function isValidMongoId(s) {
  return typeof s === 'string'
      && /^[a-fA-F0-9]{24}$/.test(s)
      && mongoose.Types.ObjectId.isValid(s);
}

Client-side generation, security and UUID v7 parallels

ObjectIds can be generated either on the client (the MongoDB driver does this by default before inserts) or on the server. Client-side generation is fine for non-security-critical IDs because the timestamp prefix and counter are not secrets โ€” but never expose ObjectIds in public URLs for resources where guessability matters, since the timestamp segment leaks creation order and approximate time.

The pattern (timestamp prefix + entropy + counter) is conceptually close to UUID v7, standardized in RFC 9562 (2024): both produce roughly time-sortable identifiers with random tail bits. If you are starting a new project today and want chronological ordering across heterogeneous data stores, UUID v7 is the cross-ecosystem standard; ObjectId remains the path of least resistance inside the MongoDB world.

Mongoose vs the raw MongoDB Node.js driver

  • Mongoose: higher-level ODM โ€” schemas, validators, middleware, virtuals, populate. Auto-injects _id, casts strings to ObjectId for you.
  • Driver: thin wrapper around the wire protocol. You manage casting and validation yourself with new ObjectId(str).
  • MongoDB Atlas: managed cloud service from MongoDB Inc. โ€” both libraries connect to it the same way.
  • Brazilian Node ecosystem: Mongoose is the dominant choice in the BR stack โ€” most tutorials, courses and production codebases use it.

FAQ

Mongoose vs the MongoDB driver โ€” which one validates the _id?

Both expose ObjectId.isValid(), but Mongoose also performs automatic casting via the schema โ€” if you declare type: ObjectId, strings are coerced and rejected through Mongoose's CastError when malformed. The driver leaves all of that to your application code.

Can the client generate an ObjectId?

Yes โ€” and that's the default in the Node.js driver. new mongoose.Types.ObjectId() on the client produces a valid ID that the server accepts. Avoid it only when ID confidentiality is a security requirement.

Are there quirks in ObjectId.isValid()?

Yes โ€” it returns true for any 12-character string because those map to 12 raw bytes. If your API contract is "24 hex characters", combine the check with a regex like /^[a-fA-F0-9]{24}$/.

Why 24 hexadecimal characters?

An ObjectId is 12 bytes (96 bits). Each byte is represented as 2 hex digits, giving 24 characters total: 4 bytes of timestamp, 5 bytes of random per-process value and 3 bytes of incrementing counter.

Can I use UUID instead of ObjectId in Mongoose?

Yes โ€” declare _id: { type: String, default: () => crypto.randomUUID() } (or use Buffer/UUID v7 libs) on your schema. You lose the built-in sortability of ObjectId but gain a cross-platform identifier.

Related Tools