Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to store high precision decimal values in MongoDB

I have little experience with MongoDB. I am usual working on large scale SQL server DBs.

MongoDB only supports double and there is no decimal. The C# driver serializes decimals as strings.

  • What functionality do I miss if I store decimals as strings in MongoDB?

  • Is there a way to set a default serialization of decimals as double (AllowTruncation) without having to put an Attribute on each property?

  • What do I lose in precision if I used Bson double?

Thanks for your help!

UPDATE

I have an existing application model that uses decimals in C#. I want to use MongoDB as a new DB layer and change as little in the existing app as possible. Thats why I am looking for a way to map decimals in C# to double in MongoDB.
I understand that I loose precision and would have to analyze the side effects of it. My only remaining question is to know if there is a way to set a default serialization of decimals as double.

Thanks again. Great answers and comments so far.

like image 490
PeterFromCologne Avatar asked Nov 17 '13 21:11

PeterFromCologne


People also ask

How does MongoDB store float value?

Double: The double data type is used to store the floating-point values.

What is NumberLong in MongoDB?

NumberLong. The mongo shell treats all numbers as floating-point values by default. The mongo shell provides the NumberLong() wrapper to handle 64-bit integers. The NumberLong() wrapper accepts the long as a string: NumberLong("2090845886852")

What is MongoDB NumberDecimal?

The decimal type is not native to JavaScript, so NumberDecimal values in the shell are special wrappers representing the BSON value stored in MongoDB. If you want to use parseFloat() you can convert a NumberDecimal to JSON in order to access the string value.


2 Answers

As of Mongodb 3.4 and the 2.4 Mongodb C# driver, decimal types are supported.

The properties of your document must have the [BsonRepresentation(BsonType.Decimal128)] attribute found in the MongoDB.Bson.Serialization.Attributes namespace.

this will map to "YourDecimalValue" : NumberDecimal("100.0000") in MongodDB. Robomongo supports the new decimal type from version 1.1 Beta.

like image 194
Darxtar Avatar answered Oct 07 '22 23:10

Darxtar


I will answer your question partially (because I do not know much about C#).

So what will you lose if you will store decimals as strings.

  • your numbers on average would weight more (each double number cost 8 bytes to store which means that every string that has more then 8 chars will weight more). Because of these your indexes (if they will be built on this field would grow)
  • you will not be able to use operators which takes numbers as arguments $inc, $bit, $mod, $min, $max and in 2.6 version $mul. (May be I forgot something)
  • you will not be able to compare numbers (may be '1.65' and '1.23' is comparable as a string, but definitely not numbers with e and minuses somewhere in between). Because of this operations which build on top of comparison like $sort, and all these $gte, $gt, $lte, $lt will not work correctly.

What will you lose in precision if you store decimal as double:

  • based on this, Decimal in C# has 28-29 significant digits, whereas looking at my first link and checking the spec for double precision you see that it has 15-17 significant digits. This is basically what you will lose
  • another really important thing which people sometimes forget when dealing with double floats is illustrated below:

.

db.c.insert({_id : 1, b : 3.44}) 
db.c.update({_id : 1},{$inc : {b : 1}})
db.c.find({b: 4.44})  // WTf, where is my document? There is nothing there

Regarding the 2-nd subquestion:

Is there a way to set a default serialization of decimals as double (AllowTruncation) without having to put an Attribute on each property?

I do not really understood it, so I hope someone would be able to answer it.

like image 22
Salvador Dali Avatar answered Oct 07 '22 23:10

Salvador Dali