MongoDB - как насчет десятичного типа значения?
в настоящее время я изучаю и применяю MongoDB для небольшого финансового проекта.
когда я прочитала MongoDB в действии он говорит:
единственная другая проблема, которая обычно возникает с числовыми типами BSON, отсутствие десятичной поддержки. Это означает, что если вы планируете хранение значений валюты в MongoDB, необходимо использовать целочисленный тип и храните ценности в центах.
мои финансовые связанный продукт будет включать некоторые валютные значения, но я немного смущен или обеспокоен приведенным выше заявлением. Вот мои вопросы:
- могу ли я использовать
double
для техcurrency values
в моем проекте? - что произойдет или последствия, если я напрямую использую
double
для них? - если десятичный тип является обязательным для финансового продукта, это плохая идея использовать MongoDB?
- что это значит
you need to use an integer type and keep the values in cents
? Означает ли это, что если Я собираюсь хранить1.34 dollars
, то я должен хранить134 cents
?
спасибо
6 ответов
Если вы хотите точное представление для финансовых целей, то значения Double или floating point непригодны, поскольку дробные части подвержены ошибке округления. Некоторые десятичные значения не могут быть представлены с использованием двоичных плавающих точек и должны быть аппроксимированы.
для менее технического вступления см. проблемы с округлением чисел с плавающей запятой; если вы хотите выродок, то прочитайте Что Каждый Компьютерщик Должен Знать О Арифметика С Плавающей Запятой.
рекомендуется использовать целочисленный тип (хранить значение в центах), чтобы избежать потенциальных ошибок округления. Этот подход описывается как "использование масштабного коэффициента" в документации MongoDB для моделирование денежных данных и общее решение для MongoDB 3.2 и ранее.
MongoDB 3.4 включает в себя новый десятичный тип BSON которое обеспечивает точную точность для манипулировать поля денежных данных.
Если вы не хотите хранить валюту в виде центовых значений, вы можете хранить валюту $1.34 в качестве объекта, подобного этому:
{
major: 1,
minor: 34,
currency: "USD"
}
выполнение любой математики с такими объектами будет непросто и не будет использовать коммерческие правила округления. Но вы все равно не должны делать бизнес-логику в базе данных, особенно когда это "тупая" база данных, такая как MongoDB.
что вы должны делать-это сериализовать/десериализовать эти объекты с/к Money
класса в вашем приложении который реализует основные валютные математические операции с соблюдением правил округления и выдает исключение при попытке выполнить операцию с различными валютными единицами (.34 + 14.95€ = error
- сначала необходимо конвертировать одну валюту в другую, указав обменный курс).
Если вы используете Мангуста, то вы можете использовать функции getter/setter в определении схемы, например
function getDecimalNumber(val) { return (val/1000000); }
function setDecimalNumber(val) { return (val*1000000); }
применимо к объекту схемы, например
balance: { type: Number, default: 0, get: getDecimalNumber, set: setDecimalNumber },
количество нулей для умножения / деления зависит от точности, которую вы хотите.
похоже, MongoDB наконец-то добавил поддержку десятичных знаков, хотя на момент написания статьи это только что законченная разработка, но, надеюсь, она должна быть доступна очень скоро в стабильной версии (3.4?).
Я знаю, что этот пост старый, но он занимает высокие позиции в Google, так...
лучшим решением для хранения финансовых данных является использование точной точности, задокументированной самим MongoDB http://docs.mongodb.org/v2.6/tutorial/model-monetary-data/#monetary-value-exact-precision.
{price: 9990, currency: "USD" }
и когда вам нужны данные, просто разделите на 100, предполагая, что вы хотите 2-значную точность. Недостатком является то, что вам всегда нужно работать с одинаковой точностью.
MongoDb добавлена поддержка десятичный тип данных в 3.4 версии. Он также доступен из shell.
3.4 добавлена поддержка формата decimal128 с новым типом данных decimal. Формат decimal128 поддерживает числа до 34 десятичных знаков цифры (т. е. значащие цифры) и диапазон показателей от -6143 до +6144.
В отличие от типа данных double, который хранит только приближение десятичные значения, тип данных decimal хранит точное значение. Для например, десятичное число ("9.99") имеет точное значение 9.99 где в качестве двойного 9.99 будет иметь приблизительное значение 9.9900000000000002131628...