Uploaded image for project: 'Documentation'
  1. Documentation
  2. DOCS-3393

Modeling Monetary Data in MongoDB



    • Improvement
    • Status: Closed
    • Major - P3
    • Resolution: Fixed
    • None
    • v1.3.7
    • manual
    • 8
    • true


      The following is something I sent to a user, and resembles something
      we discuss relatively often with users/customers.

      If you feel like documenting this, maybe also see this:



      The basic question is how to handle monetary data in MongoDB. There
      are a number of tricky aspects to this problem:

      (A) Many fractional numeric quantities that come up frequently in
      monetary problems have no exact representation in binary floating
      point. For example, one tenth and one third have no exact
      representation in binary floating point.

      (B) Many applications that want to handle monetary data are required
      to conform to some kind of regulatory requirements about how
      arithmetic works on monetary values (e.g., "banker's rounding" and the
      like). Typically, binary floating point arithmetic (such as the stuff
      implemented in modern hardware, and that MongoDB uses) does not
      conform to applicable regulation for monetary arithmetic.

      MongoDB has no built-in support for storing numeric data except as
      IEEE double-precision (64-bit) floating point numbers, and as 32-bit
      and 64-bit signed integers.

      MongoDB has no built-in support for decimal arithmetic, either exact
      or inexact, except for arithmetic on 32-bit and 64-bit integers.

      So how you handle monetary data in MongoDB depends on the
      use case.

      Broadly speaking, there are two options:

      (1) If you know in advance what the maximum precision for monetary
      data is, and you need to be able to do exact, server-side querying,
      sorting, and incrementing/decrementing: convert the monetary value to
      an integer by scaling by a power of 10 large enough that the smallest
      unit of monetary relevance becomes the least significant digit in the
      integral value. (For example, if you care about things down to the
      tenth of a cent, scale by 1000.)

      This approach allows the application to employ all numerical and
      arithmetic features MongoDB provides, so long as the application
      performs appropriate scaling of operands to these features.

      However, note that every part of the application needs to be
      consistent about this (that's also true of arithmetic operations in
      systems that use fractional values, however).

      (2) If you need arbitrary or unanticipated precision in your monetary
      data, store two fields: one that encodes the exact value as a
      non-numeric MongoDB data type (BinData or string, say), along with a
      double-precision floating point approxomation of the exact value for
      server-side range and sort queries.

      This way, an application that needs to retrieve or sort data according
      to the monetary value can, if careful, specify suitable range and sort
      specifications to the MongoDB deployment for accessing documents;
      applications that do this will also need to do client-side
      postprocessing (filtering, say) of documents retrieved based on the
      decoding of the opaque representation of the exact value.

      In general this approach is somewhat more restrictive than the
      previous, because the exact value is stored as an additional object
      for which there won't be any numeric operations available. However, if
      MongoDB is just being used for storage and retrieval, but never update
      or analysis, of monetary data, this approach mostly works.




            tim.slavin Tim Slavin
            tim.slavin Tim Slavin
            Jonathan Dahl Jonathan Dahl
            0 Vote for this issue
            3 Start watching this issue


              8 years, 5 weeks, 5 days ago