1

I have a price in String format, price can contain decimal and integer both. like

String price ="100.00";
String price ="100";
String price ="100.123";

I want to store this in mongodb, as number(100) or just 100.23(not string). How to handle this in java as parsers are different for Integer and other format.

Rishabh
  • 89
  • 1
  • 4
  • 11

4 Answers4

2

Monetary values should not be stored using floating point numbers like Double. Rounding errors can certainly happen, since these formats are not exact in their representation. The proper type to use for MongoDB is the Decimal128 type, since it stores exact representations of the values, and it has enough precision to support all forms of monetary calculation.

Ken Kopelson
  • 157
  • 1
  • 4
0

You can store the Double BSON type to store the price value. If the price value is 100, it can be stored as 100.00.

The equivalent Java type is java.lang.Double.

BSON to Java data type mapping

The integer value can be converted to double in Java. Some sample code:-

new Double(100);
int i = 100;
new Double(i);
Integer i1 = 100;
new Double(i1);
double d1 = (double) i;

There is a new Decimal128 BSON data type available since 3.4 version.

The Java API can take BigDecimal or long value to construct the Decimal128 object. Please refer the above API documentation.

Refer this blog to understand why Decimal128 is needed?

Floating point arithmetic accuracy problems

notionquest
  • 37,595
  • 6
  • 111
  • 105
0

I think you can try to go for BigDecimal.

You can read here: Java best type to hold price

Java's native floating point types (float and double) suffer from the same precision issues as other programming languages. I think you can make BigDecimal from String, long and double. But as I said you must not go to double. Please can you search a way to preserve without loosing precision inside of the Mongodb and after that convert it to BigDecimal directly. If you can not convert back easy to BigDecimal please use String to store inside Mongodb and after that construct BigDecimal from this String.

Here I found one post and one article about this: Spring Data MongoDB BigDecimal support https://www.moschetti.org/rants/mongomoney.html

Level_Up
  • 789
  • 5
  • 19
  • I never did this but for example you can read about conversion to and from org.bson.types.Decimal128 – Level_Up Sep 04 '18 at 11:35
0

TL;DR

  • STRING if you want to make the arithmetic operations on the client.
  • BSON if you want the arithmetic to happen within the db server and receive it in the response.

In depth (not that much)

It depends on where do you wish to place your numeric operations. You can always save the pricing as a String type on MongoDB, always that you don't need to make server-side arithmetic (Non-Numeric Model) AND the precision on the decimals you need.

If you wish to make arithmetic operations from the query itself, you should use Bson. Leaving you the official mongo related doc below:

Numeric Model

The numeric model may be appropriate if you need to query the database for exact, mathematically valid matches or need to perform server-side arithmetic, e.g., $inc, $mul, and aggregation framework arithmetic.

The following approaches follow the numeric model:

Using the Decimal BSON Type which is a decimal-based floating-point format capable of providing exact precision. Available in MongoDB version 3.4 and later. Using a Scale Factor to convert the monetary value to a 64-bit integer (long BSON type) by multiplying by a power of 10 scale factor.

Non-Numeric Model

If there is no need to perform server-side arithmetic on monetary data or if server-side approximations are sufficient, modeling monetary data using the non-numeric model may be suitable.

The following approach follows the non-numeric model:

Using two fields for the monetary value: One field stores the exact monetary value as a non-numeric string and another field stores a binary-based floating-point (double BSON type) approximation of the value.

EDIT: Source: https://docs.mongodb.com/manual/tutorial/model-monetary-data/

leopinzon
  • 707
  • 6
  • 13