MongoDB $toObjectId Operator

Beginner
⏱️ 9 min read
📚 Updated: Jul 2026
🎯 5 Examples
Type Conversion

What You’ll Learn

The $toObjectId operator converts string values to ObjectId in MongoDB aggregation pipelines. Use it when foreign keys are stored as text but need to match ObjectId _id fields in joins and lookups.

01

ObjectId

String to ObjectId.

02

Syntax

One expression.

03

24-char hex

Valid ID format.

04

$lookup

Join by ObjectId.

05

Use Cases

Imports, joins.

06

vs $convert

Shorthand vs safe.

Definition and Usage

In MongoDB’s aggregation framework, the $toObjectId operator converts an expression to a BSON ObjectId. MongoDB’s default _id type is ObjectId, but imported or API data often stores IDs as strings like "507f1f77bcf86cd799439011". Without conversion, a $lookup or equality match between a string field and an ObjectId _id will fail silently or return no results.

$toObjectId is shorthand for { $convert: { input: <expression>, to: "objectId" } }. It is part of the type-conversion family alongside $toString, $toDate, and $toInt.

💡
Beginner Tip

A valid ObjectId string is exactly 24 hexadecimal characters (0–9, a–f). Shorter IDs, UUIDs, or numeric IDs cannot be converted with $toObjectId.

📝 Syntax

The $toObjectId operator takes one expression:

mongosh
{ $toObjectId: <expression> }

Literal Examples

mongosh
{ $toObjectId: "507f1f77bcf86cd799439011" }
// Result: ObjectId("507f1f77bcf86cd799439011")

{ $toObjectId: "$userId" }
// Convert the userId string field

{ $toObjectId: "$productRef" }
// Convert before a $lookup join

Syntax Rules

  • $toObjectId — returns a BSON ObjectId from a valid hex string.
  • <expression> — a 24-character hex string (field path or literal).
  • null — returns null.
  • Invalid string — causes a conversion error (use $convert with onError for safety).
  • Existing ObjectId — returns the same ObjectId value.
  • Use inside $project, $addFields, $lookup pipelines, or $match.

💡 $toObjectId vs $convert vs $toString

$toObjectId — string → ObjectId (for joins and matching _id fields)
$toString — ObjectId → string (for display or export)
$convert — full form with onError when IDs may be invalid
See the $convert operator tutorial for safe conversion patterns

⚡ Quick Reference

QuestionAnswer
Operator typeAggregation expression operator (type conversion)
Syntax{ $toObjectId: <expression> }
Required format24-character hexadecimal string
Equivalent{ $convert: { input: <expr>, to: "objectId" } }
null inputReturns null
Common stages$project, $addFields, $lookup
Field
{
  $toObjectId: "$userId"
}

Convert a field

Literal
{
  $toObjectId:
    "507f1f77bcf86cd799439011"
}

Fixed ObjectId

$lookup
localField:
  "userIdObj"
foreignField: "_id"

Join after convert

Safe
$convert: {
  input: "$id",
  to: "objectId",
  onError: null
}

Invalid → null

Examples Gallery

Convert string foreign keys, join collections with $lookup, match by ObjectId, and handle invalid IDs safely.

📚 Order References

Start with an orders collection where userId is stored as a string and convert it with $toObjectId.

Sample Input Documents

Suppose you have these collections:

mongosh
// orders collection (userId stored as string)
[
  {
    "_id": 1,
    "product": "Widget",
    "userId": "507f1f77bcf86cd799439011"
  },
  {
    "_id": 2,
    "product": "Gadget",
    "userId": "507f191e810c19729de860ea"
  }
]

// users collection (_id is ObjectId)
[
  {
    "_id": ObjectId("507f1f77bcf86cd799439011"),
    "name": "Alice"
  },
  {
    "_id": ObjectId("507f191e810c19729de860ea"),
    "name": "Bob"
  }
]

Example 1 — Basic String to ObjectId

Convert the userId string to an ObjectId field:

mongosh
db.orders.aggregate([
  {
    $project: {
      product: 1,
      userId: 1,
      userIdObj: { $toObjectId: "$userId" }
    }
  }
])

How It Works

The string userId becomes a proper ObjectId in userIdObj. This typed field can now match ObjectId _id values in other collections.

📈 Joins and Filters

Use converted ObjectIds in $lookup joins and $match filters.

Example 2 — $lookup After Converting to ObjectId

Join orders to users by converting the string foreign key first:

mongosh
db.orders.aggregate([
  {
    $addFields: {
      userIdObj: { $toObjectId: "$userId" }
    }
  },
  {
    $lookup: {
      from: "users",
      localField: "userIdObj",
      foreignField: "_id",
      as: "userInfo"
    }
  },
  {
    $project: {
      product: 1,
      userName: { $arrayElemAt: [ "$userInfo.name", 0 ] }
    }
  }
])

How It Works

$lookup requires matching types on localField and foreignField. Converting the string to ObjectId enables the join to work correctly.

Example 3 — Filter by Converted ObjectId

Find orders for a specific user by converting the search ID:

mongosh
db.orders.aggregate([
  {
    $addFields: {
      userIdObj: { $toObjectId: "$userId" }
    }
  },
  {
    $match: {
      userIdObj: ObjectId("507f1f77bcf86cd799439011")
    }
  },
  {
    $project: { product: 1, userId: 1 }
  }
])

// Returns only Alice's orders

How It Works

Convert the stored string ID, then match against an ObjectId literal. Without conversion, string "507f..." would not equal ObjectId 507f....

Example 4 — Convert an Array of ID Strings

Transform each string in an array to ObjectId with $map:

mongosh
db.posts.aggregate([
  {
    $project: {
      title: 1,
      tagIdsObj: {
        $map: {
          input: "$tagIds",
          as: "tagId",
          in: { $toObjectId: "$$tagId" }
        }
      }
    }
  }
])

// tagIds: ["507f1f77bcf86cd799439011", "507f191e810c19729de860ea"]
// → tagIdsObj: [ObjectId(...), ObjectId(...)]

How It Works

$map applies $toObjectId to each element, useful when a document stores multiple string references to other collections.

Example 5 — ObjectId Contains Creation Time

After conversion, extract the embedded timestamp with $toDate:

mongosh
db.orders.aggregate([
  {
    $project: {
      product: 1,
      userIdObj: { $toObjectId: "$userId" },
      userCreatedAt: {
        $toDate: { $toObjectId: "$userId" }
      }
    }
  }
])

// ObjectId embeds a creation timestamp
// $toDate extracts it as ISODate

How It Works

ObjectIds contain a 4-byte timestamp. After converting a string to ObjectId, you can use $toDate to read when that ID was generated.

Bonus — Safe Conversion with $convert

When some IDs may be invalid, use $convert with onError:

mongosh
db.orders.aggregate([
  {
    $project: {
      product: 1,
      userIdObj: {
        $convert: {
          input: "$userId",
          to: "objectId",
          onError: null,
          onNull: null
        }
      }
    }
  }
])

// "507f1f77bcf86cd799439011" → ObjectId(...)
// "not-a-valid-id"           → null
// null                       → null

How It Works

$toObjectId errors on invalid strings and stops the pipeline. $convert with onError: null lets bad rows continue with a null value.

🚀 Use Cases

  • $lookup joins — convert string foreign keys to match ObjectId _id fields.
  • Data import cleanup — normalize string IDs from CSV/JSON into ObjectId type.
  • Cross-collection matching — compare string references against ObjectId fields in $match.
  • Array of references — convert multiple string IDs with $map for batch lookups.
  • Schema migration — transform legacy string-ID documents in aggregation pipelines.

🧠 How $toObjectId Works

1

MongoDB reads the expression

The input resolves from a field path or a 24-character hex string literal.

Input
2

Hex string is validated and parsed

MongoDB checks that the string is exactly 24 hex characters, then builds a 12-byte ObjectId.

Parse
3

An ObjectId is returned

The result matches ObjectId _id fields for joins, filters, and comparisons.

Output
=

Join-ready ObjectId

Use in $lookup, $match, and cross-collection pipelines.

Conclusion

The $toObjectId operator converts 24-character hex strings to BSON ObjectId values in MongoDB aggregation pipelines. It is essential for $lookup joins and matching when foreign keys are stored as text instead of ObjectId.

For the reverse conversion (ObjectId to string), use $toString. For invalid IDs in messy data, use $convert with onError. Next in the series: $toString.

💡 Best Practices

✅ Do

  • Convert string IDs before $lookup when _id is ObjectId
  • Validate that IDs are 24 hex characters before conversion
  • Use $convert with onError for imported or messy data
  • Store ObjectId type in new collections when referencing other documents
  • Pair with $toDate to extract creation time from ObjectIds

❌ Don’t

  • Expect UUIDs or numeric IDs to convert with $toObjectId
  • Join string fields directly to ObjectId _id without converting
  • Assume invalid strings will silently become null (they error with bare $toObjectId)
  • Forget that null input returns null
  • Confuse $toObjectId (string → ObjectId) with $toString (ObjectId → string)

Key Takeaways

Knowledge Unlocked

Five things to remember about $toObjectId

Use these points when converting strings to ObjectId in MongoDB.

5
Core concepts
📝 02

{ $toObjectId: x }

One argument.

Syntax
🔢 03

24 hex chars

Valid format.

Input
🛠 04

$lookup

Join collections.

Usage
05

onError

Safe convert.

Safety

❓ Frequently Asked Questions

$toObjectId converts a value to a BSON ObjectId inside an aggregation pipeline. It is commonly used when foreign key fields are stored as strings but need to match ObjectId _id values.
The syntax is { $toObjectId: <expression> }. The expression is usually a 24-character hexadecimal string field like "$userId" or a literal ObjectId string.
The input must be a valid 24-character hexadecimal string, such as "507f1f77bcf86cd799439011". Invalid formats cause a conversion error unless you use $convert with onError.
$toObjectId is shorthand for { $convert: { input: <expr>, to: "objectId" } }. Use $convert with onError when some strings may not be valid ObjectIds.
$toObjectId returns null when the input is null. It does not throw an error for null input.

Continue the Operator Series

Move on to $toString for the reverse conversion, or review $convert for flexible type transforms.

Next: $toString →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful