Lift store BigDecimal in MongoDB

1.2k views Asked by At

I am developing an ecommerce site in Lift with MongoDB

I need to store some data for product prices

My question is this:

What field type should I use in MongoDB if I want to store data type BigDecimal

In mapper is a field of type: MappedDecimal, but

in net.liftweb.mongodb.record.field no equivalent

How I can to store this information?

Thank you all for your attention and help

1

There are 1 answers

1
Akira Kurogane On

As of MongoDB v2.6 there is no fixed-places decimal type. The data has to be saved in a field of a different type and the application must perform translation everytime.

Potentially the intermediary libs could do this translation instead of your application. I guess net.liftweb.record does not.

If a double type would suffice for the field(s) in question, I recommend changing to that for simplicity. But assuming you are using BigDecimal for good reasons, there are well-known workarounds. These are:

(1) Store it as a string. You can have any arbitrary precision. But sorting or querying for exact value matches will only work if you pad the left side with zeroes to a fixed length every time. Even then positive and negative numbers are two different ranges sorting-wise. The negatives need to be sorted in reverse to have correct numerical sorting. An example of the order MongoDB will naturally return these zero-padded string numbers:

"-0000054321.9876"
"-0000100322"
"0000054321.9876"
"0000100322"

I believe the BigDecimal type has a constructor from a string value, so this might be the easiest to implement in your application's translation function.

(2) Store it as a shifted long (Int64). Sorting works, less disk space is used, no problems with negative v.s. positive. Requires shifting the values up by a fixed multiple which makes a bit unreadable when looking at the database directly. The precision has to be fixed to be the same for all the values in the whole collection- OK for financial use cases; not OK for some scientific use cases.

(3) Store as a pair of numbers, one for either side of the decimal point. Sorting requires a extra little work. If using Int32 numbers the precision will be limited to 9 digits either side of the decimal. Looking at two columns in the db instead of one is a little more work of course.

For a Scala code example I found the Reactive driver for MongoDB project has documented three serialization workarounds for BigDecimal. The first uses double; the latter two take yet another approach- create a whole sub-document for BigDecimal value. Trying to query values wrapped in sub-documents would be tricky I suspect.

Another real-life case from an Ebay dev team blog (Morphia/Java)


P.S. maybe MongoDB will add a decimal type in the future. There is a open feature request for it that you can watch/upvote - https://jira.mongodb.org/browse/SERVER-1393