how should i store a price in mongoose?

后端 未结 5 2201
再見小時候
再見小時候 2020-12-14 08:48

I\'m using mongoose schemas for node.js along with express-validator (which has node-validator santiziations and validators).

What\'s a good way to store price for a

相关标签:
5条回答
  • 2020-12-14 09:12

    The numeral module will accomplish that: http://numeraljs.com/ https://www.npmjs.com/package/numeral

    0 讨论(0)
  • 2020-12-14 09:15

    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

    the getPrice will convert it back to readable format, so I can use item.price in my views w/o modifying it.

    the setPrice converts it to cents.

    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

    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.

    0 讨论(0)
  • 2020-12-14 09:22

    Adds schema type "Currency" to mongoose for handling money. Strips out common characters automatically (",", "$" and alphabet chars)

    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.

    Hope it helps some1.

    0 讨论(0)
  • 2020-12-14 09:26

    Hint: The method described here is basically just another implementation of chovy's answer.

    Workaround for Mongoose 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:

    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;
    });
    
    0 讨论(0)
  • 2020-12-14 09:28

    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.

    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.

    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.

    (However, it's a great fit for version numbers that would only ever be used for display and comparison.)

    0 讨论(0)
提交回复
热议问题