If you use MongoDB to handle your database requirements, you need to get to know the ObjectId()
. Every document in your database has one!
And sometimes, you might want to reference the ObjectId()
in another document.
For example, say you have a posts
collection, with all your blog posts in it. And then you have a comments
collection, where each comment will reference which blog post it belongs to.
Or you have a products
collection, and an orders
collection, where each order will reference which products are being purchased.
I can think of a million other examples where you will reference the ObjectId()
of other documents. If you are using MongoDB, I'm sure you have examples in your own database.
So from time to time in your code, you might want to check if the ObjectId()
referenced in one document, matches the ObjectId()
in another.
Maybe you will use the strict equality operator ===
?
But that's where you can run into problems. Because ObjectId("507c7f79bcf86cd7994f6c0e") === ObjectId("507c7f79bcf86cd7994f6c0e")
will always be false
. Even if the ObjectId()
values are the same.
And that's caught me out more times than I care to admit!
Imagine you have a bunch of users in your database:
const { ObjectId } = require('mongodb');
const user1 = {
_id: new ObjectId(),
name: "codemzy",
}
And a team:
const team = {
manager: new ObjectId(user1._id)
}
Each team has one team manager. And you want to check if the user is the team manager, so you write some code like:
isTeamManager = user._id === team.manager;
But even if the user is the team manager, we get... false
. Huh?
console.log(user1._id); // new ObjectId("64b9523b35795e90949872a1")
console.log(team.manager); // new ObjectId("64b9523b35795e90949872a1")
console.log(user1._id === team.manager); // false
It looks right, but we are forgetting a golden rule of JavaScript. Equality doesn't work with objects. Well, it does, but not in the same way as strings or numbers. And our ObjectId()
- that's an object!
console.log(typeof user1._id); // object
console.log(typeof team.manager); // object
And even if when objects theoretically match, they are not equal.
console.log({} === {});
// false
So unless our team.manager
and user_id
reference the exact same ObjectId()
(not just the value, the object), they won't match. And since the ObjectId()
is stored in different documents in a database, goes to and from the client, and moves around our code - that's unlikely. The value might match - but the object does not.
Ok, that’s why equality checks don’t work on ObjectId()
. So what can we use instead?
ObjectId.equals()
My favourite way of comparing ObjectId()
's is by using the .equals()
method.
console.log(team.manager.equals(user1._id)); // true
Yep, if those ObjectId()
values match, .equals
gives us our answer. And .equals
is an inbuilt method on our ObjectId()
objects - so we can use it on any ObjectId()
!
I tend to use this method the most.
ObjectId.toString()
We can’t use equality checks on objects, but we can use equality checks on strings. And you know what else we can do with our ObjectId()
's? Turn them into strings, using the .toString()
method.
So let’s turn our ObjectId()
's into strings, and then compare them to see if they match!
console.log(team.manager.toString() === user1._id.toString()); // true
This works because we are just comparing the value as a string, instead of the object.
What I like about this method is it works even if we have stored one (or both) of the ObjectId()
's as a string.
For example, let's say the user id is sent back from the browser, it's not an ObjectId()
anymore, it's a string. If we try to compare that using the .equals()
method, it's not going to work, because strings don't have an .equals()
method. You will get an error.
.equals is not a function
But running .toString()
on a string works, so if you are unsure if one of the variables might be a string version of the ObjectId()
, then use the toString()
method or convert them both to ObjectId()'s before using
.equals()`.
let managerId = new ObjectId(team.manager);
let userId = new ObjectId(user1._id);
console.log(managerId.equals(userId)); // true
So there we have it. When ===
doesn't work, we have two new ways to compare equality in our ObjectId()
's.
console.log(team.manager === user1._id); // false 😬
console.log(team.manager.equals(user1._id)); // true 🥳
console.log(team.manager.toString() === user1._id.toString()); // true 🥳