I'm stuck with the 400 bad request when trying to POST to my mongo db, not knowing what's wrong with the code.
This is the structure in Mongoose:
var exp = mongoose.model('Exp', {
_creator: {
type: mongoose.Schema.Types.ObjectId,
required: true
},
exps: [{
description: {
type: String,
required: true
},
skillId: {
type: mongoose.Schema.Types.ObjectId,
required: true
}
}]
});
This is my test case structure and it is how I want the data to be stored:
const exp = {
_creator: UserOneId, // an ObjectID
exps:[{
description: "Ate an apple",
skillId: SkillOneId // an ObjectID
},{
description: "Took a shower",
skillId: SkillTwoId // an ObjectID
}],
};
The exps part should be an array to allow storing multiple exps, each with a description and a skill id.
Below is my POST function:
app.post('/exps', authenticate, (req, res) => {
var exp = new Exp({
_creator: req.user._id, // got from suthenticate middleware
exps: req.body.exps
});
exp.save().then(() => {
res.send(exp);
}, (e) => {
res.status(400).send(e);
});
})
and my test case:
describe('POST /exps', () => {
it('Should create new exp', (done) => {
request(app)
.post('/exps')
.set('x-auth', users[0].tokens[0].token)
.send(exps)
.expect(200)
.end(done);
})
});
With a structure like this, I just can't figure out what went wrong that's giving me the 400, middleware & variables not mentioned here have passed with other test cases so I don't think it's those.
The error message in test looks like this:
1) POST /exps Should create new exp:
Error: expected 200 "OK", got 400 "Bad Request"
at Test._assertStatus (node_modules/supertest/lib/test.js:250:12)
at Test._assertFunction (node_modules/supertest/lib/test.js:265:11)
at Test.assert (node_modules/supertest/lib/test.js:153:18)
at Server.assert (node_modules/supertest/lib/test.js:131:12)
at emitCloseNT (net.js:1552:8)
at _combinedTickCallback (internal/process/next_tick.js:77:11)
at process._tickCallback (internal/process/next_tick.js:104:9)
Any help appreciated.
Ah, found it. It was a typo in the POST function.
Related
It's along explanation so to make it easier I'll call users x and y.
I got this code, which the intention is to the X (making the requests) add his ID into Y's pending requests as well as his own sent requests.
const postSendBBRequest = async (req, res) => {
const userRecipient = await User.findById(req.params.id)
const userSender = await User.findById(req.userId);
const senderId = userSender.id;
try {
if (senderId == userRecipient.id) {
res.status(406).json("You cannot have yourself as a brother")
} else {
userSender.sentBBRequests.push({senderId});
await userSender.save();
userRecipient.receivedBBRequests.push({senderId});
await userRecipient.save();
res.status(201).json("Brotheband request sent sucessfully")
}
} catch (ERR) {
res.status(500).json({ Message: ERR.message });
}
}
My test route on Postman is /add/61b29bb33e775393ae369b79
The problem is: I'm getting an error: "Cast to ObjectId failed for value \"{ senderId: '61b29aef3e775393ae369b74' }\" (type Object) at path \"sentBBRequests\
I thought maybe the problem was how I organized my Schema too:
receivedBBRequests: [
{
type: mongoose.Schema.Types.ObjectId,
},
],
sentBBRequests: [
{
type: mongoose.Schema.Types.ObjectId,
},
],
brothers: {
type: [
{
type: mongoose.Schema.Types.ObjectId,
},
]}
There are too many points of failure I can't even come up with something to solve.
Thanks a lot.
You can use the following :
const senderId = userSender._id.toString();
const userRecipientId = userRecipient._id.toString();
this will allow you to convert the objectId to string
I am rather new to node and am having an issue that is a bit difficult for me to decipher. I am trying to make a reddit clone. The part that I am working on right now is to allow users to view posts other users have posted. I was trying to implement a new route by pasting in this bit of code
app.get('/', (req, res) => {
Post.find({}).lean()
.then((posts) => res.render('posts-index', { posts }))
.catch((err) => {
console.log(err.message);
})
})
However, I am getting this error when I run it:
Cast to ObjectId failed for value "new" (type string) at path "_id" for model "Post"
It seems like something is wrong with my post.js model, but I can't identify it. Could someone review this and help me identify the triggering factor?
const { Schema, model } = require('mongoose');
const postSchema = new Schema({
title: { type: String, required: true },
url: { type: String, required: true },
summary: { type: String, required: true },
}, { timestamps: true });
module.exports = model('Post', postSchema);
I am trying to save the desired book to my MongoDB database when I press the saved button I get a 422 error I pass in the data as an object but for some reason, the data doesn't appear in the response back from the server The data is being passed to the Axios call but for some reason, the data property always returns an empty object,
The save handler
const handleSave = (event) => {
event.preventDefault();
let save = books.filter((book) => book.id === event.target.id);
// console.log(save);
// const da/ta = ;
// console.log(data);
API.saveBook({
title: save[0].title,
authors: save[0].author,
description: save[0].description,
image: save[0].image,
})
.then((res) => {
alert("book saved");
console.log(res);
// console.log(data);
})
.catch((err) => {
// console.log(data);
console.log("book not saved");
console.log(err.response);
});
};
This is the book model and the heroku link where you can see what is being logged out
const bookSchema = new Schema({
title: { type: String, required: true },
authors: [{ type: String, required: true }],
description: { type: String, required: true },
image: { type: String },
date: { type: Date, default: Date.now },
});
Heroku Link
github
I have console.logs in my inspect so you can check those out to see the response im getting back
I have cloned this repository and tested on both your Heroku link and locally, and cannot recreate the error locally. I suspect something to do with the MongoDB server rather than a code issue. I recommend you test creating a record in the live/Heroku-attached MongoDB server using an alternative method.
Thanks,
Will Walsh
Looks like volumeInfo.description is undefined for some books. The API returns a 422 error since description is required but is not present in the request payload. You could pass a default description if the book doesn't have one.
result = {
// ...
title: result.volumeInfo.title,
description: result.volumeInfo.description || "This book doesn't have a description",
// ...
}
Or you could remove the required validation for the description field if it's not an issue.
I would recommend you rename author to authors in the result object for clarity.
result = {
// ...
authors: result.volumeInfo.authors,
// ...
}
I am trying to send an object created by MongoDB model as a body of post request in a jest test.
Here is the test:
test("post request successfully creates a new blog", async () => {
const newBlog = new Blog({
title: "My mundane day at home 3",
author: "AbG",
url: "https://www.google.co.in/",
likes: 11,
});
await api
.post("/api/blogs")
.send(newBlog)
.expect(201)
.expect("Content-Type", /application\/json/)
.catch((err) => console.log(err));
const blogs = await Blog.find({});
expect(blogs).toHaveLength(initialBlogs.length + 1);
});
As you can see, I am sending the newBlog as a body of request. But when I receive it in controller, the newBlog is present in the request.body._doc instead of request.body.
I think this has something to do with the mongoose model of blog.
const blogSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
url: {
type: String,
required: true,
},
likes: {
type: Number,
required: false,
default: 0,
},
});
module.exports = mongoose.model("Blog", blogSchema);
I cannot understand why this is happening.
I found out where I was going wrong.
In the test case, I was creating a mongodb schema instance and passing it as body of request instead of a plain JS object. And in the express app, I was trying to access the request body as a JS object. So that created a confusion.
The changes that I did:
In test:
Instead of
const newBlog = new Blog({....})
I did
const newBlog = {....}
So, I avoided passing mongodb object as request body and created the mongodb object using the constructor immediately before where I needed it.
Here is the post route:
blogsRouter.post("/", async (request, response) => {
const blog = new Blog(request.body);
const savedBlog = await blog.save();
response.status(201).json(savedBlog);
});
Am trying to upload image to the task collection in my mongodb but keep getting an error message.
here is my task model
const mongoose = require('mongoose')
const taskSchema = new mongoose.Schema({
description: {
type: String,
trim: true,
required: true
},
completed: {
type: Boolean,
default: false
},
owner: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
avatar: {
type: Buffer
}
},
{
timestamps: true
})
const Tasks = mongoose.model('Tasks', taskSchema )
module.exports = Tasks
Here is my task router code
router.post('/tasks/me/avatar', auth, upload.single('avatar'), async (req, res) => {
const buffer = await sharp(req.file.buffer).resize({ width: 250, height: 250 }).png().toBuffer()
req.tasks.avatar = buffer
await req.tasks.save()
res.send()
}, (error, req, res, next) => {
res.status(400).send({ error: error.message })
})
error message
[![enter image description here][1]][1]
It keeps giving me an error message of cannot set property 'avatar' of undefined, meanwhile the avatar field has already been defined in the task model.
How can I fix this issue, thanks.
Ok after looking at your answer i'll propose this solution.
Instead of:
req.tasks.avatar = buffer
await req.tasks.save()
Try this
const query = {id: docId}; //prepare a query to find the doc
Task.findOneAndUpdate(query, { $set: {avatar: buffer} }, ()=>{
/Your callback function to run after completed
});
//Then call findOneAndUpdate method from any mongoose.model
//Which will do exactly what its name says:
//Finding ONE element, the first one matching your query
//And then update any values inside $set
//And after that you may use any callback function
Let me know if that helps you out.