How to solve Mongoose Error on Validation - node.js

I am building an API that allows the user to log certain data into the database(MongoDB) The problem is I keep getting the following errors:
UnhandledPromiseRejectionWarning: ValidationError: item validation failed: productName: Path `productName` is required.
here is my schema :
const mongoose= require('mongoose');
const Schema = mongoose.Schema;
//create Schema
const ItemSchema = new Schema({
productName : {
type : String,
required:true
} ,
description : {
type :String,
default:true
},
supplier : {
type :String,
default:true
},
price : {
type :Number,
default:true
},
date : {
type :Date,
default:Date.now
}
});
module.exports=Inventory=mongoose.model('item',ItemSchema,'inventory');
Here is the submit post route:
const express= require('express');
const router = express.Router();
//Items model
const Inventory = require('../../../models/Inventory');
router.post('/',(req,res)=>{
const newInventory= new Inventory({
productName:req.body.productName,
description:req.body.description,
supplier:req.body.supplier,
price:req.body.price,
});
newInventory.save().then(item=>res.json(item))
});
I can't figure out why it's throwing a validation Error!

This was the step I took to resolve the problem
first, i checked what i was getting from my req.body
const express= require('express');
const router = express.Router();
//Items model
const Inventory = require('../../../models/Inventory');
console.log(req.body) //checking for content of req.body
router.post('/',(req,res)=>{
const newInventory= new Inventory({
productName:req.body.productName,
description:req.body.description,
supplier:req.body.supplier,
price:req.body.price,
});
newInventory.save().then(item=>res.json(item))
});
I got an empty object { }, this means I wasn't getting any request in the first place. Testing with Postman, I changed the option from "form data" to :
x-www-form-urlencoded
this filled my req.body with data and the error disappeared !

Related

Mongoose MongoError : 11000

I sent a create post signal through Postman. a once time, the post signal was a successfully. but next time it was failed . error message is like this.
Error creating new record : {
"driver": true,
"name": "MongoError",
"index": 0,
"code": 11000,
"keyPattern": {
"RoutineParts.userId": 1
},
"keyValue": {
"RoutineParts.userId": null
}
}
i cant understand the error message,
my post code and user model code is like that ,
// it's post code.
router.post('/',(req,res)=>{
const newRecord = User ({
username : req.body.username,
email : req.body.email,
password : req.body.password
})
newRecord.save((err,docs)=>{
if(!err) {
res.send(docs)
}else {
console.log('Error creating new record : ' + JSON.stringify(err,undefined,2))
}
})
})
// it's user model
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema(
{
username : {type:String},
email: { type: String, required: true},
password: { type: String, required: true, trim: true },
created_at : { type: Date, default: Date.now },
updated_at : { type: Date, default: Date.now },
}
)
const User = mongoose.model('User', userSchema);
module.exports = { User }
i can't understand. In fact 'RoutineParts' is a one of model, but i didn't write user's documents. and, controller path is corrected in app.js
how can i solve it?
it's RoutineParts model
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema(
{
routine_name : {type:String},
userId : { type: String, required: true},
exercise_name : { type: String},
order : { type: Number},
}
)
const RoutineParts = mongoose.model('RoutineParts', userSchema);
module.exports = { RoutineParts }
and it's app.js contents
// Connecting data to the MongoDB through Mongoose
require('./db')
const express = require('express')
const app = express()
const PORT = 5000
const bodyParser = require('body-parser')
const userRoute = require('./controller/user')
const routineRoute = require('./controller/routine')
const RP_Route = require('./controller/routineParts')
const EX_Route = require('./controller/excersise')
app.use(bodyParser.json())
app.get("/", function (req, res) {
res.status(201).send("<h1>Hey guys! Hello World !!</h1>");
});
app.listen(PORT, function () {
console.log(`start express server on port ${PORT}`);
});
app.use('/Users', userRoute)
app.use('/Routine', routineRoute)
app.use('/Excersise', EX_Route)
app.use('/RoutineParts', RP_Route)
What's going on
I took a look at your full code. The only real problem, which also fits with the error message you are seeing, is the following :
In your ./models/routineParts.js you've set a unique field. In your case userid. E.g. if your create a new routineParts document with userid "AAA" you can not create another document with the same userid "AAA". In short this means, every user can only create 1 single routineParts document.
The first time you did a POST request to your route localhost:5000/RoutineParts it created the first routineParts document. After that, every request will fail, because it already created 1 routineParts document. ( Read here about unique index with mongoose )
See your ./controller/routineParts.js . If you try to do the same request with a different userid it should work.
How to fix
1 : Remove unique: true from your ./models/routineParts Schema.
2 : ⚡ Drop the index . Mongoose most-likey already registered this index and you have to drop it specifically. Otherwise it will always treat the userid field as unique.
3 : You are still in development, so it shouldn't hurt to also drop the RoutineParts collection.
4 : Restart the app and try to hit the POST localhost:5000/RoutineParts endpoint a couple of times. You now should be able to create multiple routineParts documents under the same user.
How to drop the index
That's a different story. This question should help you with that. They are also using mongoose. If your are using the latest version of mongoose there is a method called cleanIndexes. Use this method after you've removed the unique:true from your model.
For solve this isuse you must remove index duplicate email_1 from index menu

Typeerror : 'todo.find is not a function'

I'm adding a new Model to my app but it's failing with "TypeError: todo.find is not a function". I have another model, Items, that are set up in the same way and are working fine. Things seem to be failing in the route but it works if I hook it up to the Item model. don't know what's going on wrong?
model
var mongoose = require('mongoose');
var todoSchema = new mongoose.Schema({
name: {
type: String,
required: true,
maxlength:32,
trim:true
}
},{timestamps:true}
)
module.exports = mongoose.model('Todo',todoSchema)
auth.js//route
var express = require('express');
var router = express.Router();
const {getAllTodos} = require('../controller/auth');
router.post('/getalltodo',getAllTodos);
module.exports = router;
auth.js//controller
const Todo = require('../model/todo');
exports.getAllTodos = (req,res) =>{
const todo = new Todo(req.body)
todo.find().exec((err,todo) =>{
if(err || !todo){
return res.status(400).json({
error : 'No Todos found'
})
}
res.json(todo);
})
}
You have a problem in your getAllTodos middleware. You try to do this:
const todo = new Todo(req.body); // returns a Document
todo.find()... // a Document doesn't have a 'find' method
You don't have a find method on a Document but you do have one on a Model.
Do this instead:
Todo.find()...
Look at the docs if you need more info.

Why won't my rest api post request save my array in my mongodb database

I'm trying to learn to make an api with node.js For my backend i'm using mongodb and I'm using mongoose as ORM. I created my user model as follows.
// User.js
var mongoose = require('mongoose');
var UserInfoSchema = new mongoose.Schema({
street: String,
housenumber: String,
city: String,
postcode: String,
bus: String,
});
var UserFullSchema = new mongoose.Schema({
name: String,
email: String,
password: String,
Userinfo: [UserInfoSchema]
});
mongoose.model('User', UserFullSchema);
const User = mongoose.model('user',UserFullSchema)
module.exports = User;
My Usercontroller looks like this:
// UserController.js
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
router.use(bodyParser.urlencoded({ extended: true }));
var User = require('./User');
// CREATES A NEW USER
router.post('/', function (req, res) {
User.create({
name : req.body.name,
email : req.body.email,
password : req.body.password,
Userinfo: [{
street : req.body.street,
housenumber : req.housenumber,
city : req.body.city,
postcode : req.body.postcode,
bus : req.body.bus,
}]
},
function (err, user) {
if (err) return res.status(500).send("There was a problem adding the information to the database.");
res.status(200).send(user);
});
});
For some reason when I call my API using postman to test I can never seen to be able populate my array. Did I do something wrong?
Picture as example:
Page I checked before posting:
Page I checked
You definition where you want to have a cross reference by the _id seems off.
Userinfo: [UserInfoSchema]
should probably be:
Userinfo: [{ type: mongoose.Schema.Types.ObjectId, ref: 'UserInfoSchema' }]
This way you would have a cross reference by _id. Btw not a fan of those names. It reads very confusing. I assume these are just for testing.
Now, from a simple express kinda perspective Are you even referencing the values from req.body?
Shouldn't the values be req.body.Userinfo.street?
Userinfo: [{
street : req.body.Userinfo.street, //
housenumber : req.body.Userinfo.housenumber,
city : req.body.Userinfo.city,
postcode : req.body.Userinfo.postcode,
bus : req.body.Userinfo.bus,
}]
On a side note, you can send Full fledged JSON using postman, go to the raw tab and select application/json from the dropdown
I dont know what the problem was but I was able to resolve the issue by splitting my models in 2 different files.
I made a new file called Userinfo like this:
// Userinfo.js
var mongoose = require('mongoose');
var UserInfoSchema = new mongoose.Schema({
street: String,
housenumber: String,
city: String,
postcode: String,
bus: String,
});
module.exports = UserInfoSchema;
There I exported my whole Schema
And called that Schema in my User model file like this:
// User.js
var Userinfo = require('../userinfo/Userinfo.js');
var mongoose = require('mongoose');
var UserFullSchema = new mongoose.Schema({
name: String,
email: String,
password: String,
Userinfo: [Userinfo]
});
const User = mongoose.model('user',UserFullSchema)
module.exports = User;
And my controller looked like this:
// UserController.js
var express = require('express');
var mongoose = require('mongoose');
var router = express.Router();
var bodyParser = require('body-parser');
router.use(bodyParser.urlencoded({ extended: true }));
var User = require('./User');
router.post('/', function (req, res) {
User.create({
name : req.body.name,
email : req.body.email,
password : req.body.password,
Userinfo: [{
street : req.body.Userinfo.street,
housenumber : req.body.Userinfo.housenumber,
city : req.body.Userinfo.city,
postcode : req.body.Userinfo.postcode,
bus : req.body.Userinfo.bus,
}]
},
function (err, user) {
if (err) return res.status(500).send("There was a problem adding the information to the database.");
res.status(200).send(user);
console.log(req);
});
});
After that I used postman as before and voila issue resolved:

Populating the cart doesnt work (mongoose)

I have been trying to populate cart products in user's cart. Below is my code.
const express = require('express')
const mongoose = require('mongoose')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({extended:false}))
const Schema = mongoose.Schema;
var userSchema = new Schema({
userName : {
type : String,
default : 'UserName'
},
cart : [ { type : mongoose.Schema.Types.ObjectId , ref : 'Cart' } ]
})
var cartSchema = new Schema({
productNameofUser : {
type : String,
default : 'Product'
}
})
var UserModel = mongoose.model('User' , userSchema)
var CartModel = mongoose.model('Cart' , cartSchema)
app.get('/users',(req,res)=>{
UserModel.find().populate('cart').exec((err,result)=>{
res.send(result)
})
})
app.post('/createUser',(req,res)=>{
let newUser = new UserModel()
newUser.save((err,result)=>{
console.log(result)
res.send(result)
})
})
app.get('/products',(req,res)=>{
CartModel.find((err,result)=>{
res.send(result)
})
})
app.post('/createProduct',(req,res)=>{
let newProduct = new CartModel()
newProduct.save((err,result)=>{
res.send(result)
})
})
app.listen(3000,()=>{
console.log('running')
mongoose.connect('mongodb://127.0.0.1:27017/populate' , { useNewUrlParser : true })
})
what I am trying to do is, There is a carts collection and there is another collection of users. Every user has a cart which i am trying to populate from the cart collections.
If you want to test the code, first create the user using the post link 'http://localhost:3000/createUser/' via postman and the create cart Products using 'http://localhost:3000/createProduct/' via postman. Then whenever i tried to fetch the users 'http://localhost:3000/users/' , the cart array stays empty no matter what i try.
Please figure where i am going wrong
Update your Schema defination as:
const Schema = mongoose.Schema;
var userSchema = new Schema({
userName : {
type : String,
default : 'UserName'
},
cart : [ { type : Schema .ObjectId , ref : 'Cart' } ]
})
And try this again:
app.get('/users',(req,res)=>{
UserModel.find().populate('cart').exec((err,result)=>{
res.send(result)
})
})
Let me know, if this works now.

Filter moongose results by reference field using express

I need filter the products of a collection by category id which is a reference field.
product.js
const restful = require('node-restful')
const mongoose = restful.mongoose
const productSchema = new mongoose.Schema({
name: { type: String, required: true },
category: {type: mongoose.Schema.Types.ObjectId, ref: 'CategoryProduct'}
})
productSchema.pre('find', function () {
this.find().populate('category')
})
module.exports = restful.model('product', productSchema)
routes.js
const express = require('express')
const auth = require('./auth')
module.exports = function (server) {
const protectedApi = express.Router()
server.use('/api', protectedApi)
const Product = require('../api/product/productService')
Product.register(protectedApi, '/products')
}
If I run this on Postman, http://localhost:3003/api/products/?name__regex=/test/i, I can get all products which contains 'test' on name.
So I try get all products by a specific category doing this, http://localhost:3003/api/products/?category=5af3ac4372edc6000468d766.
But as the category is an objectID, I receive this error:
{
"message": "Cast to ObjectId failed for value \"5\" at path \"category\" for model \"SimpleProduct\"",
"name": "CastError",
"stringValue": "\"5\"",
"kind": "ObjectId",
"value": 5,
"path": "category"
}
How do I filter the products by category? I do not know how to treat this parameter correctly and pass to mongoose
Here is my CategoryProduct.js file
const restful = require('node-restful')
const mongoose = restful.mongoose
const categorySchema = new mongoose.Schema({
name: {type: String, required: 'O campo Categoria é obrigatório'},
status: {type: Number, required: true},
updated_at: {type: Date}
})
module.exports = restful.model('CategoryProduct', categorySchema)
you would have to do the following in your route:
const mongoose = require('mongoose');
router.get('/', (req, res, next) => {
const category = req.query.category; // assign the query param for use
// mongoose query now
Product.find({category: mongoose.Types.ObjectId(category)}, (err, result) => {
if (err) {console.log(err)};
if (result) {
res.json(result);
}
});
});
This is just a basic example. Since you are using node-restful you might have to adjust the code but the main idea here is that you require the mongoose module using
const mongoose = require('mongoose')
then pass your category query param to it to convert the string to objectID using:
mongoose.Types.ObjectID(YOUR_CATEGORY_PARAM_HERE)
You can do this anywhere, in the your routes.js or in your express.js, just have to have the string you want to convert :)
hope that helps :).

Resources