validation failed: slug: Path `slug` is required - node.js

I created a Blog and for its slug, I install slugify and require it.
I'm trying to save a new blog post in MongoDB with mongoose, but I am getting this error: slug: ValidatorError: Path slug is required.
I validate slugify from the tutorial from Web Dev Simplified Youtube Channel but it is not working.
Here is the code :
// getting-started.js
const mongoose = require("mongoose");
const slugify = require("slugify");
main().catch((err) => console.log(err));
async function main() {
await mongoose.connect(process.env.ATLAS);
}
// Schema
const blogSchema = new mongoose.Schema({
title: {
type: String,
required: true,
unique: true,
},
description: {
type: String,
required: true,
},
slug: {
type: String,
required: true,
unique: true,
},
});
blogSchema.pre("validate", (next) => {
if (this.title) {
this.slug = slugify(this.title, { lower: true, strict: true });
}
next();
});
// Model
const Blog = mongoose.model("Blog", blogSchema);

Your code is correct, replace the arrow function with the regular function because "this" doesn't work with arrow functions and remove required: true from slug field.
blogSchema.pre("validate", function (next) {
if (this.title) {
this.slug = slugify(this.title, { lower: true, strict: true });
}
next();
});

Related

TypeError: Product.deleteMany is not a function

This is my code to automatically feed data into my database. The connection is correct as if we comment out the await Product.deleteMany() but when the following code is compiled and run, we get the error "TypeError: Product.deleteMany is not a function". Please help.
Code:
require('dotenv').config()
const connectDB = require('./db/connect')
const Product = require('./models/product')
const jsonProducts = require('./products.json')
const start = async () => {
try {
await connectDB(process.env.MONGO_URI)
await Product.deleteMany()
await Product.create(jsonProducts)
console.log('Success!!!!')
process.exit(0)
} catch (error) {
console.log(error)
process.exit(1)
}
}
start()
ConnectDB code:
const mongoose = require('mongoose')
const connectDB = (url) => {
return mongoose.connect(url, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
})
}
module.exports = connectDB
Products model:
const mongoose = require('mongoose')
const productSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'products name must be provided']
},
price: {
type: Number,
required: [true, 'products price must be provided']
},
featured: {
type:Boolean,
default: false
},
rating: {
type: Number,
required: 4.5
},
createdAt: {
type: Date,
default: Date.now()
},
company:{
type: String,
enum:{
values: ['ikea', 'liddy', 'caressa', 'marcos'],
message: '{VALUE} is not supported'
}
// enum: ['ikea', 'liddy', 'caressa', 'marcos']
}
})
module.exports = mongoose.model('Product',productSchema)
The issue was in rating section of Products model
rating: {
type: Number,
required: 4.5
}
The correct format will be,
rating: {
type: Number,
default: 4.5
}
Which makes it an invalid model and therefore no function exists for an invalid model.

joi with mongoose schema

I'm trying to use joi module on mongoose schema but it doesn't work
everything works except joi validation
the module was installed and required.
schema:
const mongoose = require("mongoose");
const joi = require("joi");
const userSchima = new mongoose.Schema({
name: {
type: String,
required: [true, "use must have a name"],
unique: true,
trim: true,
},
email: {
type: String,
required: [true, "use must have an email"],
unique: true,
trim: true,
},
password: {
type: String,
required: [true, "use must have an password"],
},
});
const User = mongoose.model("User", userSchima);
// const validateUser = (User) => {
// const schema = {
// name: joi.string().min(2).max(15),
// email: joi.types.String().email().required(),
// password: joi.minOfUppercase(1).minOfNumeric(2).noWhiteSpaces().required(),
// };
// return joi.validate(User, schema);
// };
// module.exports = validateUser;
module.exports = User;
create async fun from the controller:
i didn't add the catch method because of to much code here
exports.creatUser = async (req, res) => {
try {
const newUser = await User.create(req.body);
res.status(200).json({
status: "success",
data: {
user: newUser,
},
});
}
thanks from help

Implementing text search with Mongoose

I want to implement text search on my app, and find documents where the field login matches the searched term,
I did the code below and I have no errors but the result in the route is always an empty array, there must be an error somewhere
Model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
created_at: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
display_name: {
type: String,
required: true,
index: true,
},
login: {
type: String,
required: true,
index: true,
},
});
UserSchema.index({ login: "text", display_name: "text" });
User = mongoose.model("users", UserSchema);
User.createIndexes();
module.exports = User;
Route
router.post("/users", async function (req, res) {
const { search } = req.body;
const users = await User.find({ $text: { $search: search } });
res.send(users);
});

How to export multiple Schemas in same file in mongoose

I want to export two schemas in my model js file and I want use in router js file. I have tried this code below.
This is my certification.js file(models)
const mongoose = require('mongoose');
const Schema = mongoose.schema;
const requestCertificationSchema = mongoose.Schema({
userid: { type: String, require: true },
certName: { type: String, require: true },
certType: { type: String, require: true },
examName: { type: String, require: true },
examYear: { type: String, require: true },
examIndex: { type: String, require: true },
reqDate: {type: String, require: true},
state: { type: String, require: true}
});
const requestCertification = mongoose.model("requestCertification", requestCertificationSchema);
module.exports.saveRequest = function (newRequestCertification, callback) {
newRequestCertification.save(callback);
};
const requestStudentstatusSchema = mongoose.Schema({
studentName: { type: String, require: true },
admissionNum: { type: String, require: true },
dateofAdmission: { type: String, require: true },
currentStatus: { type: String, require: true },
description: { type: String, require: true },
});
const requestStudentstatus= mongoose.model("requestStudentstatus", requestStudentstatusSchema);
module.exports = {
requestCertification: requestCertification,
requestStudentstatus: requestStudentstatus
}
This is my certification.js file(routes)
const router = express.Router();
const Certification = require('../models/certification');
const config = require('../config/database');
router.post("/requestCert", function (req, res) {
const newRequest = new requestCertification({
userid: req.body.userid,
certName: req.body.certName,
certType: req.body.certType,
examName: req.body.examName,
examYear: req.body.examYear,
examIndex: req.body.examIndex,
reqDate:req.body.reqDate,
state: req.body.state
});
console.log(newRequest);
Certification.requestCertification.saveRequest(newRequest, function (err, request) {
if (err) {
res.json({ state: false, msg: "Data inserting Unsuccessfull..!" });
}
if (request) {
res.json({ state: true, msg: "Data inserted Successfully..!" });
}
});
});
When I call this url i have show this error! .
ReferenceError: requestCertification is not defined
Change this code to this one in routes/certification.js
const router = express.Router();
const {requestCertification} = require('../models/certification');
const {requestStudentstatus} = require('../models/certification');
const config = require('../config/database');
router.post("/requestCert", function (req, res) {
const newRequest = new requestCertification({
userid: req.body.userid,
certName: req.body.certName,
certType: req.body.certType,
examName: req.body.examName,
examYear: req.body.examYear,
examIndex: req.body.examIndex,
reqDate:req.body.reqDate,
state: req.body.state
});
// console.log(newRequest);
newRequest
.save()
.then(result => {
console.log(result)
res.json({ state: true, msg: "Data inserted Successfully..!" });
})
.catch(error => {
console.log(error)
res.json({ state: false, msg: "Data inserting Unsuccessfull..!" });
})
});
and delete the saveRequest() function in models/certification.js

How to add Schema Dynamically in MongoDB/Mongoose

I want to create a database thats defined by user, each user can have his own flavor of database. So i used strict: false But Now the problem is I cant make the user define the type of each schema under the model
Example
const mongoose = require('mongoose');
const testSchema = new mongoose.Schema({
label: {
required: 'please enter label',
trim: true,
type: String
},
url: {
type: String,
trim: true,
},
settings: {} //User defined
}, {
timestamps: true, strict: false
});
module.exports = mongoose.model('test', testSchema);
In the above case, I want the setting to be defined by user
like,
{
"label": "About Us",
"url": "www.google.com",
"settings": {
"name": {
"type": "String", //Problem is Here, i can't send datatype directly
"required": true
},
"age": {
"type": "Number",
"required": true,
"enum": [10, 12]
}
}
}
So please tell help me, how can i make the user define the type of the schema?
strict: true does not mean You can pass anything to settings field.
It means Your schema format is dynamic - You can have unexpected field names in document that is not defined in schema.
Answer to Your issue:
Seems like You want subdocument, let's make another schema and attach it as type:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const types = Schema.Types;
const testSettingsSchema = new Schema({
name: {
type: types.String,
required: true
},
age: {
type: types.Number,
required: true
enum: [10, 12]
}
},
{
_id : false,
timestamps: false,
strict: false
});
const testSchema = new Schema({
label: {
required: 'please enter label',
trim: true,
type: types.String
},
url: {
type: types.String,
trim: true,
},
settings: {
type: testSettingsSchema,
required: true
}
},
{
timestamps: true,
strict: true
});
module.exports = mongoose.model('test', testSchema);
But to gain more flexibility and avoid creating big test document (since user may push unpredictable big object), create another schema: testSettings that points to test_settings collection and make settings field to be reference:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const types = Schema.Types;
const testSettingsSchema = new Schema({
name: {
type: types.Mixed
},
age: {
type: types.Mixed
}
},
{
collection: 'test_settings',
timestamps: false,
strict: false // tells to mongoose that schema may "grow"
});
mongoose.model('testSettings', testSettingsSchema);
const testSchema = new Schema({
label: {
required: 'please enter label',
trim: true,
type: types.String
},
url: {
type: types.String,
trim: true,
},
settings: {
type: types.ObjectId,
ref: 'testSettings'
default: null
}
},
{
collection: 'tests',
timestamps: true,
strict: true
});
module.exports = mongoose.model('test', testSchema);
create it as:
const Test = mongoose.model('test');
const TestSettings = mongoose.model('testSettings');
app.post('/tests', async (req, res) => {
try {
const testSettings = await TestSettings.create(req.body.settings);
const test = new Test(req.body);
test.settings = testSettings._id;
await test.save();
res.status(201).send({_id: test._id});
}
catch(error) {
res.status(500).send({message: error.message});
}
});
and on request time get it as:
const Test = mongoose.model('test');
app.get('/tests/:id', async (req, res) => {
try {
const test = await Test.findById(req.params.id)
.populate('settings')
.lean();
res.status(200).send(test);
}
catch(error) {
res.status(500).send({message: error.message});
}
});
define your setting field as Schema.Types.Mixed , so you can able to set any kind of fields inside it , like Number , String , Array , Date , Boolean ..etc
const mongoose = require('mongoose');
const testSchema = new mongoose.Schema({
label: {
required: 'please enter label',
trim: true,
type: String
},
url: {
type: String,
trim: true,
},
settings: {
type:Schema.Types.Mixed ,
default: {}
}
}, {
timestamps: true, strict: false
});
module.exports = mongoose.model('test', testSchema);
While saving the document :
app.post('/save',function(req,res){
var setting = {};
setting.age= req.body.age;
setting.name= req.body.name;
var test = new Test({
test.label: req.body.label;
test.url :req.body.url;
test.setting: setting
});
test.save(function(err){
if(err) {return res.json(err);}
else{ res.json({status:'success',message:'saved.'});}
});
});
Just in case someone is having this issue with NestJS and schemaFactory, that's how I solved it:
...
#Schema({ strict: false })
export class Content {}
#Schema()
export class Deadletter extends Document {
#Prop({type: Header})
header: Header;,
#Prop({type: Metadata})
_metadata?: Metadata;
#Prop({type: Content})
content: any;
}
export const deadLetterFullSchema = SchemaFactory.createForClass(Deadletter);

Resources