web-dev-qa-db-fra.com

MongoDB - Qu'en est-il du type de valeur décimal?

J'apprends et applique actuellement MongoDB pour un petit projet financier.


Quand je lis MongoDB in Action , il dit:

Le seul autre problème qui survient couramment avec les types numériques BSON est le manque de prise en charge décimale. Cela signifie que si vous prévoyez de stocker des valeurs monétaires dans MongoDB, vous devez utiliser un type entier et conserver les valeurs en cents.


Mon produit financier impliquera certaines valeurs monétaires, mais je suis un peu confus ou inquiet au sujet de la déclaration ci-dessus. Voici mes questions:

  1. Puis-je utiliser double pour ceux currency values dans mon projet?
  2. Que se passera-t-il ou quelles seront les conséquences si j'utilise directement double pour eux?
  3. Si le type décimal est un élément indispensable pour un produit financier, est-ce une mauvaise idée d'utiliser MongoDB?
  4. Qu'est-ce que ça veut dire you need to use an integer type and keep the values in cents? Cela signifie-t-il que si je vais stocker 1.34 dollars, alors je devrais stocker 134 cents?

Merci

30
Jackson Tale

Si vous souhaitez une représentation exacte à des fins financières, les valeurs doubles ou à virgule flottante ne conviennent pas car les parties fractionnaires sont sujettes à une erreur d'arrondi. Certaines valeurs décimales ne peuvent pas être représentées à l'aide de virgules flottantes binaires et doivent être approximées.

Pour une introduction moins technique, voir Le problème avec l'arrondi des nombres à virgule flottante ; si vous voulez découvrir, alors lisez Ce que tout informaticien devrait savoir sur l'arithmétique à virgule flottante .

La recommandation d'utiliser un type entier (stockant la valeur en cents) est d'éviter les erreurs d'arrondi potentielles. Cette approche est décrite comme " tilisation d'un facteur d'échelle " dans la documentation MongoDB pour modélisation des données monétaires et constitue une solution de contournement générale pour MongoDB 3.2 et versions antérieures.

MongoDB 3.4 inclut un nouveau type décimal BSON qui fournit une précision exacte pour la manipulation des champs de données monétaires.

32
Stennie

On dirait que MongoDB a finalement ajouté la prise en charge des décimales, bien qu'au moment de la rédaction, ce soit juste un développement terminé, mais j'espère qu'il devrait être disponible très bientôt en version stable (3.4?).

https://jira.mongodb.org/browse/SERVER-139

4
arva

Si vous utilisez Mongoose, vous pouvez utiliser les fonctions getter/setter dans la définition de schéma, par exemple.

function getDecimalNumber(val) {    return (val/1000000); }
function setDecimalNumber(val) {    return (val*1000000); }

Applicable à un objet de schéma tel que

balance: { type: Number, default: 0, get: getDecimalNumber, set: setDecimalNumber },

Le nombre de zéros à multiplier/diviser dépend de la précision souhaitée.

4
HNyang

Lorsque vous ne souhaitez pas stocker de devise sous forme de centimes, vous pouvez stocker une devise de 1,34 $ en tant qu'objet comme celui-ci:

{
    major: 1,
    minor: 34,
    currency: "USD"
}

Faire des calculs avec des objets comme celui-ci ne serait pas facile et n'utiliserait pas de règles d'arrondi commerciales. Mais vous ne devriez pas faire de logique métier sur la base de données de toute façon, surtout pas quand c'est une base de données "idiote" comme MongoDB.

Ce que vous devez faire, c'est sérialiser/désérialiser ces objets de/vers une classe Money dans votre application qui implémente les opérations mathématiques de base de devise en respectant les règles d'arrondi et lève une exception lorsque vous essayez de faire une opération avec une devise différente unités ($12.34 + 14.95€ = error - doit d'abord convertir une devise dans l'autre devise en fournissant un taux de change).

4
Philipp

MongoDb a ajouté la prise en charge de type de données décimal dans la version 3.4 . Il est également disponible sur le Shell .

3.4 ajoute la prise en charge du format decimal128 avec le nouveau type de données décimal. Le format decimal128 prend en charge les nombres avec jusqu'à 34 chiffres décimaux (c'est-à-dire les chiffres significatifs) et une plage d'exposants de −6143 à +6144.

Contrairement au type de données double, qui ne stocke qu'une approximation des valeurs décimales, le type de données décimal stocke la valeur exacte. Par exemple, un nombre décimal NumberDecimal ("9,99") a une valeur précise de 9,99 alors qu'un double 9,99 aurait une valeur approximative de 9,9900000000000002131628 ...

3
Salvador Dali

Je sais que ce message est ancien, mais il se classe bien sur Google, alors ...

La meilleure solution pour stocker des données financières est d'utiliser la précision exacte telle que documentée par MongoDB eux-mêmes ici http://docs.mongodb.org/v2.6/tutorial/model-monetary-data/#monetary-value-exact- précision .

{price: 9990, currency: "USD" }

Et lorsque vous avez besoin des données, divisez simplement par 100 en supposant que vous voulez une précision à 2 chiffres. L'inconvénient est que vous devez toujours travailler avec la même précision.

3
heavenleft