The same default value gets used every time by `new mongoose.Schema` - javascript

I have problem using uuid with new mongoose.Schema. I use it to generate unique key for a device and save it to the MongoDb using Node.js. the problem is that it uses the same UUID every time.
This is the model:
const mongoose = require('mongoose');
const uuid = require('uuid/v4');
const DeviceSchema = new mongoose.Schema({
deviceNumberHash: {
type: String,
required: true
},
receivingKey: {
type: String,
default: uuid()
}...
});
And this is what is saved in MongoDb:
Any idea what's wrong?

You're calling uuid and passing its return value in as the default to use.
Instead, pass in the function (by not putting () after it):
const DeviceSchema = new mongoose.Schema({
deviceNumberHash: {
type: String,
required: true
},
receivingKey: {
type: String,
default: uuid // <========== No ()
}...
});
The default can be a function per the docs (an example there uses default: Date.now to provide a default for a date field, for instance).

Related

Possible to have `validate` fail on not specified elements?

The below returns success, even though obj contains an element that is not in the schema.
Question
Is it possible to have validate fail, when it sees elements that are not specified in the schema?
Jest have this expect(obj1).toEqual(obj2).
If Validate can't do it, what options do I then have to detect unwanted elements?
const Schema = require("validate");
const obj = {good: "1", bad: "2"};
const user = new Schema({
good: {
type: String,
required: true,
}
});
const r = user.validate(obj);
console.log(r);
Yes, there is a strict option on the Schema, from the documentation:
Schema
A Schema defines the structure that objects should be validated against.
Parameters
obj schema definition
opts options
opts.typecast
opts.strip
opts.strict
Validation fails when object contains properties not defined in the schema
(optional, default false)
So you'll need something like:
const options = { strict: true };
const user = new Schema({
good: {
type: String,
required: true,
}
}, options);

Typescript export default always executing

As a beginner in node js I cannot wrap my head around following problem.
import { createSchema, Type, typedModel } from "ts-mongoose";
const CompanySchema = createSchema(
{
companyName: Type.string({ required: true, unique: true })
},
{
timestamps: true
}
);
const Company = typedModel("Company", CompanySchema);
export { CompanySchema, Company };
This all works just fine until one point. When attempting to import this file.
import {CompanySchema, Company} from "./Company";
It executes typeModel method and stores the schema as expected. However, any other import of this file Company.ts reruns this method typeModel again. Which then fails because I can register schema with the name only once. How could I prevent of reruning this and still keep access to this object?
What would be general approach to this in order to keep access to both CompanySchema and Company object(as they will be later used in another schema as a reference)?
I don't know what the createSchema and typedModel are( if they are functions created by you or part of mongoose, the versions of mongoose ive worked with didnt have these functions )
...but I think you should not "createSchema" but define it instead.
e.g
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// define schema
const messageSchema = Schema({
sender: { type: Schema.Types.ObjectId, ref: 'User' },
recipient: { type: Schema.Types.ObjectId, ref: 'User' },
createdAt: { type: Date, default: Date.now },
deletedAt: { type: Date, default: undefined },
readAt: { type: Date, default: undefined},
message: { type: String, maxlength: 5000 }
});
// create a model based on that schema
const Message = mongoose.model('Message', messageSchema);
// Export the message model ... not the schema
module.exports.Message = Message;

Update date inside mongoose schema every time

I'm trying to update the lastMessageAt every time the [messageSchema] is updated.
It doesn't work this way. I The only date that is generated when the messageSchema is filled with it's very first object.
How do i solve this?
Thanks in advance!
const chatSchema = new mongoose.Schema({
userName1: String,
userName2: String,
messages: [messageSchema],
lastMessageAt: {
type: Date,
default: Date.now
}
});
You could use mongooses post middleware.
chatSchema.post('save', function(next) {
if (this.isModified('messages')) {
this.lastMessageAt = Date.now();
}
next();
});
found out that mongoose now has built in timestamps and they are used like this:
const chatSchema = new mongoose.Schema(
{
userName1: String,
userName2: String,
messages: [messageSchema]
},
{ timestamps: true }
);

Is it possible to define fields at the schema level that are calculated from another field using mongoose?

Is it possible to define fields at the schema level that are based off of another field using mongoose schemas?
For example, say I have this very simple schema:
const mongoose = require('mongoose')
const { Schema } = mongoose
const UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true
},
username_lower: {
type: String,
// calculated: this.username.toLowerCase()
},
email: {
type: String,
required: true,
unique: true
},
email_lower: { // for case-insensitive email indexing/lookup
type: String,
// calculated: this.email.toLowerCase()
},
password: {
type: String,
required: true
},
password_acceptable: {
type: Array,
// calculated: [
// this.password.toLowerCase(),
// this.password.toUpperCase()
// this.password.removeWhiteSpace(), // just an example
// ]
}
})
const User = mongoose.model('User', UserSchema)
module.exports = User
Is there something similar to the dummy "calculated" fields (that I've commented out) that would allow automatic field creation when the new document is saved? This would be very convenient and would reduce the clutter from having to manually define these fields on my back-end routes.
Thank you very much for your help!
you can do it by Pre middleware function, for more details
UserSchema.pre('save', function(){
this.username_lower = this.username.toLowerCase();
this.email_lower = this.email.toLowerCase();
// and so on ...
next();
});

Is there a way to get the model name from a mongoose model instance?

I´m using mongoose and I need to find a model name from a model instance.
In one part of the code I have:
const schema = new mongoose.Schema({
name: {
type: String,
required: true
},
phone: {
type: String,
required: true
}
}
const schema = new mongoose.Schema('MyData', schema);
let instance = new this({
name: 'Pete',
phone: '123'
});
Ths instance variable is passed around in my code. Later I need to find out instance name, but I´m no sure if there is a way to do it, something like:
let instanceName = getInstanceName(instance); <== Expects 'MyData' to be returned
Is that possible using mongoose ?
I realized I had a model not an instance of a model so I needed to use something else.
If you have a model, you can get the name as below:
const model = mongoose.model("TestModel", schema);
const collectionName = model.collection.collectionName;
If you have a specific item/instance of the model:
const instance = new model({...});
const collectionName = instance.constructor.modelName
as Hannah posted.
The name of the model can be accessed using this instance.constructor.modelName.
In my case I was looking for how to get a discriminator model name from a mongoose model, and the suggested solutions didn't work:
const PerformanceResult = DropDown.discriminator('PerformanceResult', new db.Schema({
name: { type: String, required: true }
}))
export default PerformanceResult
console.log(PerformanceResult.constructor.modelName) // undefined
console.log(PerformanceResult.collection.collectionName) // DropDown (parent name)
you can use this:
console.log(PerformanceResult.modelName) // PerformanceResult
mongoose version: "^5.11.8"

Categories