Meteor and JavaScript toFixed() saving as a string in MongoDB what's the correct way?


#1

With JavaScript when calling the toFixed() method It returns a string because 0.1, and powers thereof (which are used to display decimal fractions), are not representable (at least not with full accuracy) in binary floating-point systems.

However this creates issues if your calling toFixed in a meteor collection, instead of saving it as a float in mongo it saves it as a string.

If I don’t call toFixed then I get long float numbers which I don’t need and just use more bytes in mongo for no need reason.

What’s the correct approach to trim my float number of X decimal and still save it as a float in mongo?


#2

Use toFixed when you displaying the number. Call it inside a helper. That won’t affect your MongoDB data in any way.


#3

@arunoda yes that is correct but if I don’t do tofixed and would like to save 1.9 I need to wrap it in parseFloat and when I do that I get 1.90000000 which is what I don’t want to save.


#4

Okay. That won’t take additional space your DB. Even though it’s 1.900000 it’s a float. (That’s what float is).

Float only takes a fixed size in DB even if you save 1.9 or 1.9000000


#5

@arunoda Is there an easy way to save it in the DB as a float but still fixed to two decimal points, I’m thinking that is going to be easier and a faster fix


#6

As Arunoda explained, a float is a float.
You want to save a float as a fixed precision while still using a float and you complain that it doesn’t work !?!


#7

@vjau this is mostly a JS issue your able to save a float with decimal points IE 1.9 in the database as a float in other languages. JS converts tofixed as a string so your only choice is to save it as 1.9 in string or 1.90000 as a float. Even if it doent have any size / performance I need now to create a helper function to convert it the exact decimal point.

It’s not complaining I was looking for a way to still have the decimal point so I can avoid the helper function.

To me it makes perfect sense to save an object as is in the database and not have to do any conversion. Meaning if I would like to save 1.9 as a float I should be able to do that.


#8

You could create a custom EJSON binary type of fixed size or a type that you can store as string to de/serialize to/from your custom type.


#9

The answer lies in the first sentence of your question:

You cannot store 0.1 as a float, period.


#10

If you content with always showing X digits, you can do it without a helper by simply writing {{theDoc.theNumber.toFixed X}}.


#11

Leaving aside MongoDB’s internal storage of floating point numbers, which has been answered, it seems to me that what you want is a way of rendering the number appropriately. If all you want to do is avoid doing this in the helper function, you should take a look at Meteor’s transform functionality on the collection. You can use this either to add or replace your floating number as a computed, fixed point property for use on presentation. This will automatically become available to your Blaze views.

In this example I have added the fixed point property someFixedPointNumber to the collection:

MyCollection = new Mongo.Collection("my-collection", {
  transform: function(doc) {
    var someFixedPointNumber = doc.someFloatNumber.toFixed(1); // Adds the fixed point number as a computed property
    return doc; // return the new document
  }
});

The template to make use of this is vanilla Blaze/Spacebars:

<template name="results">
  {{#each myDocument}}
    <div>
      <span>{{someFixedPointNumber}}></span>
    <div>
  {{/each}}
</template>

The template helper is entirely standard:

Template.results.helpers({
  myDocument: function () {
    return MyCollection.find();
  }
});

Documentation: http://docs.meteor.com/#/full/mongo_collection


Using transform in db queries
#12

Annotation: nice interface to use transform is also available by meteor-collection-helpers


#13

Thanks, this saved me a lot of headache. :slight_smile:
Altough it’s common in Europe to write commas in currency (which is my usecase). I guess I’ll have to do this client side and just write me a little helper and some input-js-magic which transforms commas to “dots” and save it that way. Or is there a better way to do that?


#14

You are maybe coming into an internationalization “problem”. The question is for what countries you will provide your app. If these are always countries with number format “1.000,00” you can do it with a simple static helper. If you provide world wide software you have to change the formats. In this case have a look at http://formatjs.io/ for those approaches.

I started a forum discussion about different options here: I18n / Internationalization of your app - choose the right package


#15

Thanks formatjs is awesome. I will definitely check out the discussion you started because right now I don’t know who exactly will use my app, I’ll start some beta testing with friends so that shouldn’t be the problem but anyways I’ll need your solution to provide a solution where the user doesn’t have to care about. :wink: