我正在为node.js使用mongoose模式以及express-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 ...我宁愿只转换为十进制并删除所有字符,所以我总是将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
我只需要一种方法将4200转换为$ 42.00,当我调用item.price并清理并将输入转换为4200时。
答案 0 :(得分:24)
这就是我最终做的......
我在数据库中将价格存储为美分,因此如下所述,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})?$/);
}
我希望有一种方法允许$因为我认为它是一个可用性问题,只是让用户输入它,但将其剥离。我不知道该怎么做,仍然确认我们有价格,而不是一堆信件。
答案 1 :(得分:9)
提示:此处描述的方法基本上只是chovy's answer的另一种实现。
如果您无法直接在架构中定义getter和setter,您还可以使用schema.path()
函数来完成此工作:
<!DOCTYPE html>
<html>
<head>
<script src="http://maps.googleapis.com/maps/api/js"></script>
<script>
var myCenter=new google.maps.LatLng(45.159457,18.0158902);
function initialize() {
var mapProp = {
center:new google.maps.LatLng(45.159457,18.0158902),
zoom:13,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
var map=new google.maps.Map(document.getElementById("map"),mapProp);
var marker=new google.maps.Marker({
position:myCenter,
});
marker.setMap(map)
}
</script>
<script>
function tagovi(){
var myCenter2=new google.maps.LatLng(45.1568915,18.0153617);
var marker2=new google.maps.Marker({
position:myCenter2,
});
marker2.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div class="b_m"><a href="#" onclick="tagovi()"><img src="slike/restorani.png"></a></div>
</body>
</html>
答案 2 :(得分:3)
添加架构类型&#34;货币&#34;为了处理钱而愚弄。自动删除常用字符(&#34;,&#34;,&#34; $&#34;和字母字符)
https://github.com/paulcsmith/mongoose-currency
它的作用:
将字符串保存为整数(通过剥离非数字并乘以100)以防止在执行计算时出现舍入错误(有关详细信息,请参阅gotchas) 从字符串的开头删除符号(有时用户包括货币符号) 删除逗号(有时用户用逗号添加或将粘贴值复制到表单中,例如&#34; 1,000.50) 仅从小数点后的两位数保存(&#34; $ 500.559&#34;转换为50055并且不进行舍入) 从字符串中剥离[a-zA-Z] 传入一个字符串或数字。号码将按原样存储。 假设如果您将值设置为整数,则表示您已完成转换(例如50000 = $ 500.00) 如果传递一个浮点数,它将围绕它。 (500.55 - > 501)。只需传入整数即可。
希望它有所帮助。
答案 3 :(得分:1)
我一直在研究这个话题,因为我不仅要存储价格,还要存储版本,这两个版本都可能有0后跟0,当存储为数字时会被切断。据我所知,Mongoose / MongoDB无法使用尾随零保存数字。
除非您将数字保存为字符串。
除了存储数十或数千的数字以及分割或解析之外,您还可以将其存储为字符串。这意味着,只需使用变量而不需要任何转换就可以在需要显示“1.0”或“1.00”时将其打印出来。由于JavaScript是无类型的,您仍然可以将其与数字进行比较(确保它位于左侧)。 Var&lt;例如,10将返回正确的评估,即使var是一个字符串。如果你要比较两个变量,你需要确保它们都是数字。当你需要一个数字时,你可以将字符串乘以一(var * 1&lt; var2 * 1),这将确保JavaScript将var视为一个数字,尽管它会丢失尾随的零。
一方面,将其存储为字符串意味着每次要将变量用作数字时都需要进行转换。另一方面,每次你想使用美分数作为美元金额时,你可能会进行数字转换(var / 100)。此选项取决于您需要将数值作为数字的频率。如果你忘记你的变量是一个字符串而不是忘记你的变量是美分,它也可能导致更大的错误。
(但是,它非常适合只能用于显示和比较的版本号。)
答案 4 :(得分:0)