mongoose objectid to number

14,908

Solution 1

try using the virtual id onstead of _id

option(data-id=val.id) #{val.name}

instead of

option(data-id=val._id) #{val.name}

Solution 2

This is untested, but I think you'd want to do something like this:

var idNum = parseInt(objectId.valueOf(), 16);

MongoDB ObjectIDs are essentially 12 byte hex strings. This makes them larger than the MAX_VALUE for a JavaScript Number (2^53), so you may run into errors with the conversion. But, it looks like Number.MAX_VALUE in my node.js environment (0.11.6) can handle that value. So you might be safe...

Why are you converting an Object ID to a Number though? You really shouldn't be performing arithmetic operations on an ObjectId...

Solution 3

I assume you want the unique id of the object as an integer/number (sometimes just a small easy to use integer for end-users). I had the same use case for ticket numbers. There are times when you want end-users to be able to refer directly to the record id but without those funky chars. So one could really want to convert it to a simple integer eg: 000001 instead of 5220bb43b754af4118000001.

Here I am mostly answering the question's title to help me and others, I hope it answers the question at large.

Actually for the above use case or most you don't need to convert the entire object id:

According to this https://devopslog.wordpress.com/2012/04/22/disassemblingreassembling-mongodb-objectids/

timestamp → Generation timestamp (4 bytes)
machine → First 3 bytes of the MD5 hash of the machine host name, or of the mac/network address, or the virtual machine id.
pid → First 2 bytes of the process (or thread) ID generating the ObjectId.
inc → ever incrementing integer value.

In chars this translates to:

timestamp → 0-7
machine → 8-13
pid → 14-17
inc → 18-23

Which means:

"5220bb43b754af4118000001"

is broken down to:

timestamp → 5220bb43
machine → b754af
pid → 4118
inc → 000001

you may only need the inc part of the id or at least the timestamp and inc.

let objID = "5220bb43b754af4118000001";
let id = objID.substr(18);
console.log(id);
// 000001
// if parsed to int this becomes 1

Hope this helps someone.

Solution 4

Writing in case you have the same problem using something other than mongoose: I've had the same issue using mongoskin.

Somehow Jade freaks out when rendering a mongo _id as an HTML attribute.

For me the solution was this:

// instead of

option(data-id=val._id)

// try

option(data-id="#{val._id}")
Share:
14,908
Admin
Author by

Admin

Updated on June 24, 2022

Comments

  • Admin
    Admin almost 2 years

    How can I cast an ObjectId to a number? In my app I'm using the latest mongoose version and backbone on the clientside.

    My problem is that the ObjectId always ends up being put in between quotes which results in double quotes like ""233453452534"" in my jade templates and on my client.


    edit:

    I'm querying mongodb with

    this.users.find({},function(err,docs){
      cb(null,docs)
    })
    

    console.log(docs) shows

    { name: 'test',
     _id: 5220bc207f0c866f18000001,
     __v: 0 }
    

    in my template

    option(data-id=val._id) #{val.name}
    

    i pass this to res.render

    res.render('test.jade',docs)
    

    and my html renders:

    ""5220bb43b754af4118000001""
    

    with double quotes arround my object id. i tried to set a number in a schema and this works, no quotes arround it if it's a number, so my guess is that that happens because it's an objectID.

  • Old Geezer
    Old Geezer over 5 years
    I couldn't get back the integer that I "cast" into an ObjectId. id = mongoose.Types.ObjectId(123); parseInt(id.valueOf(), 16); doesn't give me back 123.
  • Fusseldieb
    Fusseldieb over 5 years
    This is definitively easier than creating an additional index and messing with "pre" saves and stuff. Though I don't know if it's a good approach to take this and then offset it so you get zero on the first item.