I have this mongoose schema, I added updated_by and created_by, but for some reason when I save models from client to server, those fields aren't visible:
userSchema = mongoose.Schema({
role: {
type: String,
enum: ['Admin', 'Owner', 'User']
},
username: {
type: String,
unique: true,
required: true,
validate: [validation.usernameValidator, 'not a valid username']
},
passwordHash: {
type: String,
required: true,
validate: [validation.passwordValidator, 'not a valid password']
},
email: {
type: String,
unique: true,
required: true,
validate: [validation.emailValidator, 'not a valid email address']
},
firstName: {
type: String,
required: false
},
lastName: {
type: String,
required: false
},
registered_at: {
type: Date,
default: Date.now
},
created_by: {
type: String,
required: false
},
updated_by: {
type: String,
required: false
},
created_at: {
type: Date,
default: Date.now
},
updated_at: {
type: Date,
default: Date.now
}
},
{
autoIndex: false
});
is this normally a problem? Do I have to somehow rebuild something with Mongoose or MongoDB in order for them to pick up the new properties on this model?
Of course, I did restart the mongoDB server, but that didn't do anything.
In any case, if you save your User model, the fields with actual values shown in MongoDB will be the ones you set a value for yourself when saving the model OR the fields with a default value set in your userSchema.
So, just to clarify on this:
address: { type: String, default: ' ' }
will be shown in MongoDB with a value of ' ' unless you set a specific address when saving your User model.
But,
address: String
will NOT be shown in MongoDB unless you set a specific address when saving your User model.
EDIT
Thanks to Matthew for pointing it out, actually upsert behavior is indeed the following:
If upsert is true and no document matches the query criteria, update() inserts a single document.
Related
const notificationSchema = mongoose.Schema({
type:{
type: String
},
message:{
type: String
},
userId:{
type: String,
required: true,
},
timestamp:{
type: Date,
default: new Date()
},
expireAt: {
type: Date,
default: Date.now,
index: { expires: '5m' },
},
})
My data is not getting automatically delete in mongoose, Is something wrong with my model? Here is my Structure of model.Can anyone help
const notificationSchema = mongoose.Schema({
type:{
type: String
},
message:{
type: String
},
userId:{
type: String,
required: true,
},
{
timestamps: true
}
});
notificationSchema.index({createdAt: 1},{expireAfterSeconds: 3600});
Each field in the collection will be deleted after 3600seconds
There's several ways, but one that pops to mind is TTL.
"TTL indexes are special single-field indexes that MongoDB can use to automatically remove documents from a collection after a certain amount of time or at a specific clock time."
Find out more here > https://docs.mongodb.com/manual/core/index-ttl/
And for mongoose > https://github.com/mongoosejs/mongoose-ttl
I am trying to reference a schema property named grade in my model to another model's id. But there are some instance where I would like to keep it as null. I tried to keep the default as null and tried but I get the following error:
ValidationError: User validation failed: grade: Cast to Array failed for value "" at path "grade"
The following is my code:
import * as mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
username: String,
email: { type: String, unique: true, lowercase: true, trim: true },
password: String,
school: { type: String, default: null },
mobile: Number,
grade: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Grade', default: null }],
role: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Role' }],
company: { type: String, default: null },
designation: { type: String, default: null },
active: { type: Number, default: 2 },
url: { type: String, default: null },
admin: { type: Number, default: 0},
created: { type: Date, default: Date.now },
last_active: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
export default User;
Is there a way I can keep default values as null though referencing it?
In MongoDB or NoSQL databases there is no need to make a default value as NULL as it is based on Schemaless architecture however in relational databases you can do that. as long as you don't have a value for the field this column should not be there at all for this row.
Check below those example for 2 rows of your schema:
{username: "jack", email: "jack#gmail.com", password: "123"}
{username: "msoliman", email: "msoliman#gmail.com", password: "123", school: "AB"}
you notice the first row doesn't have school at all, this is exactly the same as you save in relational database school as NULL.
I hope this helps you understand what I mean, if not please leave a comment. if it helps please don't forget to rate my answer
The NoSQL is defined in such way if the values are available so it will store in schema otherwise it won't consider it. So If you want to define your keys which might have or haven't values take them as you have taken the role in your above schema else required you can take it as
default: '',
school: { type: String, default: '' }
I have build a schema as follows:
const UserInfoSchema = new Schema({
email: { type: String, required: true, unique: true },
username: { type: String, required: true, unique: true },
userId: { type: Schema.Types.ObjectId, ref: 'User'},
displayName: { type: String, required: true },
profilePic: {
filename: {type: String},
url: {type: String}
},
created_at: Date,
updated_at: Date
})
What I need here is once the fields such as email, username and userId are saved, should not be modified. Is there anything pre-build in mongoose for this kind of feature?
I have done some research on schema.pre('update', (next) => {}), but got nothing really useful/don't know if one can use for the mentioned feature. Any help on this matter is greatly appreciated. Thanks in advance.
There is an easier way
when you save the Schema, you can set the field as immutable, like this
const UserInfoSchema = new Schema({
email: { type: String, required: true, unique: true, immutable:true },
username: { type: String, required: true, unique: true, immutable:true },
userId: { type: Schema.Types.ObjectId, ref: 'User', immutable:true},
displayName: { type: String, required: true },
profilePic: {
filename: {type: String},
url: {type: String}
},
created_at: Date,
updated_at: Date
})
it won't throw any error, if you want it you should check it elsewhere, but when you try to modify the immutable fields, it wont be changed at all
for(const key in userUpdates) {
switch(key) {
case 'username':
case 'email':
throw new Error('These field/s cannot be changed anymore');
}
}
User.findByIdAndUpdate(id, userUpdates, { new: true, runValidators: true });
In my Mongoose schema I'm using Date.now to insert a user based on creation time. For some strange reason (unknown to me), the time is one hour behind. I'm thinking it's because I'm (GMT+1) but and my Express/Node/Mongo setup must be standard GMT time, or maybe not. Has anyone come across this before?
User = new Schema({
fullName: {
type: String,
required: true
},
password: {
type: String,
required: true
},
emailAddress: {
type: String,
unique: true,
required: [true, 'Email address is required.']
},
uniqueURL: {
type: String,
required: true,
unique: true
},
created: {
type: Date,
default: Date.now
}
});
I Have schema design as below. I have posts array which is reference to the post model. Is it good idea to put it in User schema or should I not include as it is always growing as users add their post. I guess I should only put accesstokens in reference and not posts. Am I thinking right?
var UserSchema = new Schema({
username: {
type: String,
unique: true,
required: true,
lowercase: true,
trim: true
},
encrypted_password: {
type: String,
required: true
},
salt: {
type: String,
required: true
},
email: {
type: String,
unique: true,
required: true,
lowercase: true,
trim: true
},
mobile: {
type: Number,
unique: true
},
bio: {
type: String
},
created: {
type: Date,
default: Date.now
},
access_tokens: [{type: Schema.Types.ObjectId, ref: 'AccessToken'}],
posts: [{type: Schema.Types.ObjectId, ref: 'Post'}]
}, { collection: 'users' });
You should have a separate collection for Posts but you should keep the access_tokens within the user schema. One good reason you might consider separating the posts into its own collection is there are many use cases where you will query for just posts. However, with access_tokens, they will always be tied to a user.
tldr;
Posts should have their own schema
Access tokens should be in user schema
Hope that helps!