How to insert the value 0 as a double?


#1

This seems like it should be mind-numbingly simple, but I can’t figure it out. I want to basically insert 0 into a document, but as a Double value. The only way I can seem to do this is with a hack:

newId = Collection.insert({value: 0.1});
Collection.update(newId, {$inc: {$value: -0.1}});

I know that in dealing with mongo directly, you can specify types as you insert them, but that doesn’t seem to be possible within Meteor… or is it?


#2

Well, there is decimal: option in simple schema, other than that I dont know :smiley:
Never needed any other way or insert as specific type.
But I think it is JS way of handling numbers - they are all the same.


#3

I specifically need a double, because later the user can set to a value such as 2.8, but since in the database it’s an Int32, it drops the decimal.


#4

Javascript precision works in interesting ways.

Collection.insert({value: 0.0000001})

will practically give you a 0.000000 Double type


#5

Ha… that works too!


#6

you can write it however you want, javascript Number is always 64-bit floating point .
There are no integers, doubles whatever.


#7

Right. This is more of a Meteor/Mongo issue than a JavaScript issue, as Mongo definitely has types.


#8

later the user can set to a value such as 2.8, but since in the database it’s an Int32, it drops the decimal.

this is strange!

I can certainly insert integers and later set them to doubles. are you sure you don’t have another problem elsewhere, perhaps with a schema enforcing package?


#9

how you set them to doubles ?


#10

I do nothing special, mongodb is not a type-restrictive database (unless you define a schema with the new 3.2 version)

so you can do:

var int = Coll.insert({val: 1}) // 1 as Integer
Coll.update(int, {$set: {val: 1.1}}) // 1.1 as Double

#11

I really dont see a difference

0 is double
1 is double
1.1 is double
0x254 is double

All are 64-bit floating point = double - in both javascript and mongodb if you dont force it as NumberLong() or NumberInt() from mongo shell.


#12

Yeah, that’s exactly the point :smile:

Except that, the first one “1” gets to be stored as Int32 by the get go. Makes no difference in how javascript interprets it though within the context of a meteor application.


#13

I still dont understand what would prevent user to set it to whatever he wants.

> Testing1.insert({testNumber: 1})
'eZanNgqt5SFz69A25'
> Testing1.update({testNumber: 1},{$set: {testNumber: 1.1}})
1
> Testing1.findOne()
{ _id: 'eZanNgqt5SFz69A25',
  testNumber: 1.1 }
>

That is from meteor shell.


#14

I am using Astronomy, but I didn’t declare a type for the fields in question, so it shouldn’t be enforcing anything.


#15

For the official MongoDB JS driver:

For minimongo which Meteor uses:

  • I have no idea, somewhat new to Meteor.
  • But minimongo don’t provide constructors for Int, Long, and Double. Maybe they missed it, and we should raise it as an issue?

For your case:

  • I would assume that all numbers go into minimongo as a float/Double. To test it, after inserting, go to the mongo shell, find the document, and then check the field’s value’s type.

#16

Ah there you go I told you you had a schema-enforcing-package problem right in the beginning :slight_smile:

Astronomy does type casting! So you should take this to their github issue tracker and ping @jagi


#17

Weird. I did a test in Astronomy, defining a “number” type field. I was able to initially set it to 0 (it was Int32 in MongoDB), and then change it to 2.8 and it became a Double.

I’ll try again and go look at my code and see what’s up. Maybe I was imagining all of this… :confounded:


#18

Ok, apparently it works fine. I must’ve been doing something wrong before. Everyone move along, nothing to see here! :wink:


#19

Hi. Guys, it’s nothing related with Astronomy, SimpleSchema, MongoDB or Meteor. It’s just how JavaScript works:

JavaScript Numbers are Always 64-bit Floating Point

http://www.w3schools.com/js/js_numbers.asp

Even if you try storing integer it will store float/double. There is always problem of precision, like for example 0.1 + 0.2 === 0.3 is false in JavaScript but not only in JS.

If you store number 0.0 it will definitely be 0.0 in a database, if you store 0 it will also be 0.0. However if that 0.0 number comes from some calculation it can contain non zero fractional part which I don’t know how will be stored in MongoDB.


#20

And one more thing. I would rather not recommend using $inc operator for incrementing by non integer values. It’s even risky in JS alone (and other languages too).

If you need the number 0.0 in the UI you should just format it as a string: (0).toFixed(1);. It will give the "0.0" string.