Luc
Luc

Reputation: 17082

Decimal / Float in mongoose for node.js

I start my first test app on node.js / mongoDB / mongoose, this is a very simple app that aims to crate record in DB and retrieve them.

I create a model like:

var Car = new Schema({
    brand : String,
    speed  : Number,
    date  :  { type: Date, default: Date.now }
});

This is working fine, except that I would like to be able to provide a float value for speed instead of the integer one. I gave a try to Decimal and Float but none of them are working. I did not find in the documentation either.

Any idea ?

Upvotes: 71

Views: 144706

Answers (5)

99problems
99problems

Reputation: 564

While the mongoDB fully supports float type, the mongoose supports only type of Number which is integer. If you try to save to mongoDB float number using mongooses type of Number it will be converted to string.

To sort this out, you will need to load some plugin for mongoose which will extend its value types. There are some plugins which work best with currencies or dates, but in your case I would use https://www.npmjs.com/package/mongoose-double.

Your model after changes would look something like this:

var mongoose = require('mongoose')
require('mongoose-double')(mongoose);

var SchemaTypes = mongoose.Schema.Types;
var Car = new Schema({
    brand: { 
        type: String 
    },
    speed: {
        type: SchemaTypes.Double
    },
    date: {
        type: Date, 
        default: Date.now 
    }
});

Hope it helps.

Edit: I have just found that in 2018, the mongoose added support for Decimal128 so you can simply just use mongoose.Types.Decimal128 for your schema

Upvotes: -4

Pranab Das
Pranab Das

Reputation: 119

You can use the Decimal128 in Mongoose Schema as

speed:{
type:mongoose.Types.Decimal128
}

Upvotes: 11

Ehsan Sarshar
Ehsan Sarshar

Reputation: 3221

you can create your custom one. like so

'use strict';

const mongoose = require('mongoose');

class DoubleType extends Number {
  constructor(v) {
    super(v);
    this.value = v;
    this._bsontype = 'Double';
  }

  toBSON() {
    return this;
  }
}

class Double extends mongoose.SchemaType {
  constructor(key, options) {
    super(key, options, 'Double');

    Object.assign(this.$conditionalHandlers, {
      '$lt': val => this.castForQuery(val),
      '$lte': val => this.castForQuery(val),
      '$gt': val => this.castForQuery(val),
      '$gte': val => this.castForQuery(val),
    });
  }

  cast(val) {
    if (val == null) {
      return val;
    }
    if (val._bsontype === 'Double') {
      return new DoubleType(val.value);
    }

    const _val = Number(val);
    if (isNaN(_val)) {
      throw new mongoose.SchemaType.CastError('Double',
        val + ' is not a valid double');
    }
    return new DoubleType(_val);
  }
}

mongoose.Schema.Types.Double = Double;
mongoose.Types.Double = DoubleType;

module.exports = Double;

source is copied from @mongoosejs/double

Upvotes: 2

Muzaffar Mahmood
Muzaffar Mahmood

Reputation: 1908

Yes you can use the Decimal128 type.

https://mongoosejs.com/docs/api.html#mongoose_Mongoose-Decimal128

Upvotes: 10

Andrew Orsich
Andrew Orsich

Reputation: 53695

I've searched a bit and found this article stating that for storing float values you must use Number type. You can store any float value in speed field.

Upvotes: 99

Related Questions