How to validate only when param is exist in express-validator - javascript

I'm building a update user method in express. The data is dynamic.
Like: I have 2 field that can be updated: name, phone_number,
In 1 request, the data can be only phone_number or name or both.
I use express-validator to validate data:
update: [
check('name').trim().isLength({ min: 3, max: 30 }).bail(),
(req, res, next) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.json({ code: 400, message: 'invalid data' })
next()
},
]
When I want to update only phone_number, the data won't have name.
I want to validate name only when data has name. How can I solve it?

What you're looking for is optional.
This will skip validations when the value of name is not set (undefined):
check('name').optional().trim().isLength({ min: 3, max: 30 }),
But you can also skip them when the value is null or undefined, like this:
check('name').optional({ nullable: true }).trim().isLength({ min: 3, max: 30 }),
And finally, if you'd like to skip validations when the value is null, undefined, false, zero or an empty string, you can do this:
check('name').optional({ checkFalsy: true }).trim().isLength({ min: 3, max: 30 }),

Related

MongoBulkWriteError: E11000 duplicate key error collection

So, I read all the answers to my problem on Stackoverflow and other websites and none of the solutions have helped me.
The following is the exact error -
MongoBulkWriteError: E11000 duplicate key error collection: test.users index: email_1 dup key: { email: "aaaaaaa#gmail.com" }
Below is my schema -
import mongoose from "mongoose";
const UserSchema = new mongoose.Schema(
{
firstName: {
type: String,
required: true,
min: 2,
max: 50,
},
lastName: {
type: String,
required: true,
min: 2,
max: 50,
},
email: {
type: String,
required: true,
max: 50,
unique: true,
},
password: {
type: String,
required: true,
min: 5,
},
picturePath: {
type: String,
default: "",
},
friends: {
type: Array,
default: [],
},
location: String,
occupation: String,
viewedProfile: Number,
impressions: Number,
},
{
timestamps: true,
}
);
const User = mongoose.model("User", UserSchema);
export default User;
I tried dropping the index email_1 that is causing the problem from the website (graphically).
However, that doesn't seem to do anything. And email_1 is created every time I try to run my server.
Also, I checked my database and found that there is no duplicate 'aaaaaaa#gmail.com' email in my database. I manually uploaded my some starting data to my db for testing purposes of the app I am trying to build.
I am reluctant on deleting my entire database because IF this were to happen to me in production, deleting the entire db would not be an option. I want to fix the issue.
Any help will be appreciated. Thank you.
Right so, I figured out the error.
Whenever you're working with "sample data", make sure you're complying to the restrictions you set in your schema.
In my case, I was trying to add the same sample data to my db every time I ran the server. I essentially forgot to comment out the part of my code where I was inserting my sample data to my db. All I had to do was comment out that part of the code and the server was live again!

Unexpected MongoServerError 11000 (duplicate) for a field that is NOT even declared in schema

I'm developing an online store Node.js REST API with Mongoose (MongoDB), which I'm new to. I decided to test the orders service and saw that after I had made 1 successful order (so it worked once), it sent me a duplicate key error for the next one, for a key 'name' with value 'null', of the order.products collection that is an Array, and not a kvp object.
I should note that nowhere in my code is 'products.name' mentioned.
ERROR:
MongoServerError: E11000 duplicate key error collection: store.orders index: products.name_1 dup
at {...}{
key: { products.name: null }
index: 0,
code: 11000,
keyPattern: { 'products.name': 1 },
keyValue: { 'products.name': null },
[Symbol(errorLabels)]: Set(0) {}
}
when the error is handled, this message is received and it makes no sense:
{ "message": "Order with products.name "null" already exists" }
Order schema:
const schema = new Schema({
userId: {
type: Types.ObjectId,
ref: 'User'
},
address: {
type: addressSchema,
required: true
},
products: {
type: [orderProductSchema],
required: true,
validate: nonEmptyArray
},
status: {
type: Number,
validate: inCollection(Object.values(ORDER_STATUS))
},
price: { type: Number, required: true, min: 0 }
}, { timestamps: true });
don't bother with the validators or the address/status/user/price, it has nothing to do with them; what is more, nothing is specified as unique: true
As you can see, the 'products' field is just an array of products, no 'name' is declared
orderProductSchema:
const schema = new Schema({
product: {
_id: { type: Types.ObjectId, required: true },
name: {
type: String,
required: true,
maxLength: 250
},
displayImage: String,
price: { type: Number, required: true, min: 0 }
},
quantity: {
type: Number,
required: true,
validate: isInteger,
min: 1
},
}, { _id: false });
I have a 'name' field here, but it's just the name of a product. The error is thrown even when the names are unique.
Orders service:
// get data and format it to fit the Order model
console.dir(products); // --> all is how it's expected to be in the schema
return await Order.create({
userId,
address,
products,
status: ORDER_STATUS.AWAITING_CONFIRMATION,
price: totalOrderPrice
});
It seems to me that this is some weird MongoDB behaviour/specification that I missed. If someone has any idea what could cause the problem - please help.
I tried removing all parts such as other fields and validations to see if they might've caused the problem but that was not the case. I thought maybe I had formatted the object I send to the database wrong, but I console.log-ed it and it was fine ({products: Array})
Thanks to #user20042973 and #MTN I saw that my 'orders' database had index 'products.name' (no idea how it got there).. I just removed the index and the problem is solved.

sort mongodb data based on array express react

i have record in mongoose which kinda look like this(demo) -
{
name:"son",
email:"final#gmail.com",
score:[40,100,30,5]
}
my model is -
const uModel = new Schema({
name: {
type: String,
required: true,
max: 20,
},
email: {
type: String,
required: true,
unique: true,
max: 50,
min: 6
},
password: {
type: String,
required: true,
min: 6
},
profile:{
type: String,
default: ''
},
score:{
type: Array
}})
and here is my post method in express -
const getAllData = (req, res)=>{
userModel.find().sort({score: -1})
.then(user =>{
res.status(200).json(user)
})
.catch(err=>{
res.status(200).json(err)
})}
i have a dashboard and i want to show user with highest score(score is dynamic, changes all the time)
what i want is to sort score array(descending order ) and then sort user based on highest score(descending order). two thing what i want but i have no idea how to do it.
after sorting 0 index of score array should have the higher value and last index lowest.
find().sort({}) does not work for me.
is it possible or should i change my strategy if i should change then what could be better one ??
thanks in advance

Mongoose - findByIdAndUpdate runValidators based on other properties

I'm trying to update a model with the following query:
Model.findByIdAndUpdate(id, { min_age: 18, max_age: 24 }, { new: true, runValidators: true, setDefaultsOnInsert: true })
The thing is that I need to validate that those values aren't opposed to each other like the following query
Model.findByIdAndUpdate(id, { min_age: 24, max_age: 18 }, { new: true, runValidators: true, setDefaultsOnInsert: true })
the schema I built so far is this one:
let ageSchema = new mongoose.Schema({
min_age: {
type: Number,
min: 18,
max: 80,
required: true,
validate: {
validator: function(value) {
return this.max_age >= value
},
message: 'min_age has to be lower than or equal to max_age'
}
},
max_age: {
type: Number,
min: 18,
max: 80,
required: true,
validate: {
validator: function(value) {
return this.min_age <= value
},
message: 'max_age has to be greater than or equal to min_age'
}
}
})
The validation works for creating the model, but unfortunately, it doesn't work for updating the data.
When I'm creating the model, the this keyword refers to the model, which gives me access to other properties on this model.
When I'm updating the model, the this keyword refers to global, which doesn't give me access to other properties on this model.
Is there any practical way to validate those properties based on other properties during an update?
Thanks.

hapi/joi descriptive error in nested validation

I'm trying to use https://github.com/hapijs/joi to do nested array of object validation, my code as below (playground here)
const Joi = require("#hapi/joi")
const schema = Joi.array().required().items(
Joi.object().required().keys({
name: 'room_range',
value: Joi.object({
min: Joi.number().required(),
max: Joi.number().min(Joi.ref('min')).required()
})
}),
Joi.object().required().keys({
name: 'anything',
value: Joi.object({
min: Joi.number().required(),
max: Joi.number().min(Joi.ref('min')).required()
})
}),
)
const result = schema.validate([
{
name: 'room_range',
value: {
min: 'dddd',
max: 2
}
},{
name: 'anything',
value: {
min: 1,
max: 2
}
}
]);
console.log('error: ', result.error);
I got this error
exports.ValidationError: "value" does not contain 1 required value(s)
Then the frontend will not be able to know by the error msg.
You could try this:
value: Joi.object({
min: Joi.number().required().error(() => 'error message here'),
max: Joi.number().min(Joi.ref('min')).required().error(() => 'error message here'),
}),
If you need an error message on the object or array you should be able to do the same thing just on the object.
value: Joi.object({
min: Joi.number().required(),
max: Joi.number().min(Joi.ref('min')).required(),
}).required().error(() => 'error message here'),
The 'error()' takes either an instance of error or a function.
https://hapi.dev/family/joi/?v=16.1.4#anyerrorerr
Maybe you can find more usefull info here:
Node.js + Joi how to display a custom error messages?
Hope this helps as I'm not exactly sure of what you are asking for.

Categories