現在、MongoDBを学習し、小規模な金融関連プロジェクトに適用しています。
MongoDB in Action と読むと、次のように表示されます:
BSON数値型で一般的に発生する他の唯一の問題は、10進数のサポートがないことです。つまり、MongoDBに通貨値を保存する予定がある場合は、整数型を使用して値をセント単位で保持する必要があります。
私の金融関連製品にはいくつかの通貨価値が含まれますが、上記の声明について少し混乱または心配しています。私の質問は次のとおりです。
currency values
にdouble
を使用できますか?double
を直接使用するとどうなりますか、または結果はどうなりますか?you need to use an integer type and keep the values in cents
とはどういう意味ですか? 1.34 dollars
を保存する場合、134 cents
を保存する必要があるということですか?ありがとう
財務目的で正確な表現が必要な場合、小数部分は丸め誤差の影響を受けるため、倍精度値または浮動小数点値は不適切です。特定の10進数値は、バイナリベースの浮動小数点を使用して表現できないため、近似する必要があります。
あまり技術的でないイントロについては、 浮動小数点数の丸めに関する問題 ;をご覧ください。オタクしたい場合は、 すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと を読んでください。
整数型を使用する(値をセント単位で保存する)ことをお勧めします。これは、潜在的な丸めエラーを回避するためです。このアプローチは、MongoDBドキュメントの 通貨データのモデリング で「 スケール係数の使用 」と説明されており、MongoDB 3.2以前の一般的な回避策です。
MongoDB 3.4には、通貨データフィールドを操作するための正確な精度を提供する新しい Decimal BSON type が含まれています。
MongoDBがついに小数のサポートを追加したように見えますが、これを書いている時点では開発は終了しましたが、安定版(3.4?)ですぐに利用できるようになることを願っています。
Mongooseを使用している場合、スキーマ定義でgetter/setter関数を使用できます。
function getDecimalNumber(val) { return (val/1000000); }
function setDecimalNumber(val) { return (val*1000000); }
次のようなスキーマオブジェクトに適用可能
balance: { type: Number, default: 0, get: getDecimalNumber, set: setDecimalNumber },
乗算/除算するゼロの数は、必要な精度によって異なります。
通貨をセント値として保存したくない場合は、次のようなオブジェクトとして$ 1.34の通貨を保存できます。
{
major: 1,
minor: 34,
currency: "USD"
}
このようなオブジェクトを使用して計算を行うことは簡単ではなく、商業的な丸め規則を使用しません。ただし、データベースでビジネスロジックを実行しないでください。特に、MongoDBのような「ダム」データベースの場合はそうではありません。
あなたがしなければならないのは、アプリケーションのMoney
クラスとの間でこれらのオブジェクトをシリアライズ/デシリアライズすることです。単位($12.34 + 14.95€ = error
-為替レートを提供することにより、最初に1つの通貨を他の通貨に変換する必要があります)。
MongoDbは、 .4バージョンの10進データ型 のサポートを追加しました。 Shell からも利用できます。
3.4では、新しいdecimalデータ型でdecimal128形式のサポートが追加されています。 decimal128形式は、最大34桁の10進数(つまり、有効数字)と-6143から+6144の指数範囲を持つ数値をサポートします。
10進値の近似値のみを格納するdoubleデータ型とは異なり、10進データ型は正確な値を格納します。たとえば、10進数のNumberDecimal( "9.99")の正確な値は9.99ですが、倍精度の9.99の概算値は9.9900000000000002131628 ...です。
この投稿は古いことは知っていますが、Googleで上位にランクされているので...
財務データを保存するための最適なソリューションは、ここにMongoDB自身が文書化した正確な精度を使用することです http://docs.mongodb.org/v2.6/tutorial/model-monetary-data/#monetary-value-exact-精度 。
{price: 9990, currency: "USD" }
また、データが必要な場合は、2桁の精度が必要だと仮定して100で除算するだけです。欠点は、常に同じ精度で作業する必要があることです。