66

How can I check whether an ObjectID is valid using Node's driver

I tried :

var BSON = mongo.BSONPure;
console.log("Validity: "  + BSON.ObjectID.isValid('ddsd'))

But I keep getting an exception instead of a true or false. (The exception is just a 'throw e; // process.nextTick error, or 'error' event on first tick'

Tarang
  • 75,157
  • 39
  • 215
  • 276

9 Answers9

101

This is a simple check - is not 100% foolproof

You can use this Regular Expression if you want to check for a string of 24 hex characters.

var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$")

checkForHexRegExp.test("i am a bad boy")
// false
checkForHexRegExp.test("5e63c3a5e4232e4cd0274ac2")
// true

Regex taken from github.com/mongodb/js-bson/.../objectid.ts


For a better check use:

var ObjectID = require("mongodb").ObjectID

ObjectID.isValid("i am a bad boy")
// false
ObjectID.isValid("5e63c3a5e4232e4cd0274ac2")
// true

isValid code github.com/mongodb/js-bson/.../objectid.ts

Gianfranco P.
  • 10,049
  • 6
  • 51
  • 68
  • The regex above gives false positives in the case of `112345679065574883030833` any idea why? – gmajivu Jan 07 '14 at 09:40
  • 1
    the regex is going to test if there is string that has 0 to 9 or a to F. So this works: `checkForHexRegExp.test("112345679065574883030833"); true` - `checkForHexRegExp.test("000000000000000000000001"); true` - `checkForHexRegExp.test("FFFFFFFFFFFFFFFFFFFFFFFF"); true` – Gianfranco P. Jan 07 '14 at 13:13
  • ok, so there seems to be no sure way of asserting a true ObjectID it seems. same discussion [here](http://stackoverflow.com/a/13851334/645458) – gmajivu Jan 07 '14 at 20:07
  • @gabeno Why are you saying that's a false positive? That's a valid ObjectID. – JohnnyHK Jan 07 '14 at 20:15
  • @JohnnyHK I say so in reference to [this](http://docs.mongodb.org/manual/reference/object-id/). The **false positive** is not a [hex](http://docs.mongodb.org/manual/reference/object-id/#core-object-id-class) string. Please correct me if I am wrong. – gmajivu Jan 08 '14 at 04:41
  • 1
    @gabeno That is a hex string, it just doesn't happen to contain any A-F digits. – JohnnyHK Jan 08 '14 at 04:56
  • @JohnnyHK in my use case, I want to specifically match those hex strings with A-F. Help me out. – gmajivu Jan 08 '14 at 05:21
  • @gabeno Please post a separate question for that containing the details of what you're looking to do. – JohnnyHK Jan 08 '14 at 05:23
  • @JohnnyHK I got answered [here](http://stackoverflow.com/questions/20988446/regex-for-mongodb-objectid) – gmajivu Jan 08 '14 at 07:07
  • 8
    FYI: As of Jan 17, 2014 `Object.isValid()` has been implemented, [commit `821bed15727015ca36a585778e739c9469ae2ec4`](https://github.com/mongodb/js-bson/commit/821bed15727015ca36a585778e739c9469ae2ec4#diff-3c6e907061285ee033834c05c718dd84) I can't seem to find anything in JIRA regarding commit 821bed1, but I'd guess this was included in the mongodb v2.6 release update (node-mongodb-native 1.4). *Edit: @Mandy's answer actually is regarding this* – zamnuts May 01 '14 at 23:47
  • new RegExp("^[0-9a-fA-F]{23}$").test("5e79d319ab5bfb2a9ea4239") results in true . I am using spring boot with mongo db . Mind it its length is 23 – Arka Bandyopadhyay Mar 26 '20 at 10:25
  • @RandyOrton that regex checks for 23 characters. the length of a valid ObjectId is `24`. so it should be `new RegExp("^[0-9a-fA-F]{24}$")` - https://docs.pexip.com/admin/regex_reference.htm#repetition – Gianfranco P. Mar 26 '20 at 22:20
  • for mongodb objectid is 23 – Arka Bandyopadhyay Mar 27 '20 at 07:45
  • @RandyOrton see here (https://docs.mongodb.com/manual/reference/method/ObjectId/) all the ObjectIDs have 24 characters. where do see 23? – Gianfranco P. Mar 28 '20 at 22:48
  • 1
    The right way of validating this is using the isValid function from MongoDB driver. – William Kennedy Oct 23 '20 at 20:49
  • Can I write this somehow in a validation pipeline to be checked in my controller before it reaches any function? – Branchverse Dec 11 '21 at 13:44
58

isValid() is in the js-bson (objectid.ts) library, which is a dependency of node-mongodb-native.

For whoever finds this question, I don't recommend recreating this method as recommend in other answers. Instead, continue using node-mongodb-native like the original poster was using, the following example will access the isValid() method in js-bson.

var mongodb = require("mongodb");
var objectid = mongodb.BSONPure.ObjectID;

console.log(objectid.isValid('53fbf4615c3b9f41c381b6a3'));

July 2018 update: The current way to do this is:

var mongodb = require("mongodb")
console.log(mongodb.ObjectID.isValid(id))
Gianfranco P.
  • 10,049
  • 6
  • 51
  • 68
Eat at Joes
  • 4,937
  • 1
  • 40
  • 40
  • No, it is not. try console.log( ObjectId.isValid( 9 ) ); And see how it return true, while it should return false. – alexserver Aug 17 '15 at 17:23
  • 4
    @alexserver That is a valid id, actually any number will work. If you have to verify the id was a mongo generated hexadecimal string then you can use `(new RegExp("^[0-9a-fA-F]{24}$")).test('53fbf4615c3b9f41c381b6a3')` or look at the accepted answer. – Eat at Joes Aug 21 '15 at 02:45
  • 2
    Anything with 12 characters will pass `m.ObjectID.isValid('#tringI 1234') === true`... – Ray Foss Aug 20 '19 at 13:56
  • It will not work 100% , because it checks for 24 digits length on java platform and what is getting saved is 23 alphanumeric text – Arka Bandyopadhyay Mar 26 '20 at 10:27
  • 1
    @a this should work as it's taken from the mongodb's Node library see https://github.com/mongodb/js-bson/blob/v4.2.0/src/objectid.ts#L301 – Gianfranco P. Oct 24 '20 at 10:17
  • @alexserver it is because Number type is also a valid id, cast your input to string to make sure you test for the alphanumeric format – venimus Mar 30 '22 at 20:31
25

As an extension of Eat at Joes answer... This is valid in node-mongodb-native 2.0

var objectID = require('mongodb').ObjectID

objectID.isValid('54edb381a13ec9142b9bb3537') - false
objectID.isValid('54edb381a13ec9142b9bb353') - true
objectID.isValid('54edb381a13ec9142b9bb35') - false
Sean McClory
  • 4,195
  • 3
  • 32
  • 35
10

If you are using mongoose then you can use mongoose for validation rather than depending on any other library.

if (!mongoose.Types.ObjectId.isValid(req.id)) {
    return res.status(400).send("Invalid object id");
}
Arghya Saha
  • 5,599
  • 4
  • 26
  • 48
  • 2
    "rather than depending on any other library". Mongoose includes `node-mongodb-native` so that statement is wrong. Just so you know, Mongoose simply exposes the isValid function from `node-mongodb-native`... https://github.com/Automattic/mongoose/blob/a057217ba5ef0abd2c030135185f77c04c4d677a/lib/types/objectid.js#L13 – Eat at Joes Mar 01 '20 at 16:11
9

@GianPaJ's snippet is great but it needs to be extended slightly to cover non hex objectID's. Line 32 of the same file indicates objectID's can also be 12 characters in length. These keys are converted to a 24 character hex ObjectID by the mongodb driver.

function isValidObjectID(str) {
  // coerce to string so the function can be generically used to test both strings and native objectIds created by the driver
  str = str + '';
  var len = str.length, valid = false;
  if (len == 12 || len == 24) {
    valid = /^[0-9a-fA-F]+$/.test(str);
  }
  return valid;
}
jksdua
  • 778
  • 9
  • 11
  • 1
    You seem to have misunderstood what a 12-byte ObjectID means. That is the binary (not hex) representation of the id - so most ids in that format will fail your test (any 12 bytes form a valid ObjectID). – Aaron Dufour May 13 '14 at 20:24
1

Below is my model where I am trying to validate subject id that is of type objectId data using JOI (Joi.objectId().required()):

const Joi = require('joi');
const mongoose = require('mongoose');

const Category = mongoose.model('Category', new mongoose.Schema({
  name: String
}));

function validateCategory(category) {
  const schema = {
    name: Joi.string().min(5).max(50).required(),
    subject_id: Joi.objectId().required(),
  };

  return Joi.validate(category, schema);
}

exports.Category = Category;
exports.validate = validateCategory;

It will validate like this if anyone tries to send invalid objectId

joi-objectid validates that the value is an alphanumeric string of 24 characters in length.

MongoDB ObjectId validator for Joi.

Gianfranco P.
  • 10,049
  • 6
  • 51
  • 68
Nishant
  • 301
  • 3
  • 7
0

Follow this regular expression :

in js

new RegExp("^[0-9a-fA-F]{23}$").test("5e79d319ab5bfb2a9ea4239")

in java

Pattern.compile("^[0-9a-fA-F]{23}$").matcher(sanitizeText(value)).matches()

enter image description here

0

Previous answers will work, but I do found that we might need another additional check in order to cater some edge case, exp: any random 12 char string.

  • This is applicable on mongoose / mongodb (I have tested for both node driver)

    // const ObjectId = require('mongoose').Types.ObjectId; if you use mongoose
    const ObjectId = require('mongodb').ObjectId;
    ObjectId.isValid('123456789012'); //true
    ObjectId.isValid('61dd12a0cae2dc1c09c5166f'); //true
    
  • So in order to cater this edge case, one more additional checking will be needed to cast the string to an objectId and check whether it match its original value.

    const ObjectId = require('mongodb').ObjectId;
    const id = "61dd12a0cae2dc1c09c5166f"; // Valid
    // const id = "123456789012"; Invalid
    if(ObjectId.isValid(id) && String(new ObjectId(id)) === searchString){
        // Valid Object ID
    }
    else {
        // Invalid Object ID
    }
    
Henry Teh
  • 151
  • 3
  • 5
-2

You can use Cerberus and create a custom function to validate and ObjectId

from cerberus import Validator
import re

class CustomValidator(Validator): 
    def _validate_type_objectid(self, field, value):
        """ 
        Validation for `objectid` schema attribute.

        :param field: field name.
        :param value: field value.
        """
        if not re.match('[a-f0-9]{24}', str(value)):
            self._error(field, ERROR_BAD_TYPE % 'ObjectId')

## Initiate the class and validate the information
v = CustomValidator()

schema = {
    'value': {'type': 'objectid'}
}
document = {
    'value': ObjectId('5565d8adba02d54a4a78be95')
}

if not v(document, schema):
    print 'Error'
technology_dreamer
  • 473
  • 1
  • 5
  • 13