I'm using the Mongo Native Javascript driver to insert data into a Mongo database. All of the docs I've read say that Mongo stores all of its numeric values as Doubles, and Javascript also stores all of its numerics as doubles. I can confirm that this works in the shell:
PRIMARY> db.products.insertOne({id: 10, price: 10})
PRIMARY> db.products.insertOne({id: 11, price: 11.99})
PRIMARY> db.products.aggregate([{$project: { price: {$type: "$price"}}}])
{ "_id" : ObjectId("605525ed8f87f3c9bc136a69"), "price" : "double" }
{ "_id" : ObjectId("605525fb8f87f3c9bc136a6a"), "price" : "double" }
However, when I insert values from the Javascript driver, they are not all doubles, but instead the integer-looking number is stored with a bsontype of int
:
-- Node
await products.insertOne({id: 1, price: 20});
await products.insertOne({id: 2, price: 20.85});
--Mongo Shell
PRIMARY> db.products.aggregate([{$project: { price: {$type: "$price"}}}])
{ "_id" : ObjectId("6055261ee2efe2622736a36e"), "price" : "int" }
{ "_id" : ObjectId("6055261ee2efe2622736a36f"), "price" : "double" }
Is there a way in the mongo js driver to force it to always store numbers as doubles? I am ultimately reading this into a Java program which really wants the incoming types to be consistent, so if I can make them that way on insert I'd like to do that.
Option 1
You can use https://plugins.mongoosejs.io/plugins/double
const Double = require('@mongoosejs/double');
const productsSchema = new Schema({ price: Double });
console.log(new Double(5));
Output - Double {
path: 5,
instance: 'Double',
validators: [],
getters: [],
setters: [],
options: SchemaTypeOptions {},
_index: null,
[Symbol(mongoose#schemaType)]: true }
You can check the source code here
https://github.com/mongoosejs/mongoose-double/blob/master/lib/index.js
Option 2
You can use mongoose.Decimal128
-
https://mongoosejs.com/docs/api.html#mongoose_Mongoose-Decimal128
const productsSchema = new Schema({ price: mongoose.Decimal128 });
Insert query will be like this -"price":{"$numberDecimal":"5"}
The Mongoose Decimal128 SchemaType. Used for declaring paths in your schema that should be 128-bit decimal floating points. Do not use this to create a new Decimal128 instance, use mongoose.Types.Decimal128 instead.
https://jira.mongodb.org/browse/SERVER-854
https://docs.mongodb.com/manual/core/shell-types/#numberint
https://docs.mongodb.com/manual/core/shell-types/#numberdecimal
The mongo shell treats all numbers as 64-bit floating-point double values by default. The mongo shell provides the NumberDecimal() constructor to explicitly specify 128-bit decimal-based floating-point values capable of emulating decimal rounding with exact precision. This functionality is intended for applications that handle monetary data, such as financial, tax, and scientific computations.
Mongo shell default insertion for the number is double to insert int we have to typecast using NumberInt
db.data.insertOne({ "numDouble":20.87, "numInt": NumberInt(1) })
https://github.com/Studio3T/robomongo/issues/622
Another option not sure it will work.
https://mongodb.github.io/node-mongodb-native/api-bson-generated/double.html
typecast the value to Double
while inserting the value
const Double = require("mongodb").Double;
await products.insertOne({id: 1, price: Double(20) });
console.log(new Double(5))
Output - Double { _bsontype: 'Double', value: 5 }
A class representation of the BSON Double type. class Double()
Arguments:
value (number) – the number we want to represent as a double. Returns: double