Mongoose Required true validation not working - node.js

I am trying out nodejs and using mongoose to save a document to mangoDB but my validation for name which I set to required : true is not working. Though I have not set name field the document gets saved. Am i missing an thing in my code
const courseSchema = new mongoose.Schema({
name: {type:String, requried:true},
author: String,
tags: [ String ],
date: Date,
isPublished: Boolean,
price: Number
});
const Course = mongoose.model('Course',courseSchema);
async function createCourse() {
try {
const course = new Course({
author: "Srikanth xyz",
tags: ['express','js'],
isPublished: true,
price: 15
});
const result = await course.save();
console.log(result);
} catch (error) {
console.log("ERROR: " + error.message);
}
}
createCourse();

You might want to double check "requried" to "required"

Here, the spelling of required is wrong. Correct it from
requried to required.

Related

Update multiple documents instance in MongoDb collection with Mongoose. save() is not a function

Mongoose newbe here. I got the following function to update the references (deleting them) in the document Post when a Tag is deleted. When I call my GraphQl API this is what I got:
message": "posts.save is not a function"
The function in my gql resolver:
async deleteTag(root, { id }, context) {
const posts = await Post.find();
const tag = await Tag.findById(id);
if(!tag){
const error = new Error('Tag not found!');
error.code = 404;
throw error;
}
posts?.forEach(async (post) => {
await post.tags.pull(id);
})
await posts.save()
await Tag.findByIdAndRemove(id);
return true;
}
This is the Post model:
const PostSchema = new Schema({
body: {
type: String,
required: true
},
tags: {
type: [Schema.Types.ObjectId],
ref: 'Tag',
required: false
},
});
and this is the Tag model:
const TagSchema = new Schema(
{
name: {
type: String,
required: true
},
},
{ timestamps: true }
);
Looks like I can't call the method save() on the array of objects returned by Exercise.find()
I used the same pattern in other functions, the difference is that there I used .findById()
Any solution? Advice and best practice advide are super welcome.
You have to save the posts individually:
posts?.forEach(async (post) => {
await post.tags.pull(id);
await post.save();
})
Or use Model.updateMany() combined with the $pull operator.
FWIW, you should probably limit the number of matching Post documents by selecting only documents that have the specific tag listed:
await Post.find({ 'tags._id' : id });

create mongoose schema with array of objects

Even though the question have been asked numerous time none of the answers have any idea to help me .
This is my mongoose Schema
const mongoose = require('mongoose')
const { Schema } = mongoose;
const recipeSchema = new Schema({
name: { type: String, required: true },
description: { type: String, required: true },
imagePath: { type: String, required: true },
ingredients:[
{
name:{type:String, required:true},
amount:{type:Number,required:true }
}
]
})
module.exports = mongoose.model("Recipe",recipeSchema);
what i need is to get the data from angular and store it to my database using node
const Recipe = require('../models/recipe.model');
const recipeCtrl={};
recipeCtrl.CreateRecipeServer =async(req, res, next)=>{
if(!req.file) {
return res.status(500).send({ message: 'Upload fail'});
}
else {
let ingredientArray=new Array()
ingredientArray.push(req.body.ingredients)
req.body.imageUrl = 'http://192.168.0.7:3000/images/' + req.file.filename;
const recipe=new Recipe({
name:req.body.name,
description:req.body.description,
imagePath:req.body.imageUrl,
ingredients:[
{
name:ingredientArray,
amount:ingredientArray }
]
});
await recipe.save();
}
Everything except the ingredients array works perfectly/as i require.
I am getting the ingredients as an array from formdata so it have to be JSON.stringfied inorder to append with the form. So what i am getting at backend is string . eg
**[{"name":"dasdasd","amount":2},{"name":"fsfsd","amount":2},{"name":"sdfsdgd","amount":3}]**
this is a string. Any ideas on how to convert it and store to database
use JSON.parse and choose first element of that
JSON.parse(data)[0]

can't find documents by id

so I'm trying to update a document but it just doesn't work with _id but if I filter with "name" it works
I also tried with FindByID and it returns null
using mongoose version 5.0.18
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mongo-exercises')
.then(() => console.log('connected to database :)'))
.catch(reason => console.log('Can not connect to data base',reason));
const courseSchema = mongoose.Schema({
name: String,
author: String,
tags: [String],
Date: { type:Date,default:Date.now },
isPublished: Boolean,
price: Number
});
const Course = mongoose.model('courses',courseSchema);
async function updateCourse(id){
let result = await Course.update({_id: id},{
$set:{
author: "some random dude",
isPublished: true
}
});
console.log('result: ',result);
}
updateCourse('5a68fde3f09ad7646ddec17e');
try using
//make sure you import Course module
Course.findByIdAndUpdate(id)
.then(response=>{
})
.catch(err=>{
})
I just had to re-import the collection without _id so it can regenerate them

Mongoose: How to ensure row should be unique only if value of property is equal to something?

I have a simple Mongoose schema that looks like this:
const fruitSchema = new mongoose.Schema({
name: {
type: String
required: true
},
type: {
type: String,
required: true
}
})
schema.index({ name: 1, type: 1 }, { unique: true })
const Fruit = mongoose.model('Fruit', fruitSchema)
Under normal circumstances, the table is unique on (name, type) so the user is able to store multiple types for each fruit. However, I want to allow the user to only store one type if the name of the Fruit is apple.
So basically, I want make the following check before a save is made:
if (newFruit.name === 'apple') {
if (Fruit.find({ name: 'apple' }).count >= 1) throw new Error()
}
One way of enforcing this is to execute the code above in a pre-save hook. But, I was just wondering if there would be an in-built way to specify this within the Mongoose schema itself?
Thanks for the help!
SOLUTION:
In addition to the solution kindly provided by #SuleymanSah below, I thought I'd post what I finally ended up using.
const fruitSchema = new mongoose.Schema({
fruit: {
type: String
required: true,
async validate(name) {
if (name === 'apple') {
let fruit
try {
fruit = await Fruit.findOne({ name })
} catch (e) {
console.error('[Fruit Model] An error occurred during validation.')
console.error(e)
throw e // rethrow error if findOne call fails since fruit will be null and this validation will pass with the next statement
}
if (fruit) throw new Error(`A fruit for ${name} already exists.`)
}
},
type: {
type: String,
required: true
}
})
schema.index({ fruit: 1, type: 1 }, { unique: true })
const Fruit = mongoose.model('Fruit', fruitSchema)
You can use custom validators like this:
const schema = new mongoose.Schema({
name: {
type: String,
required: true
},
type: {
type: String,
required: true,
validate: {
validator: async function() {
if (this.name === "apple") {
let doc = await this.constructor.findOne({ name: "apple" });
return Boolean(!doc);
}
},
message: props => "For apple only one type can be."
}
}
});
You can do it like this with express, for example when saving a new fruit:
const express = require("express");
const router = express.Router();
router.post("/save", (req, res) => {
const { name, type } = req.body; //this is coming from front-end
Fruit.findOne({ name }).then(fruit=> {
if (fruit) return res.status(400).json({ name: "This fruit already exist!" });
This will prevent any fruit with same name from saving to database
i think this is similar query
you need to add index and set it to unique
restrict to store duplicate values in mongodb

Mongoose ODM - failing to validate

I'm trying to perform validation without saving. The API documentation shows that there's a validate method, but it doesn't seem to be working for me.
Here's my schema file:
var mongoose = require("mongoose");
var schema = new mongoose.Schema({
mainHeading: {
type: Boolean,
required: true,
default: false
},
content: {
type: String,
required: true,
default: "This is the heading"
}
});
var moduleheading = mongoose.model('moduleheading', schema);
module.exports = {
moduleheading: moduleheading
}
..and then in my controller:
var moduleheading = require("../models/modules/heading").moduleheading; //load the heading module model
var ModuleHeadingo = new moduleheading({
mainHeadin: true,
conten: "This appears to have validated.."
});
ModuleHeadingo.validate(function(err){
if(err) {
console.log(err);
}
else {
console.log('module heading validation passed');
}
});
You may notice that the parameters I'm passing in are called 'mainHeadin' and 'conten' instead of 'mainHeading' and 'content'. However, even when I do the call to validate() it never returns an error.
I'm obviously using validate incorrectly - any tips? The mongoose documentation is really lacking!
Thanks in advance.
Your validation will never fail because you've created default attributes for both mainHeading and content in your schema. In other words, if you don't set either of those properties, Mongoose will default them to false and "This is the heading" respectively - i.e. they will always be defined.
Once you remove the default property, you'll find that Document#validate will work as you initially expected. Try the following for your schema:
var schema = new mongoose.Schema({
mainHeading: {
type: Boolean,
required: true
},
content: {
type: String,
required: true
}
});

Resources