Home > Enterprise >  Comparing array of ObjectIds to ObjectId
Comparing array of ObjectIds to ObjectId

Time:02-11

I have a simple use case that used to work in my code, however now I've had to make changes to accommodate an issue I am now having. Looking to get some insights into why this has changed and requires extra check if anyone can help. My scenario is as described.

I have an array userBadgeIds which holds the following: [ new ObjectId("59f347fca0f50c0004b5a3ac") ]

I used to do the following line: const exists = userBadgeIds.includes(badge._id) which worked perfectly and told me if the input badge._id was in the array. Both are mongoose ObjectId so comparing equivalent in this way seemed perfect (again, it worked!).

However, for whatever reason I now have to compare them in the following way:

      const exists = userBadgeIds.map(String).includes(badge._id.toString())

Now it works again. Is there something I'm missing about how the .includes compares equivalence or something I'm missing about comparing ObjectId specifically around ObjectId[]?

CodePudding user response:

When you compare objects, they have to be the exact same object and not an object that has the same properties.

It's possible that something has changed in your code elsewhere or in a library that turns what was basically this:

const obj1 = { _id: 'a' };
const obj2 = { _id: 'b' };
const obj3 = { _id: 'c' };
const searchFor = obj1;

[obj1, obj2, obj3].includes(searchFor); // true

Into something that is essentially this:

const obj1 = { _id: 'a' };
const obj2 = { _id: 'b' };
const obj3 = { _id: 'c' };
const searchFor = { _id: 'a' };

[obj1, obj2, obj3].includes(searchFor); // false

searchFor might have the same properties and prototype, but it's not the exact same object as obj1. Perhaps some code is cloning badge, making it not equal to the entries in the userBadgeIds array.

Your workaround works, because when you compare strings, they don't have to be the exact same string, just have the same value.


As an aside, there's ObjectId.prototype.equals() to compare two (identical or equivalent) ObjectIds.

// You need to pass searchFor as the second parameter to `some`
// so that `this` is correctly set.
[obj1, obj2, obj3].some(searchFor.equals, searchFor);

// Or you can do:
[obj1, obj2, obj3].some(searchFor.equals.bind(searchFor));

// Or:
[obj1, obj2, obj3].some(id => searchFor.equals(id));

Array.prototype.some returns true if any array entry matches the callback function, like includes does for values.

  • Related