22

node.js の mongoose スキーマを、express-validator (node-validator santiziations とバリデーターを備えています) と共に使用しています。

商品の価格を保存する良い方法は何ですか?

私は現在持っています

var ItemSchema = new Schema({
    name            : { type: String, required: true, trim: true }
    , price             : Number
});

価格はオプションなので、次のものがあります。

  if ( req.body.price ) {
    req.sanitize('price').toFloat();
    req.assert('price', 'Enter a price (number only)').isFloat();
  }

express-validator は、isNumeric (0 パディングを許可)、isDecimal、および isInt を提供します...10 進数に変換してすべての文字を削除したいので、常に 42.00 を db に挿入しています。

$42.00、$42、42、42.00 を入力して、42.00 だけを保存できるようにします。どうすればこれを達成できますか? たとえば、「abc」と入力した場合、req.assert を使用してフォームにエラーを返したいとします。

あと、通貨はいずれ問題になると思いますが…

更新、価格をセント単位の整数として保存するように言うこの投稿を見つけたので、4200 https://dba.stackexchange.com/questions/15729/storing-prices-in-sqlite-what-data-type-to-use

item.price を呼び出すときに 4200 を $42.00 に変換し、入力をサニタイズして 4200 に変換する方法が必要です。

4

6 に答える 6

30

これが私がやったことです...

価格をセントとしてデータベースに保存したので、ここで説明されているように、49.99 に対して 4999 です: https://dba.stackexchange.com/questions/15729/storing-prices-in-sqlite-what-data-type-to-use

getPrice はそれを読み取り可能な形式に変換するので、ビューで item.price を変更せずに使用できます。

setPrice はそれをセントに変換します。

モデル:

var ItemSchema = new Schema({
    name            : { type: String, required: true, trim: true }
    , price             : {type: Number, get: getPrice, set: setPrice }
});

function getPrice(num){
    return (num/100).toFixed(2);
}

function setPrice(num){
    return num*100;
}

$ を使用せずに、価格フィールドに数字と小数のみを許可することにしました。したがって、49、49.99、49.00 は入力できますが、49.0 または $49 は入力できません。

正規表現を使用した検証:

if ( req.body.price ) {
    req.assert('price', 'Enter a price (numbers only)').regex(/^\d+(\.\d{2})?$/);
}

使いやすさの問題だと思うので、$ を許可する方法があればいいのにと思います。ユーザーに入力させて、それを取り除いてください。どうすればよいかわかりませんが、たとえば、大量の文字ではなく価格があることを検証します。

于 2012-11-09T09:23:07.707 に答える
14

ヒント:ここで説明する方法は、基本的にchovy's answer の別の実装です。

Mongoose 3 & 4 の回避策:

ゲッターとセッターをスキーマで直接定義するのに問題がある場合は、関数を使用schema.path()してこれを機能させることもできます。

var ItemSchema = new Schema({
  name: String,
  price: Number
});

// Getter
ItemSchema.path('price').get(function(num) {
  return (num / 100).toFixed(2);
});

// Setter
ItemSchema.path('price').set(function(num) {
  return num * 100;
});
于 2016-04-16T18:22:29.073 に答える
3

お金を扱うためのスキーマタイプ「Currency」を mongoose に追加します。一般的な文字 (","、"$" およびアルファベット文字) を自動的に取り除きます。

https://github.com/paulcsmith/mongoose-currency

機能:

文字列を整数として保存し (数字以外を削除して 100 を掛けることにより)、計算実行時の丸め誤差を防ぎます (詳細については、落とし穴を参照してください) 文字列の先頭から記号を削除します (ユーザーが通貨記号を含める場合もあります)ユーザーはコンマを追加するか、値をコピーしてフォームに貼り付けます (例: "1,000.50)文字列または数値. 数値はそのまま保存されます. 値を整数に設定した場合, すでに変換が完了していると仮定します (例: 50000 = $500.00). -> 501) 安全のために整数を渡すだけです。

それがsome1に役立つことを願っています。

于 2016-05-01T22:55:42.197 に答える
1

価格だけでなくバージョンも保存したいので、このトピックについてしばらく調査してきました。どちらも、数値として保存すると切り捨てられる末尾の 0 を持つ可能性があります。私の知る限り、Mongoose/MongoDB は数字の末尾にゼロを付けて保存することはできません。

数値を文字列として保存しない限り。

数を数万単位で格納したり、分割または解析したりするだけでなく、文字列として格納することもできます。つまり、変換せずに変数を使用するだけで、「1.0」または「1.00」を表示する必要があるときに、いつでも印刷することができます。JavaScript は型付けされていないため、数値と比較することができます (左側にあることを確認してください)。たとえば、Var < 10 は、var が文字列であっても正しい評価を返します。ただし、2 つの変数を比較する場合は、両方とも数値であることを確認する必要があります。数値が必要な場合は、文字列に 1 を掛けることができます (var * 1 < var2 * 1)。これにより、JavaScript は確実に var を数値として扱いますが、末尾のゼロは失われます。

一方では、変数を数値として使用するたびに変換を行う必要があることを文字列として保存することを意味します。一方、セント数をドル額として使用するたびに、とにかく数値変換 (var / 100) を行うことになるでしょう。このオプションは、数値としての値を必要とする頻度によって異なります。また、変数がセント単位であることを忘れた場合よりも、変数が文字列であることを忘れた場合の方が、より大きなバグを引き起こす可能性があります。

(ただし、表示と比較にのみ使用されるバージョン番号には最適です。)

于 2013-01-13T02:28:53.443 に答える
0

数値モジュールはそれを実現します : http://numeraljs.com/ https://www.npmjs.com/package/numeral

于 2015-07-13T05:54:11.477 に答える