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
?
Спасибо
Ответы
Ответ 1
Если вы хотите получить точное представление для финансовых целей, то значения удвоения или значения с плавающей запятой неприемлемы, поскольку дробные части подвержены ошибкам округления. Определенные десятичные значения не могут быть представлены с использованием двоичных плавающих точек и должны быть аппроксимированы.
Для менее технического введения см. Проблема с округлением чисел с плавающей запятой; если вы хотите выкрикнуть, тогда прочитайте Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой.
Рекомендация использования целочисленного типа (сохранение значения в центах) заключается в том, чтобы избежать возможных ошибок округления. Этот подход описывается как " Использование коэффициента масштабирования" в документации MongoDB для моделирование денежных данных и является общим обходным моментом для MongoDB 3.2 и ранее.
MongoDB 3.4 включает новый Decimal BSON type, который обеспечивает точную точность для манипулирования полями денежных данных.
Ответ 2
Если вы не хотите хранить валюту в виде центов, вы можете хранить валюту в размере 1,34 доллара США в качестве объекта, подобного этому:
{
major: 1,
minor: 34,
currency: "USD"
}
Выполнение любой математики с такими объектами было бы непросто и не использовало бы правила коммерческого округления. Но в любом случае вы не должны делать какую-либо бизнес-логику в базе данных, особенно если это "тупая" база данных, например MongoDB.
Что вы должны делать, это сериализовать/десериализовать эти объекты из/в класс Money
в вашем приложении, который реализует основные операции математической математики в отношении правил округления и генерирует исключение, когда вы пытаетесь выполнить операцию с другой валютой единицы ($12.34 + 14.95€ = error
- сначала конвертировать одну валюту в другую валюту, предоставляя обменный курс).
Ответ 3
Если вы используете Mongoose, вы можете использовать функции getter/setter в определении схемы, например.
function getDecimalNumber(val) { return (val/1000000); }
function setDecimalNumber(val) { return (val*1000000); }
Применимо к объекту схемы, например
balance: { type: Number, default: 0, get: getDecimalNumber, set: setDecimalNumber },
Количество нулей для умножения/деления зависит от требуемой точности.
Ответ 4
Похоже, что MongoDB наконец-то добавила поддержку десятичных знаков, хотя на момент написания это только что закончилась, но, надеюсь, она должна быть доступна очень скоро в стабильной версии (3.4?).
https://jira.mongodb.org/browse/SERVER-1393
Ответ 5
Я знаю, что этот пост старый, но он высоко оценивает Google, поэтому...
Лучшим решением для хранения финансовых данных является точная точность, как это описано самими MongoDB здесь http://docs.mongodb.org/v2.6/tutorial/model-monetary-data/#monetary-value-exact-precision.
{price: 9990, currency: "USD" }
И когда вам нужны данные, просто разделите их на 100, считая, что вам нужна двузначная точность. Недостатком является то, что вам всегда нужно работать с одинаковой точностью.
Ответ 6
MongoDb добавил поддержку десятичный тип данных в версии 3.4. Он также доступен из shell.
3.4 добавляет поддержку формата decimal128 с новым десятичным типом данных. Формат decimal128 поддерживает номера до 34 десятичных знаков цифры (то есть значащие цифры) и диапазон экспоненциального диапазона от -6143 до +6144.
В отличие от двойного типа данных, в котором сохраняется только аппроксимация десятичные значения, тип десятичных данных сохраняет точное значение. Для Например, десятичный NumberDecimal ( "9.99" ) имеет точное значение 9.99 где в качестве двойного 9.99 будет иметь приблизительное значение 9,9900000000000002131628...