node.js 我应该如何在猫鼬中存储价格?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13304129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how should i store a price in mongoose?
提问by chovy
I'm using mongoose schemas for node.js along with express-validator (which has node-validator santiziations and validators).
我正在将 mongoose 模式用于 node.js 和 express-validator(它具有 node-validator santiziations 和验证器)。
What's a good way to store price for an item?
存储商品价格的好方法是什么?
I currently have
我目前有
var ItemSchema = new Schema({
name : { type: String, required: true, trim: true }
, price : Number
});
Price is optional, so I have:
价格是可选的,所以我有:
if ( req.body.price ) {
req.sanitize('price').toFloat();
req.assert('price', 'Enter a price (number only)').isFloat();
}
express-validator gives me isNumeric (allows 0 padding), isDecimal, and isInt...I'd rather just convert to decimal and strip all characters, so I'm always inserting 42.00 into db.
express-validator 给了我 isNumeric(允许 0 填充)、isDecimal 和 isInt...我宁愿转换为十进制并去除所有字符,所以我总是将 42.00 插入到 db 中。
I want to allow them to enter $42.00, $42, 42, 42.00 and just store 42.00. How can I accomplish this? and still validate that I'm seeing something resembling a number, for example if they enter 'abc' I want to throw an error back to the form using req.assert.
我想让他们输入 $42.00、$42、42、42.00 并只存储 42.00。我怎样才能做到这一点?并且仍然验证我看到的是类似于数字的东西,例如,如果他们输入“abc”,我想使用 req.assert 将错误抛出回表单。
Also, I suppose currency will eventually become an issue...
另外,我想货币最终会成为一个问题......
Update, I found this post which says to store price as integer in cents, so 4200 https://dba.stackexchange.com/questions/15729/storing-prices-in-sqlite-what-data-type-to-use
更新,我发现这篇文章说将价格存储为以美分为单位的整数,所以 4200 https://dba.stackexchange.com/questions/15729/storing-prices-in-sqlite-what-data-type-to-use
I just need a way to convert 4200 to $42.00 when I call item.price and also sanitize and convert the input into 4200.
当我调用 item.price 时,我只需要一种将 4200 转换为 42.00 美元的方法,并将输入清理并转换为 4200。
采纳答案by ofhouse
Hint:The method described here is basically just another implementation of chovy's answer.
提示:这里描述的方法基本上只是chovy's answer 的另一种实现。
Workaround for Mongoose 3 & 4:
猫鼬 3 和 4 的解决方法:
If you have trouble to define getters and setters directly in the schema, you could also use the schema.path()function to make this work:
如果您在模式中直接定义 getter 和 setter 有困难,您也可以使用该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;
});
回答by chovy
This is what I ended up doing...
这就是我最终做的...
I stored price as cents in database, so it is 4999 for 49.99 as described here: https://dba.stackexchange.com/questions/15729/storing-prices-in-sqlite-what-data-type-to-use
我在数据库中将价格存储为美分,因此 49.99 为 4999,如下所述:https: //dba.stackexchange.com/questions/15729/storing-prices-in-sqlite-what-data-type-to-use
the getPrice will convert it back to readable format, so I can use item.price in my views w/o modifying it.
getPrice 会将其转换回可读格式,因此我可以在视图中使用 item.price,而无需修改它。
the setPrice converts it to cents.
setPrice 将其转换为美分。
model:
模型:
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;
}
I opted to only allow digits and decimal in price field, without $. So they can enter 49, 49.99, 49.00, but not 49.0 or $49
我选择在价格字段中只允许数字和小数,没有 $。所以他们可以输入 49、49.99、49.00,但不能输入 49.0 或 49 美元
validation using regex:
使用正则表达式验证:
if ( req.body.price ) {
req.assert('price', 'Enter a price (numbers only)').regex(/^\d+(\.\d{2})?$/);
}
I wish there was a way to allow the $ because I think its a usability issue, just let the user enter it, but strip it off. I'm not sure how to do that and still validate that we have a price and not a bunch of letters for example.
我希望有一种允许 $ 的方法,因为我认为这是一个可用性问题,让用户输入它,但将其去掉。我不确定如何做到这一点,并且仍然验证我们有一个价格而不是一堆字母。
回答by Dionis Olen
Adds schema type "Currency" to mongoose for handling money. Strips out common characters automatically (",", "$" and alphabet chars)
向猫鼬添加模式类型“货币”以处理金钱。自动去除常见字符(",", "$" 和字母字符)
https://github.com/paulcsmith/mongoose-currency
https://github.com/paulcsmith/mongoose-currency
What it does:
它能做什么:
Saves a String as an integer (by stripping non digits and multiplying by 100) to prevent rounding errors when performing calculations (See gotchas for details) Strips out symbols from the beginning of strings (sometimes users include the currency symbol) Strips out commas (sometimes users add in commas or copy paste values into forms, e.g. "1,000.50) Only save from two digits past the decimal point ("$500.559" is converted to 50055 and doesn't round) Strips [a-zA-Z] from strings Pass in a string or a number. Numbers will be stored AS IS. Assumes that if you set the value to an integer you have already done the conversion (e.g. 50000 = $500.00) If a floating point number is passed in it will round it. (500.55 -> 501). Just pass in integers to be safe.
将字符串保存为整数(通过去除非数字并乘以 100)以防止执行计算时出现舍入错误(有关详细信息,请参阅陷阱)从字符串的开头去除符号(有时用户包括货币符号)去除逗号(有时)用户添加逗号或将粘贴值复制到表单中,例如“1,000.50”)仅保存小数点后两位数(“$500.559”转换为 50055 且不舍入)从字符串中剥离 [a-zA-Z] 传入字符串或数字。数字将按原样存储。假设如果您将值设置为整数,则您已经完成了转换(例如 50000 = $500.00)如果传入一个浮点数,它将对其进行四舍五入。(500.55 -> 501). 只需传入整数即可安全。
Hope it helps some1.
希望对大家有所帮助。
回答by ansorensen
I've been researching for a while on this topic, because I want to store not only price, but version, which both may have trailing 0s that get chopped off when stored as a number. As far as I know, Mongoose/MongoDB can't save a number with trailing zeroes.
我一直在研究这个主题一段时间,因为我不仅要存储价格,还要存储版本,这两个可能都有尾随 0,当存储为数字时会被砍掉。据我所知,Mongoose/MongoDB 无法保存带有尾随零的数字。
Unless you save the number as a string.
除非您将数字保存为字符串。
Aside from storing numbers in tens or thousands and dividing or parsing, you can also store it as a string. This means, you can always just print it out when you need to show "1.0" or "1.00" by just using the variable without any conversion. Due to JavaScript being untyped, you can still compare it to numbers (make sure it's on the left hand side). Var < 10, for example, will return the right evaluation, even when var is a string. If you're comparing two variables, you'd need to make sure that they're both numbers, though. When you need a number, you can multiply the string by one (var * 1 < var2 * 1), which will ensure that JavaScript treats the var as a number, although it will lose the trailing zeros.
除了存储数以万计的数字和除法或解析之外,您还可以将其存储为字符串。这意味着,当您需要显示“1.0”或“1.00”时,只需使用变量而不进行任何转换,就可以随时将其打印出来。由于 JavaScript 是无类型的,您仍然可以将其与数字进行比较(确保它在左侧)。例如,Var < 10 将返回正确的评估,即使 var 是一个字符串。但是,如果要比较两个变量,则需要确保它们都是数字。当您需要一个数字时,您可以将字符串乘以 1 (var * 1 < var2 * 1),这将确保 JavaScript 将 var 视为一个数字,尽管它会丢失尾随的零。
On the one hand, storing it as a string means you need to do a conversion every time you want to use the variable as a number. On the other hand, you would presumably be doing a numeric conversion anyway (var / 100) every time you want to use a cents number as a dollar amount. This option would depend on how frequently you need to your value as a number. Also it may cause bigger bugs if you forget that your variable is a string than if you forget that your variable is in cents.
一方面,将其存储为字符串意味着每次要将变量用作数字时都需要进行转换。另一方面,每次您想使用美分数字作为美元金额时,您大概都会进行数字转换(var / 100)。此选项取决于您需要将值作为数字的频率。此外,如果您忘记变量是字符串,则可能会导致更大的错误,而不是忘记变量以美分为单位。
(However, it's a great fit for version numbers that would only ever be used for display and comparison.)
(但是,它非常适合仅用于显示和比较的版本号。)
回答by Francesco
The numeralmodule will accomplish that: http://numeraljs.com/https://www.npmjs.com/package/numeral
该数字模块将实现这一目标: http://numeraljs.com/ https://www.npmjs.com/package/numeral

