How to make mongoose schema dynamic, depending upon the value? - javascript

I am new to mongoose and I have searched alot about it and was not able to find out the ans. Please help, thanks in advance.
const user = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true
},
rollno: {
type: Number,
required: true,
unique: true,
},
password : {
type: String,
required: true,
},
isVoter: {
type: Boolean,
required: true,
default: true
}
}, {
timestamps: true
});
Can I have a schema which would be dependent on the value of isVoter. For example if value of isVoter is false then we should have schema like this :
const user = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true
},
rollno: {
type: Number,
required: true,
unique: true,
},
password : {
type: String,
required: true,
},
isVoter: {
type: Boolean,
required: true,
default: true
},
promises: [
{
type: String
}
]
, {
timestamps: true
});

You can defined if one variable is required or not based in another property in this way:
promises: [
{
type: String,
required: function(){
return this.isVoter == false
}
}
]
So, promises will be required only if isVoter is false. Otherwise will not be required.

you can use pre hook in mongoose, check the documentation and before saving, check the isVoter value, if you don't want to save promises, try this.promises = undefined
user.pre('save', function(next) {
if(this.isVoter== true){
this.promises = undefined
}
else{
this.promises = "hello"
//do somethings
}
next();
});
and in the schema promises should be definded

Related

Hide all hidden mongoose methods and properties

I use nuxt 3. I have this code on my serverside.
findAuthorByEmail(email: string, showPassword = false) {
return Author.findOne({ email })
.select(showPassword ? "" : "-password_hash")
.lean();
},
Inside my /server/api/login.post.ts i return it here:
return {
token,
author,
};
Nuxt has the feature to provide the types for my front end. What should my query look like so that my response only provides the properties which are available? If I try to use for example $isDefault then it does not work of course.
Here is also my mongoose model:
import { Document } from "mongoose";
import { AuthorI } from "~~/types";
import { conn } from "../configuration/connection";
import { authorConfig } from "../configuration/author";
import mongoose from "mongoose";
const schema = new mongoose.Schema({
email: {
required: true,
type: String,
trim: true,
lowercase: true,
unique: true,
},
password_hash: {
type: String,
required: true,
trim: true,
minlength: authorConfig.password_min_length,
},
name: {
maxlength: authorConfig.name_length,
trim: true,
type: String,
},
family_name: {
type: String,
maxlength: authorConfig.family_name_length,
trim: true,
},
description: {
type: String,
maxlength: authorConfig.description_length,
trim: true,
},
props: {},
username: {
type: String,
trim: true,
unique: true,
required: true,
maxlength: authorConfig.username_length,
},
created: {
type: Date,
required: true,
default: Date.now,
immutable: true,
},
enabled: {
type: Boolean,
default: true,
},
});
export const Author = conn.model<AuthorModel>("Author", schema);
interface AuthorModel extends AuthorI, Document {}
use .lean() method. check official doc mongoose lean

How to store empty array in mongodb

I want to store empty array in user schema's friends key. But, mongoose won't let me to add empty array of friends.
Here's my User schema
const userSchema = mongoose.Schema({
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
userName: {
type: String,
unique: true,
required: true,
},
email: {
type: String,
required: true,
unique: true,
validate: [validator.isEmail, "Please enter a valid Email"],
},
password: {
type: String,
required: true,
minlength: [6, "Password must be at least 6 characters"],
},
friends: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
unique: true,
},
],
});
And here's my code to pull data from array and save empty array
const index = req.user.friends.findIndex(friend => friend.toString() === req.params.id);
if(index !== -1){
req.user.friends.splice(index, 1);
}else{
req.user.friends.push(req.params.id);
}
const user = new User(req.user);
await user.save({validateBeforeSave: false});
return res.json({success: true});
specify default value instead
friends: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
unique: true,
default: []
},
],

Node Populate Array with object reference

I need to Populate courses of StudentSchema with the courses (Object_id) from CoursesSchema that belong to the major same as students major
let StudentSchema = new Schema({
_id: new Schema.Types.ObjectId,
emplId: {
type: Number,
required: true
},
major:{
type: String,
required: true
},
courses:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'courses',
grade:{
type: String,
required: false,
}
}],
});
const courseSchema = new mongoose.Schema({
code: {
type: String,
required: true
},
title: {
type: String,
required: true
},
//array of majors that a courses is required for e.g: ['CS', 'CIS']
major: {
type: Array,
required: false,
},
//
CIS:{
type: Boolean,
required: false,
},
CNT:{
type: Boolean,
required: false,
},
CS:{
type: Boolean,
required: false,
},
GIS:{
type: Boolean,
required: false,
},
})
What do I do?
StudentCoursesRouter.get('/studentcourses', (req, res) => {
Courses.find({CS: true}, (err, courses) => {
if ( err ) {
console.log('Error occured while getting records');
res.json(err);
} else {
courseMap = {}
courses.forEach(function(course) {
courseMap[course._id] = course._id;
});
//res.send(courses);
Students.find({empleId: 12345678}).courses.push(courses);
}
res.json(Students);
})
This is what i am doing but it is not populating courses of student and gives an empty array for courses.
API Request Response Screenshot
You mention populate but you are not using populate?
e.g. Students.find({empleId: 12345678}).populate('course')
If you want it lean u also need to install mongoose-lean-virtuals
e.g. Students.find({empleId: 12345678}).populate('course').lean({ virtuals: true })

How to sustainably organise user schema in mongoose

I have a user which should have the following fields and currently has following schema:
const UserSchema = new Schema(
{
email: {
type: String,
required: true,
index: { unique: true },
lowercase: true,
},
isVerified: { type: Boolean, default: false }, // whether user has confirmed his email
name: { type: String, required: false },
password: { type: String, required: true, minLength: 6 }, // object with next two included?
passwordResetExpires: Date,
passwordResetToken: String,
roles: [{ type: 'String' }], // Array of strings?
username: { type: String, required: false },
token: [{ type: String, required: false }], // used to send verification token via email
},
{ timestamps: true },
);
So yes, what is the world's default standard for organising user schemas. This schema's fields are pretty common, right?

How do I access the data in the .pre('validation') hook?

I am having trouble with performing operations during the pre('validate') hook. I need to do some prevalidation (making sure at least one of 2 different fields is populated, but not necessarily both, for example).
const AccessorySchema = new Schema({
accessory: {
type: String,
required: true,
},
category: {
type: String,
required: true,
enum: [
'Offense',
'Defence',
'Miscellaneous'
]
},
space: {
type: Number,
required: true,
validate: {
validator: Number.isInteger,
message: 'Space must be an integer'
}
},
priceFixed: {
type: Number,
required: false,
validate: {
validator: Number.isInteger,
message: 'Fixed Price must be an integer'
}
},
priceMultiplier: {
type: [Schema.Types.Mixed],
required: false
},
weightFixed: {
type: Number,
required: false,
validate: {
validator: Number.isInteger,
message: 'Fixed Weight must be an integer'
}
},
weightMultiplier: {
type: [Schema.Types.Mixed],
required: false
},
vehicles: {
type: [String],
required: true,
enum: ["car","cycle"]
}
});
AccessorySchema.pre('validate', (next) => {
console.log(this);
next();
});
And I send it this object :
{
accessory: "some name",
category: "Miscellaneous",
priceMultiplier: [3,5],
weightMultiplier: [3,5],
space: 0,
vehicles: ["car"]
}
this logs {} and populates the mongo DB. But I can't check any of the properties in pre validation.
mongoose version is ^4.7.7, nodejs 6.10.2, mongodb version is 3.2.9
How can I access the data in the pre validation hook?
do not use arrow function, it doesn't bind the context.
Change your code to below
AccessorySchema.pre('validate', function(next){
console.log(this);
next();
});

Categories

Resources