Mongoose Path "." is required - problem with PostmanMocking? - mongodb

i am testing my mongoose (for MongoDB) schema, and I encountered an validation issue. After making POST verb I am getting en error:
"message": {
"errors": {
"number": {
"message": "Path `number` is required.",
"name": "ValidatorError",
"properties": {
"message": "Path `number` is required.",
"type": "required",
"path": "number"
},
"kind": "required",
"path": "number"
}
},
"_message": "eventArrayModel validation failed",
"message": "eventArrayModel validation failed: number: Path `number` is required.",
"name": "ValidationError"
}
This is my mocked json in Postman:
JSON mocked file
{
"arrayName": "displayedEvents",
"number": "4"
}
And this is my mongoose schema:
const mongoose = require("mongoose");
const eventSchema = new mongoose.Schema({
title: {
type: String,
// required: true,
},
start: {
type: Date,
// required: true,
},
end: {
type: Date,
// required: true,
},
allDay: {type: Boolean, default: true},
resource: {
type: String,
// required: true,
},
});
const eventArrayModel = mongoose.model("eventArrayModel", {
arrayName: {
type: String,
required: true,
},
array: {type: [eventSchema]} ,
number: {
type: Number,
required: true,
}
});
module.exports = eventArrayModel;
And the get router:
router.get('/', async (req,res)=> {
try{
const posts = await eventArrayModel.find();
res.json(posts);
}catch(err){
res.json({message: err});
}
});
I can't see anything wrong about this code. It works fine without number field.

Okey I found it, this part of code
router.post('/', async(req,res)=>{
const post = new eventArrayModel({
arrayName: req.body.arrayName
});
try {
const savedPost = await post.save();
res.json(savedPost);
}catch(err){
res.json({message: err});
}
});
Should looks more like this:
router.post('/', async(req,res)=>{
const post = new eventArrayModel({
arrayName: req.body.arrayName,
array: req.body.array,
myNumber: req.body.myNumber
});
try {
const savedPost = await post.save();
res.json(savedPost);
}catch(err){
res.json({message: err});
}
});

Related

API call fails when i put required:true model schema

I am trying to make an api endpoint and this is my model schema MongoDB
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
unique: true,
},
email: {
type: String,
},
password: {
type: String,
},
profilePic: {
type: String,
default: "",
},
},
{ timestamps: true }
);
module.exports = mongoose.model("User", UserSchema);
API logic
const router = require("express").Router();
const User = require("../models/User");
//REGISTER
router.post("/register", async (req, res) => {
try {
const newUser = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password,
});
const user = await newUser.save();
res.status(200).json(user);
} catch (err) {
res.status(500).json(err);
}
});
module.exports = router;
index.js
const express = require("express");
const app = express();
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const authRoute = require("./routes/auth");
const cors = require("cors");
const bodyParser = require("body-parser");
app.use(
bodyParser.urlencoded({
extended: false,
})
);
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(express.json());
dotenv.config();
mongoose
.connect(process.env.MONGO_URL, {
useUnifiedTopology: true,
useNewUrlParser: true,
})
.then(() => console.log("DB Connected!!!"))
.catch((err) => {
console.log("did not work", err);
});
app.use("/api/auth", authRoute);
app.use("/", (req, res) => {
console.log("main url");
});
app.listen("5002", () => {
console.log("server running");
});
When I am trying to POST call to localhost:5002/api/auth/register , with the following body
{
"username": "testname",
"email": "test#gmail.com",
"password": "122",
}
I get the following error
{
"errors": {
"username": {
"name": "ValidatorError",
"message": "Path `username` is required.",
"properties": {
"message": "Path `username` is required.",
"type": "required",
"path": "username"
},
"kind": "required",
"path": "username"
}
},
"_message": "User validation failed",
"name": "ValidationError",
"message": "User validation failed: username: Path `username` is required."
}
When I remove required:true this api call works but i cant see the fields for username, email, password in collection of the database.
What am I doing wrong here?

MongoDB - JSON schema validation

Can anyone please tell me where to place the $jsonSchema in the following code. Every time I test post my code returns the status(400) success: false.
All I'm trying to do is validator the title and description have been entered correctly.
import { connectToDatabase } from "../../../util/mongodb";
export default async (req, res) => {
const { method } = req;
const { db } = await connectToDatabase();
switch (method) {
case "GET":
try {
const products = await db.collection("products").find({}).toArray();
res.status(200).json({ success: true, data: products });
} catch (error) {
res.status(400).json({ sucess: false });
}
break;
case "POST":
try {
const product = await db
.collection("products")
.insertOne(req.body)
.runCommand({
collMod: "products",
validator: {
$jsonSchema: {
bsonType: "object",
required: ["title", "description"],
properties: {
title: {
bsonType: "string",
description: "must be a string and is required",
unique: true,
},
description: {
bsonType: "string",
description: "must be a string and is required",
},
},
},
},
});
res.status(201).json({ success: true, data: product });
} catch (error) {
res.status(400).json({ sucess: false });
}
break;
default:
res.status(400).json({ dsucess: false });
break;
}
};

Mongoose schema optional with validation

Given a Schema like this:
new Schema(
{
someData: {
someString: {
required: false,
maxlength: 400,
type: String
}
otherData: {
required: true,
type: String
}
});
someString is optional but has a validation to check if it's length is below 400.
If I'm given an invalid length string (>400) would this object still be saved but without the someString or would this throw an error? If this throws an error how can I change the schema so that the object will still get saved?
It will throw an error without saving the document.
Let's say we have this schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const studentSchema = new Schema({
someData: {
someString: {
required: false,
maxlength: 5,
type: String
},
otherData: {
required: true,
type: String
}
}
});
module.exports = mongoose.model("Student", studentSchema);
And this post route:
const Student = require("../models/student");
router.post("/students", async (req, res) => {
try {
const result = await Student.create(req.body);
res.send(result);
} catch (err) {
console.log(err);
if (err.name === "ValidationError") {
return res.status(400).send(err.errors);
}
res.status(500).send("Something went wrong");
}
});
When we send a bad request it will give ValidationError where we can read the error details from err.errors.
Request Body:
{
"someData": {
"someString": "123456",
"otherData": "other"
}
}
The response will be:
{
"someData.someString": {
"message": "Path `someData.someString` (`123456`) is longer than the maximum allowed length (5).",
"name": "ValidatorError",
"properties": {
"message": "Path `someData.someString` (`123456`) is longer than the maximum allowed length (5).",
"type": "maxlength",
"maxlength": 5,
"path": "someData.someString",
"value": "123456"
},
"kind": "maxlength",
"path": "someData.someString",
"value": "123456"
}
}
You can resolve this by removing the maxlength option, or check the field's length in your route, and if it's length is bigger than the specified maxlength, you can substr it so that it doesn't result in error.
router.post("/students", async (req, res) => {
try {
let doc = req.body;
if (doc.someData && doc.someData.someString && doc.someData.someString.length > 5) {
doc.someData.someString = doc.someData.someString.substring(0, 5);
}
const result = await Student.create(doc);
res.send(result);
} catch (err) {
console.log(err);
if (err.name === "ValidationError") {
return res.status(400).send(err.errors);
}
res.status(500).send("Something went wrong");
}
});

postman returns empty array

I sent below (raw/json) from postman to mongodb and I received filled img, text but coordinates was empty array "[]"
{
"coordinates": [],
"_id": "5b309b5671903722e073827e",
"date": "2018-06-25T07:35:50.932Z",
"__v": 0
},
Why is this is and how get not empty coordinates array?
Postman
{
"img": "test",
"text": "Meet",
"coordinates": [12, 23]
}
this is my schema
const mongoose = require('mongoose')
const memoSchema = new mongoose.Schema({
img: {
type: String
},
text: {
type: String
},
date: {
type: Date,
default: Date.now
},
coordinates: [Number]
})
module.exports = mongoose.model('Memo', memoSchema)
this is my router
api.post('/', async (req, res) => {
let newMemo = new Memo()
newMemo.img = req.body.img
newMemo.text = req.body.text
newMemo.coordinates = req.body.coordinates
await newMemo.save((err) => {
if(err) return res.status(500).json({ message: 'internal error' })
res.json({ message: 'saved...' })
})
})
I didn't add bodyparser
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())

Expressjs collection.update $push result with TypeError: Cannot call method 'update' of undefined

I try to create valid geojson FeatureCollection and some problems occurred during updating document in collection.
My Model
var mongoose = require('mongoose');
Schema = mongoose.Schema;
var DataSchema = new Schema({
type: {type:String, default:"Feature"},
properties:{
title: { type: String, required: true },
description: { type: String, required: true},
date: {type:Date, default:Date.now}},
geometry:{
type:{type:String, default:"Point"},
coordinates: {type: [Number]}}
});
var MetadataSchema = new mongoose.Schema({
type : {type: String, default: "FeatureCollection"},
features: [DataSchema]
});
var rescueModel = mongoose.model('rescueModel', MetadataSchema);
Router
router.post('/mountain_rescue', function(req, res){
db.collection('rescuemodels', function(err, collection){
collection.update({
"type": "FeatureCollection"
},
{
$push: {
"features": {
properties: {
title: req.body.title,
description: req.body.description
},
geometry: {
coordinates: req.body.coordinates.split(',')
}
}
}
});
res.redirect('/mountain_rescue');
});
});
module.exports=rescueModel;
So If everything is okay but why is it that after executing post route I get
TypeError: Cannot call method 'update' of undefined
I also checked the command in mongo shell and it works
db.rescuemodels.update(
{
"type":"FeatureCollection"
},
{
$push:{
"features": {
"properties":{"title":"WOW"}
}
}
}
)
The problem is that collection is not defined before running the update. Also, you might want to do the redirect in the callback to the update function, but that will depend on the behaviour you are looking for. Your code would then look something like this:
var collection = db.collection('rescuemodels');
collection.update({
"type": "FeatureCollection"
},
{
"$push": {
"features": {
"properties": {
"title": req.body.title,
"description": req.body.description
},
"geometry": {
"coordinates": req.body.coordinates.split(',')
}
}
}
}, function(err, result) {
if (err) throw err;
res.redirect('/mountain_rescue');
});