MongoDB $toObjectId

From MongoDB 4.0, you can use the $toObjectId aggregation pipeline operator to convert a string to an ObjectId.

The string must be a hexadecimal string of length 24.

Example

Suppose we have a collection called foo and it contains the following document:

{ "_id" : 1, "bar" : "6008c9a5c8eb4369cf6ad9cc" } 

We can use the $toObjectId operator to convert the bar field to an ObjectId.

db.foo.aggregate(
  [
    {
      $project:
        { 
          _id: 0,
          bar: { $toObjectId: "$bar" }
        }
    }
  ]
).pretty()

Result:

{ "bar" : ObjectId("6008c9a5c8eb4369cf6ad9cc") } 

Now the string has been converted to an ObjectId as specified.

Errors

The above example worked because we provided a hexadecimal string of length 24 to the $toObjectId operator.

Here’s what happens when we provide a value that’s not a hexadecimal string of length 24:

db.foo.aggregate(
  [
    {
      $project:
        { 
          _id: 0,
          bar: { $toObjectId: "$_id" }
        }
    }
  ]
).pretty()

Result:

Error: command failed: {
	"ok" : 0,
	"errmsg" : "Unsupported conversion from double to objectId in $convert with no onError value",
	"code" : 241,
	"codeName" : "ConversionFailure"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:618:17
assert.commandWorked@src/mongo/shell/assert.js:708:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1046:12
@(shell):1:1

This error halts the whole aggregation operation, and provides a nasty looking error.

An alternative approach is to use the $convert operator instead of $toObjectId. The $convert operator allows you to handle errors without affecting the whole aggregation operation.

The $toObjectId operator is the equivalent of using the $convert operator to convert a value to an ObjectId.

Here’s the same example using $convert:

db.foo.aggregate(
  [
    {
      $project:
        { 
          _id: 0,
          result: 
          {
            $convert: { 
              input: "$_id", 
              to: "objectId",
              onError: "An error occurred",
              onNull: "Input was null or empty" 
            }
          }
        }
    }
  ]
)

Result:

{ "result" : "An error occurred" } 

Using $convert allowed us to specify the error message to use when the error occurred, and it didn’t halt the whole aggregation operation.

See MongoDB $convert for more examples.