I am doing MongoDB lookups by converting a string to BSON. Is there a way for me to determine if the string I have is a valid ObjectID for Mongo before doing the conversion?
I found that the mongoose ObjectId validator works to validate valid objectIds but I found a few cases where invalid ids were considered valid. (eg: any 12 characters long string)
var ObjectId = require('mongoose').Types.ObjectId;
ObjectId.isValid('microsoft123'); //true
ObjectId.isValid('timtomtamted'); //true
ObjectId.isValid('551137c2f9e1fac808a5f572'); //true
What has been working for me is casting a string to an objectId and then checking that the original string matches the string value of the objectId.
new ObjectId('timtamtomted'); //616273656e6365576f726b73
new ObjectId('537eed02ed345b2e039652d2') //537eed02ed345b2e039652d2
This work because valid ids do not change when casted to an ObjectId but a string that gets a false valid will change when casted to an objectId.
@ross-u answer is just amazing.
I have chained the methods to do a full validation inline:
documentId = id && isValid(id) && new ObjectId(id) == id ? id : null
Note the double equal sign, which is VERY important as new ObjectId()
does not return a string and strict comparison will return false when compared against a normal string (which I had coming in my logic).
The methods have been destructured from the mongoose
object exposed by the require:
const {
Types: {
ObjectId: { isValid },
ObjectId
}
} = require("mongoose");
If you have the hex string you can use this:
ObjectId.isValid(ObjectId.createFromHexString(hexId));
Here is some code I have written based on @andy-macleod's answer.
It can take either an int or string or ObjectId and returns a valid ObjectId if the passed value is valid or null if it is invalid:
var ObjectId= require('mongoose').Types.ObjectId;
function toObjectId(id) {
var stringId = id.toString().toLowerCase();
if (!ObjectId.isValid(stringId)) {
return null;
}
var result = new ObjectId(stringId);
if (result.toString() != stringId) {
return null;
}
return result;
}