Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store money in elasticsearch

I've created an elasticsearch index and my current mapping stores the dollar amount of an item as a string. This is proving to be difficult as I can't search/filter on this value correctly.

GET catalog/product/_search
{
  "filter": {
    "range": {
      "price": {
        "from": 230.0,
        "to": 300.0
      }
    }
  }
}

Where price is mapped as a string. I used a string because going from a python decimal value, I've had issues where this value suddenly gets values at something like 17.989999999999999999998789. This only happens sometimes but I don't wanna get into the issue of going from a python decimal to a java double/float (so I just str() the thing).

Any thoughts on a better approach? Should I bite the bullet and map the price to a double or a float?

like image 343
stincity Avatar asked Jun 10 '15 20:06

stincity


2 Answers

This occurs because ElasticSearch has no built-in type for decimals or currency, so your value is likely being converted to a float and suffering from floating point precision issues.

You should be able to get around this by simply storing the value as a long (e.g. the number of cents rather than dollars) and converting to and from your decimal application-side.

Since you'll only ever do this conversion for values you are already enumerating, the performance impact should be negligible.

like image 184
Ant P Avatar answered Oct 23 '22 05:10

Ant P


In newer version (checked for 5.0), probably the best option is to use scaled_float with scaling_factor = 100 like in their example:

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "number_of_bytes": {
          "type": "integer"
        },
        "time_in_seconds": {
          "type": "float"
        },
        "price": {
          "type": "scaled_float",
          "scaling_factor": 100
        }
      }
    }
  }
}

You can find their doc here.

like image 33
The_Ham Avatar answered Oct 23 '22 05:10

The_Ham