How to validate Array of Objects in Mongoose - javascript

I need to validate the array of objects in my schema
Schema:
user: [{
name: String,
Age: String,
Contact: Number
}]
How to validate name, age and contact.

I assume your user array is inside another schema.
Let's say we have a Course model with users like this:
const mongoose = require("mongoose");
const courseSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
users: [
{
name: { type: String, required: [true, "Name is required"] },
age: { type: Number, required: [true, "Age is required"] },
contact: { type: Number, required: [true, "Contact is required"] }
}
]
});
const Course = mongoose.model("Post", courseSchema);
module.exports = Course;
To validate this in a post route you can use mongoose model validateSync method:
const Course = require("../models/course");
router.post("/course", async (req, res) => {
const { name, users } = req.body;
const course = new Course({ name, users });
const validationErrors = course.validateSync();
if (validationErrors) {
res.status(400).send(validationErrors.message);
} else {
const result = await course.save();
res.send(result);
}
});
When we send a requset body without required fields like age and contact:
(you can also transform validationErrors.errors for more useful error messages.)
{
"name": "course 1",
"users": [{"name": "name 1"}, {"name": "name 2", "age": 22, "contact": 2222}]
}
The result will be like this:
Post validation failed: users.0.contact: Contact is required, users.0.age: Age is required

It will be similar to the usual validation but inside an array, you need to make a validator function as so:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//the custom validation that will get applied to the features attribute.
var notEmpty = function(features){
if(features.length === 0){return false}
else {return true};
}
var CarSchema = new Schema({
name: {
type: String,
required: true,
},
features: [{
type: Schema.ObjectId,
ref: Feature
required: true; //this will prevent a Car model from being saved without a features array.
validate: [notEmpty, 'Please add at least one feature in the features array'] //this adds custom validation through the function check of notEmpty.
}]
});
var FeatureSchema = new Schema({
name: {
type: String,
required: true //this will prevent a Feature model from being saved without a name attribute.
}
});
mongoose.model('Car', CarSchema);
mongoose.model('Feature', FeatureSchema);

By using type key/property:
var breakfastSchema = new Schema({
eggs: {
type: Number,
min: [6, 'Too few eggs'],
max: 12
},
bacon: {
type: Number,
required: [true, 'Why no bacon?']
},
drink: {
type: String,
enum: ['Coffee', 'Tea'],
required: function() {
return this.bacon > 3;
}
}
});

Related

Pushing object to triple nested array in Mongoose

I am trying to figure out how to access and push an object into a triple nested array while using mongoose.
My idea is to divide a blog post into an array of chapters, where each has their own array of pages. Each page will have a title, image and body.
Story schema (parent document)
const mongoose = require('mongoose')
const pageSchema = require('./pageModel')
const storySchema = mongoose.Schema({
storyTitle: {
type: String,
required: [true, 'Title required.']
},
storyAuthor: {
type: String,
required: [true, 'Author required.']
},
storyImage: {
type: String,
required: true,
},
chapters: [{
chapterTitle: {
type: String,
//required: [true, 'Title required.']
},
chapterSummary: {
type: String,
// required: [true, 'Summary required.']
},
pages: [pageSchema]
}]
})
module.exports = mongoose.model('Story', storySchema)
the Page Schema
const mongoose = require('mongoose')
const pageSchema = mongoose.Schema({
pageTitle: {
type: String,
required: [true, 'Title required.']
},
pageBody: {
type: String,
},
pageImage: {
type: String,
}
})
module.exports = pageSchema;
Simple ops
const mongoose = require('mongoose')
const Story = require('./storyModel')
const Page = require('./pageModel')
const test = new Story({
storyTitle: 'Test',
storyAuthor: 'Myself',
storyImage: 'test',
});
console.log(test);
test.chapters.push({
chapterTitle: 'chapter 1',
chapterSummary: 'let us see',
})
const first = {
pageTitle: 'A page',
pageImage: 'image',
pageBody: 'A body'
}
console.log(test)
//test.chapters[0].pages[0].push(page)
test.chapters[0].pages.push(first)
console.log(test)
When I log each step, the parent is correctly made, and I am able to append a chapter to the chapters array. But when I the first object, the change isn't visible.
If I log test.chapters, the pages array shows pages: [ [Object] ]
And if I log test.chapters.pages, I just see 'undefined'.
Any suggestions and critique is appreciated.

How to insert ref objectId in nodejs?

Main Model
{
name: {
type: String,
trim: true,
required: true
},
carModels: [{
type: ObjectId,
ref: 'CarModel'
}]
}
Second Model
{
name: {
type: String,
trim: true,
required: true
},
carModels: [
{
type: ObjectId,
ref: 'CarModel'
}
]
},
Third Model
{
name: {
type: String,
trim: true,
required: true
}
},
Here i am trying to insert the data like this
{
"name": "test",
"phoneNumber": "0123456789",
"email": "m#m.com",
"carMakes": [{
"name": "BMW",
"carModels": [{
"_id": "some id"
}]
}]
}
and it giving me error like
carMakes.0: Cast to [ObjectId] failed for value
here is the create function
export const create = async data => {
const result = await Booking(data).save();
return result;
};
Can anyone tell what I am missing here ..i am learning nodejs
i think the problem is with the _id that you're passing to carModel and since you set the type to ObjectId it has to be in a valid format "either 12 byte binary string, or a 24 hex byte string" and "some id" is not the valid one if you're sending that.
you can check if your id is valid with isValidObjectId() function.
or you can easily generate an ObjectId:
var mongoose = require('mongoose');
var id = new mongoose.Types.ObjectId();

How to query a mongo document using mongoose?

MongoDB documents contain an array of objects and what is the best way to query those documents if I want to find and remove an object from an array with some specific value;
Here is an example of the document schema
const mongoose = require("mongoose");
const LibrarySchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
},
books: [
{
type: new mongoose.Schema({
bookName: {
type: String,
required: true,
},
chapterReading: {
type: Number,
default: 1,
required: true,
},
}),
},
],
});
const Library = mongoose.model("Library", LibrarySchema);
exports.Library = Library;
If I want to find and remove a book with some bookName
Use $pull
Example :
Library.update({}, { $pull: { books: { bookName: "Yourbookname" } } })

Push To Mongoose Subdocuments

Hello I am creating a series of groupings describing the roles certain users are taking within the context of helping a client. The object in the Prospect model is called caseworkers. In caseworkers is a series of arrays for the different types of roles done. The equation is to allow the user to push his info as a subdocument called CaseWorker. Basically creating an object with 6 arrays that users can push to. Ive tried a few things and settled on Subdocuments. Any help would be awesome.
Here is my code:
const mongoose = require("mongoose");
const CaseWorker = require("./CaseWorker");
const ProspectSchema = mongoose.Schema({
caseWorkers: {
originators: [CaseWorker.schema],
loanProcessors: [CaseWorker.schema],
documentProcessors: [CaseWorker.schema],
upsells: [CaseWorker.schema],
primaryReso: [CaseWorker.schema],
taxPreparers: [CaseWorker.schema],
secondaryReso: [CaseWorker.schema],
}
module.exports = mongoose.model("prospect", ProspectSchema);
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const CaseWorkerSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
role: { type: String },
resoCred1: { type: String },
resoCred2: { type: String },
reminders: [
{
_id: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
userReminded: { type: mongoose.Schema.Types.ObjectId },
reminderDate: { type: Date },
reminderDueDate: { type: Date },
status: { type: String },
daysTilDue: { type: Number },
id: { type: String },
text: { type: String },
clientId: { type: mongoose.Schema.Types.ObjectId, ref: "Prospect" },
},
],
});
module.exports = mongoose.model("caseWorker", CaseWorkerSchema);
router.put("/:_id/caseWorkers/loanProcessors", auth, async (req, res) => {
const prospect = await Prospect.findByIdAndUpdate(req.params._id, {
"$push": {
"loanProcessors": {
"caseWorker": {
"name": req.body.name,
"email": req.body.email,
"role": req.body.role,
"resoCred1": req.body.resoCred1,
"resoCred2": req.body.resoCred2,
},
},
},
});
res.json(prospect);
console.log(prospect);
});
In your approach when updating the document you put caseWorker under loanProcessors but it's declared in the schema the other way around.
To update a nested object you have to use the dot notation to reference the field.
Don't forget to put the object key that represent the field as a string like this "caseWorkers.loanProcessors", because caseWorkers.loanProcessors is an invalid object key in javascript
"$push": {
"caseWorkers.loanProcessors": {
"name": req.body.name,
"email": req.body.email,
"role": req.body.role,
"resoCred1": req.body.resoCred1,
"resoCred2": req.body.resoCred2,
},
},

Adding Array To Mongo via AJAX Call and Mongoose

I'm trying to update a document in a mongo database with information from a form, with all the form going into a field which is an array. At the moment I can't get it to update a document, only create a new one, but more pressingly I can't get the information from the form into the array.
Here is my schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const WorkoutSchema = new Schema({
day: {
type: Date,
default: Date.now
},
exercises: [
{
type: String,
trim: true,
required: "Exercise type is required"
},
{
name: String,
trim: true,
required: "Exercise name is required"
},
{
duration: Number
},
{
weight: Number
},
{
reps: Number
},
{
sets: Number
},
{
duration: Number
},
{
distance: Number
}
]
});
const Workout = mongoose.model("Workout", WorkoutSchema);
module.exports = Workout;
And here is my API route. I've included the results of console.logs below it so you can see the information that is getting passed.
app.put("/api/workouts/:id", (req, res) => {
console.log("api body: " + JSON.stringify(req.body));
console.log("body is " + typeof req.body);
var body = JSON.stringify(req.body);
// body = body.split("{")[1];
// body = body.split("}")[0];
// body = "["+body+"]";
console.log(body);
Workout.create({exercises: `${body}`})
.then(Workout => {
res.json(Workout);
})
.catch(err => {
res.json(err);
});
});
api body: {"type":"resistance","name":"Test Press","weight":100,"sets":5,"reps":6,"duration":10}
body is object
{"type":"resistance","name":"Test Press","weight":100,"sets":5,"reps":6,"duration":10}
In the database I get exercises as an array with one element - the above object - instead of a series of key/value pairs. I've tried a lot of things, but this is as close as I get to what I'm trying to do.
Can anyone see where I've gone wrong?
This turned out to be a basic syntax error which came about because one of my keys was "type". The issue is in the syntax of the exercises array, the model should look like this:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const WorkoutSchema = new Schema({
day: {
type: Date,
default: Date.now
},
exercises: [{
type: {
type: String,
trim: true,
required: "Exercise type is required"
},
name: {
type: String,
trim: true,
required: "Exercise name is required"
},
duration: {
type: Number,
required: "Duration is required"
},
weight: {
type: Number
},
reps: {
type: Number
},
sets: {
type: Number
},
distance: {
type: Number
}
}]
});
const Workout = mongoose.model("Workout", WorkoutSchema);
module.exports = Workout;

Categories

Resources