Why integer (Number) are saved as Double in MongoDb - mongodb

I'm working on a new project and I try to figure out why when Mongoose save my model, instead of having an integer, I got a Double.
Ex. {myId: 12345678} become {myId: 12345678.0}​
My schema contains this:
{
myId: {
type: Number
}
}
Mongoose version: 5.x
Node: 10.x
Any idea ?

The Number schema type is floating point. If you want to store a number as an integer, you can use the mongoose-int32 plug-in:
var Int32 = require('mongoose-int32');
const schema = new mongoose.Schema({
myId: {
type: Int32
}
});
If you need 64-bit integer support, use the mongoose-long plug-in.

Instead of additional npm package overhead, it's recommended to use such getter/setter in the Schema Types.
var numberSchema = new Schema({
integerOnly: {
type: Number,
get: v => Math.round(v),
set: v => Math.round(v),
alias: 'i'
}
});
Therefore, CRUD operations related to field of Number Schema Type will cast to Int32 in Mongodb.
More info can be found in Mongoose v5.8.9 Schema Types documentation

Related

How to use Object type in mongose schema?

I am trying to store the amount of time an employee has worked in my MongoDB database, but not able to make a mongoose schema whose type will object.
The desired database should have a document like this:
{
name: 'name of employee',
report: {'01-01-2023':5hr, '02-01-202':7hr, '03-01-2023':8hrs}
}
This report will contain an object whose key will be a date and the value will be minutes or hours an employee has worked on that date.
how can I make a schema to achieve the desired goal, I have tried like this but did not work.
const UserSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
report: {
type: Object, // what should I write here
}
})

Mongoose does not seem to recognize the Number type

I am playing around with the mongoose documentation: https://mongoosejs.com/docs/schematypes.html
For some unknown reason to me, the code below does not run, it gives out the error:
TypeError: Invalid value for schema path `integerOnly.type`, got value "undefined"
If I change the type to String, like, it works:
var numberSchema = new Schema({
integerOnly: {
type: String,
get: v => Math.round(v),
set: v => Math.round(v),
alias: "i"
}
});
Does anyone can point out what is happening? I have found the mongoose documentation outdated, it seems that they do not update the documentation.
The original code, as in the mongoose page, is below.
//--------------------------------------------------
require("./connection");
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
//---------------------------------------------------
var numberSchema = new Schema({
integerOnly: {
type: Number,
get: v => Math.round(v),
set: v => Math.round(v),
alias: "i"
}
});
var Number = mongoose.model("Number", numberSchema);
Detail. if I comment out the line var Number = mongoose.model("Number", numberSchema);, it gives no error, but I cannot work without defining a model!
After a good night of sleep, my beauty sleep, I have found the problem:
var numberSchema = new Schema({
integerOnly: {
type: Number,
get: v => Math.round(v),
set: v => Math.round(v),
alias: "i"
}
});
var NumberType = mongoose.model("Number", numberSchema);
var doc = new NumberType();
The problem was: I was defining a type, namely Number, that already exists in mongoose.
It makes me wonder why mongoose would have a sample in their tutorial with such a primitive error: I was shadowing the Number type, it is textbook error.
It makes me think that I am missing something since I am trying to learn new tricks in mongoose, and I was unable to run the example the way they provided.

Mongoose mixed SchemaType

I couldn't understand that for what purpose mongoose schemaType is used for. If someone could explain it will be helpful.
I'm have to reference another schema from a schema i want to know if we can get the details of all schema together when we do a findOne() on mongoose.
mixed schema means whatever you want the type to be. if you input a String, Number, Date, mongoose will let you do that. However according to documentation, mongoose ref does not work with mixed.
Note: ObjectId, Number, String, and Buffer are valid for use as refs.
if you use mixed, and ref it, you won't be able to query it back.
If you start all over(delete the database and reinsert again), use ObjectId instead of Mixed.
var storySchema = Schema({
author : { type: ObjectId, ref: 'Person' },
});
If you wish to retain old database, the best way is to change mixed to string
var storySchema = Schema({
author : { type: String, ref: 'Person' },
});

Does using dbref do anything more than just storing an `id`

My Mongoose schema:
// set up the schema
var CategorySubSchema = new Schema({
name: { type: String },
_category_main : { type: String, ref: 'CategoryMain' }
},
And my controller code:
CategorySub.create({
name : req.body.name,
_category_main : req.body.category_main
}, function(err, data){
An entry in my db:
{
"_id": "54dd163434d78ae58f6b1a69",
"name": "Snacks",
"_category_main": "54dcf4a71dfecb4d86ddcb87",
"__v": 0
},
So I used an underscore, because I was following an example. Does this mean anything to the database or is it just convention for references?
Also, instead of passing the entire JSON object in the request - req.body.category_main, why not just pass and id and change my schema to this?:
var CategorySubSchema = new Schema({
name: { type: String },
category_main_id : { type: String }
},
In short, Yes.
The below schema definition is an example of Manual references.
var CategorySubSchema = new Schema({
name: { type: String },
category_main_id : { type: String }
}
where,
you save the _id field of one document in another document as a
reference. Then your application can run a second query to return the
related data. These references are simple and sufficient for most use
cases.
In this case, we need to write explicit application code to fetch the referred document and resolve the reference. Since the driver that we use wouldn't know about the collection in which the referred document is present nor the database in which the referred document is present.
When you define the schema as below, this is an example of storing the details of the referred document .(Database references)
var CategorySubSchema = new Schema({
name: { type: String },
_category_main : { type: String, ref: 'CategoryMain' }
}
They include the name of the collection, and in some cases the
database name, in addition to the value from the _id field.
These details allow various drivers to resolve the references by themselves, since the name of the collection and the database(optional) of the referred document would be contained in the document itself, rather than we writing explicit application code to resolve the references.
So I used an underscore, because I was following an example. Does this mean anything to the database or is it just convention for
references?
Using underscore in the _id field is a valid naming convention, but mongoDb doesn't explicitly mention about the naming convention of other fields which are used to resolve references. You could just use any other field name as long as it conforms to this.

Mongoose OR operator for schema definitions

Does Mongoose support, or is there an available package that supports multiple "options" for the embedded schemas in an array?
For example, the things property can contain only one of two schemas:
new Schema({
things: [{
requiredProp: String,
otherProp: Number
}, {
otherOption: Number
}]
});
In other words, I do not want to just allow anything (AKA Schema.Types.Mixed) to be stored in this property, but only these two possible definitions.
Or, do schema design recommendations exist to avoid this problem?
You should only define one dict in the array type of the schema, and then set if they are required or not with the mongoose schema types logic. Use pre save if you want to do more logic to assure that either one of the fields have been set, like this:
var MySchema = new Schema({
things: [{
requiredProp: {type: String, required: true},
otherProp: Number,
otherOption: Number,
}]
});
MySchema.pre('save', function(next) {
if (!this.otherProp && !this.otherOption) {
next(new Error('Both otherProp and otherOption can\'t be null'))
} else {
next()
}
})
Opon saving the object it will return an error if neither otherProp nor otherOption has been set.