8

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.

  • You'll need to show more of what's the problem. Where are the quotes coming from? Why would you want to convert it to a number? – WiredPrairie Aug 31 '13 at 02:49

4 Answers4

12

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...

Jesse Fulton
  • 2,188
  • 1
  • 23
  • 28
  • 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. – Old Geezer Aug 23 '18 at 15:09
  • 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. – Fusseldieb Nov 05 '18 at 13:41
7

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.

Emmanuel Mahuni
  • 1,766
  • 16
  • 16
3

try using the virtual id onstead of _id

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

instead of

option(data-id=val._id) #{val.name}
supernova
  • 3,814
  • 3
  • 22
  • 37
1

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}")
Simon
  • 103
  • 7