mongoose validator not working as expected - mongodb

i want to add batch,department,stream,id fields to the schema depending if usertype is “Student”,i do not understand why,but sometimes it adds the fields sometimes not.forexample if i created a user with usertype “Student” first it does not add the fields,but after that when i created a user with usertype “Teacher” or “Admin” it asks me the fields are required meaning it add the fields and this happens vice versa.why any way to fix this issue?please help guys.
what i have tried well,i have asked chatGpt but no answers i mean just the answers do not solve the issue.
here is the code
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema(
{
fullName: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
userType: {
type: String,
required: true,
},
phoneNumber: { type: String, required: true },
password: { type: String, required: true },
approved: { type: Boolean, default: true },
},
{
timestamps: true,
}
);
userSchema.pre("validate", function (next) {
if (this.userType === "Student") {
this.constructor.schema.add({
batch: {
type: Number,
required: true,
},
department: {
type: String,
required: true,
},
stream: {
type: String,
required: true,
},
id: { type: String, required: true }, //, unique: true
});
}
next();
});
const userModel = mongoose.model("users", userSchema);
module.exports = userModel;

Related

Populate a property of a mongoose schema with all the data in another collection

I have a model with articles, and would like to populate an array of data with all the documents in a collection.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ArticlesSchema = new mongoose.Schema({
path: {
type: String,
required: true,
unique: true,
},
base_headline: {
type: String,
required: true,
},
intro: {
type: String,
required: true,
},
featured_image: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
platform_filter: {
type: String,
},
free_filter: {
type: String,
},
content_type: {
type: String,
required: true,
},
data: [{ type: Schema.Types.ObjectId, ref: 'DesignProducts' }],
date: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model('Articles', ArticlesSchema);
The data property should be populated with all documents in the DesignProducts collection.
I tried running this but the data array is still empty:
Article.findOne({ path: slug }).populate('data').exec();
Here is what the designProducts model looks like:
const mongoose = require('mongoose');
const DesignProductsSchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true,
},
intro: {
type: String,
required: true,
},
website: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model('DesignProducts', DesignProductsSchema);
This array should be populated with all the documents in the DesignProducts collection:

MongoDB: Find items with the user id

I have a product collection and a user collection where I reference user to my product collection.
So far what I am trying to achieve here is to get only the products that are created by that user.
const getOwnerProduct = expressAsyncHandler(async (req, res) => {
const activeUser = await User.findById(req.user._id)
const pageSize = 10
const page = Number(req.query.pageNumber) || 1
const items = { user: { _id: activeUser } }
const count = await Product.countDocuments({ ...items } )
const products = await Product.find({ ...items }).limit(pageSize).skip(pageSize * (page - 1))
res.json({ products, page, pages: Math.ceil(count / pageSize) })
})
Here's the Product Schema:
const productSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
name: {
type: String,
required: true
},
price: {
type: Number,
required: true,
},
description: {
type: String,
required: true
},
email: {
type: String
},
rating: {
type: Number,
required: true,
default: 0
},
image: {
type: String,
required: true,
default: 0
},
}, { timestamps: true
})
And here's the userSchema:
const userSchema = mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
phone: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
role: {
type: String,
enum: ['administrator', 'productOwner', 'regular'],
default: 'regular'
}
}, { timestamps: true
})
Here's the router:
app.use('/api/products', productRoutes)
router.route('/').get(getProducts, admin).get(getOwnerProducts, productOwner)
For some reason this doesn't work. I think my query on mongodb is not correct.
Any idea what am I missing here?
Here instead of const products = await Product.find({ ...items }) you can try
await User.findById(req.user._id).forEach(element =>{Product.find({user=element._id})});
or
await User.findById(req.user._id).forEach(element =>{Product.find(user=element._id)});

MongoDB: Set and get Sub Document Schema

I'm using mongoose and I have users collection shown below, but I now want to allow the user to save a number of articles, an article has a title, subtitle, and body, One user can have many articles.
How can I restructure the users collection to allow the articles to be added
const userSchema: Schema = new Schema(
{
email: { type: String, required: true, unique: true },
fullName: { type: String, required: true },
password: { type: String, required: true },
},
{
timestamps: true,
}
);
I'm using the below to set new data to the user's collection, how do I adapt it to allow me to set and get the new articles detailed above?
const confirmed = await userModel
.findOneAndUpdate(
{ email },
{
$set: { password },
}
)
.exec();
You can set the option strict: false and add(save) new fields to your schema.
const userSchema: Schema = new Schema(
{
email: { type: String, required: true, unique: true },
fullName: { type: String, required: true },
password: { type: String, required: true },
},
{
strict: false,
timestamps: true,
}
);
Here is the docs

Data is not inserted as per schema

I had defined mongoose schema and i tried to insert data into mongodb.But it is not inserted as per defined schema
export const EmpSchema: mongoose.Schema = new Schema({
name: {
type: String,
required: true
},
empNo: {
type: String,
required: true
},
skill: {
type: [String],
required: true
},
address: {
type: String,
required: true
}
}, {
_id: false,
versionKey: false,
retainKeyOrder: true
});
It is getting stored like Array elements as last field.like
name
empno
address
skill
export const EmpSchema: mongoose.Schema = new Schema({
name: {
type: String,
required: true
},
empNo: {
type: String,
required: true
},
skill: {
type: [String],
required: true
},
address: {
type: String,
required: true
}
}, {
_id: false,
versionKey: false,
retainKeyOrder: true
});
YOUR SCHEMA DEFINATION IS CORRECT PLEASE CHECK THE CONTROLLER PART WHERE YOU PUT THE INSERT QUERY . THERE MATTERS A INSERTION ORDER

Mongoose: How can I reference a nested schema that is in a separate file?

If two schemas are in the same file, you can reference it with: [AccountSchema]. You can see that in the "accounts" property of the UserSchema.
import express from 'express'
import mongoose from 'mongoose'
const Schema = mongoose.Schema
import Account from './accounts'
let AccountSchema = new Schema ({
accountName: {
type: String,
trim: true,
required: true,
unique: [true, "You already have an account with this name."],
},
percent: {
type: Number,
min: 1,
max: 100,
required: true
},
isGoal: {
type: Boolean,
default: false
},
accountHistory: {
type: Array
}
})
let UserSchema = new Schema ({
username: {
type: String,
unique: [true, "This username is taken."],
trim: true,
},
email: {
type: String,
unique: [true, "This email is already being used."],
trim: true
},
password: {
type: String,
trim: true
},
infusions: {
type: Array,
timestamps: true
},
accounts: {
type: [AccountSchema],
count: {
type: Number,
default: 8
}
},
secretToken: {
type: String
},
active: {
type: Boolean,
default: false
},
isAdmin: {
type: Boolean,
default: false
}
}, {
timestamps: true,
})
const User = mongoose.model('users', UserSchema)
export default User
But what do you do if the schemas are in separate files? How can you reference them? I tried like this, but it didn't work:
// account.js
import express from 'express'
import mongoose from 'mongoose'
const Schema = mongoose.Schema
let AccountSchema = new Schema ({
accountName: {
type: String,
trim: true,
required: true,
unique: [true, "You already have an account with this name."],
},
percent: {
type: Number,
min: 1,
max: 100,
required: true
},
isGoal: {
type: Boolean,
default: false
},
accountHistory: {
type: Array
}
})
const Account = mongoose.model('users', AccountSchema)
export default Account
And the User schema in a separate file with:
// users.js
import express from 'express'
import mongoose from 'mongoose'
const Schema = mongoose.Schema
import Account from './accounts'
let UserSchema = new Schema ({
username: {
type: String,
unique: [true, "This username is taken."],
trim: true,
},
email: {
type: String,
unique: [true, "This email is already being used."],
trim: true
},
password: {
type: String,
trim: true
},
infusions: {
type: Array,
timestamps: true
},
accounts: {
type: [Account],
count: {
type: Number,
default: 8
}
},
secretToken: {
type: String
},
active: {
type: Boolean,
default: false
},
isAdmin: {
type: Boolean,
default: false
}
}, {
timestamps: true,
})
const User = mongoose.model('users', UserSchema)
export default User
In one article I was told to export the schema, not the model that references the schema, but they did not give any idea as to how to achieve that.
Try removing below line from your account.js file
const Account = mongoose.model('users', AccountSchema);
And change the last line to this
export default AccountSchema;