When I execute this function from something like Postman:
router.get('/db', function(req, res, next) {
tune.find({}, function (err, results) {
res.json(results);
});
});
My database returns this:
[{"_id":"56f30425ba97bb301fe6ab1a","__v":0},
{"_id":"56f30514f9b7ea3b1f1fd9f7","__v":0},
{"_id":"56f306bb9c8203451f2cc58a","__v":0},
{"_id":"56f306ca9c8203451f2cc58b","__v":0},
{"_id":"56f306e99c8203451f2cc58c","__v":0},
{"_id":"56f33d43b64d540b208b6c3c","__v":0}]
My mongoose schema:
var Schema = mongoose.Schema;
var track = new Schema({
title: String,
artist: String,
genre: String
});
var tune = mongoose.model('tune', track);
My post:
router.post('/db', function(req, res, next) {
var tune1 = new tune(req.body);
tune1.save(function (err) {
if (err) { console.log('error!');}
else {
res.json({message: 'Track successfully posted'});
}
});
});
Request Post:
app.use('/users', userRoutes);
var options = { method: 'POST',
url: 'http://localhost:3000/users/db',
headers:
{ 'content-type': 'application/x-www-form-urlencoded',
'postman-token': '',
'cache-control': 'no-cache' },
form: { title: '000000', artist: 'blah blah', genre: 'rap' } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
When I do a post command from Postman I get a successful post message. Is it just the way I am returning the JSON? I want to be able to see title, artist, and genre for every post in the DB.
Thanks
In this instance, Mongoose simply isn't saving what you're expecting. Try taking a look at req.body and tune1 in a debugger to make sure you're getting the expected result.
It might also help to set strict to 'throw' in your schema, just so we get an error back when we attempt to save an invalid tune:
var track = new Schema({
title: String,
artist: String,
genre: String
}, {
strict: 'throw'
});
Related
I'm working on a library management software project but I'm running into trouble when trying to implement check out functionality. The Angular part of my application passes a put request with the user id in the request and the book in the body. In my NodeJs application the put is supposed to add the book to an array in the user object, but whenever I try this instead of the book being added to the array a new object made up of only one of the books properties is added.
The Node.Js checkout function looks like this:
exports.checkOut = (req, res, next) =>{
Book.findByIdAndUpdate(req.body._id,{
checkedOutTo: req.params.userid,
currentlyCheckedOut: true
}, { new: true });
User.findByIdAndUpdate(req.params.userid, {
$push: {"booksCheckedOut": req.body}
}, { new: true })
.then((user) => {
res.statusCode = 200;
res.setHeader('Content-Type','application/json');
res.json(user);
}, (err) => next(err))
.catch((err) => next(err));
}
The user model looks like this
const mongoose = require("mongoose");
const Book = require("./book.model").schema;
const User = mongoose.model(
"User",
new mongoose.Schema({
username: String,
email: String,
password: String,
booksCheckedOut: [Book]
})
);
module.exports = User;
The book model looks like this
const mongoose = require("mongoose");
const Book= mongoose.model(
"Book",
new mongoose.Schema({
author: String,
title: String,
genre: String,
currentlyCheckedOut: { type: Boolean, default: false}
})
);
module.exports = User;
The Angular function that sends the request looks like this
checkOut(book: any, userid: string){
let headers = new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-type',
'Access-Control-Allow-Headers': 'GET, POST, OPTIONS, DELETE, PUT'
});
return this.http.put(`http://localhost:8080/api/book/update/${userid}`, {book}, {headers})
.subscribe(
res => console.log(res),
err => console.log(err)
);
}
What is it I'm doing wrong? I don't know if I need to include anything, so let me know if I do
So it turns out that the problem was basically that using req.body didn't return anything because I still had to refer to the book object inside of the body. Replacing req.body with req.body.book fixed everything. Also when using findByIdAndUpdate those id's I'm passing were actually strings that had to be cast to the ObjectId type.
I'm really stuck trying to figure out how to update my data("Post") to MongoDB (I'm using Mongoose, MongoDB, Node, Express, and Angular 9.1.1). I have no trouble with POST and DELETE, but can't figure out where I'm going wrong with PUT.
Thanks in advance, all help really appreciated -Geoff
ANGULAR: file post.ts
export class Post {
id: string;
title: string;
message: string;
}
ANGULAR: file postsService.ts
//Working OK
deletePost(postId: string) {
this.http.delete(`http://localhost:3000/api/posts/${postId}`)
.subscribe(() => {
const updatedPosts = this.posts.filter(post => post.id !== postId);
this.posts = updatedPosts;
this.postsUpdate$.next([...this.posts]);
});
}
//Not working - I want to update one post
updatePost(postId: string, postTitle: string, postMessage: string) {
const post: Post = { id: postId, title: postTitle, message: postMessage };
this.http.put(`http://localhost:3000/api/posts/${postId}`, post)
.subscribe(response => console.log(response));
}
NODE SERVER: File backend/app.js
// Working OK
app.delete("/api/posts/:id", (req, res, next) => {
Post.deleteOne({ _id: req.params.id }).then((result) => {
console.log(req.params.id);
res.status(200).json({ msg: "Post deleted successfully!" });
});
});
//Not working - I want to update one post
// Post is defined in file: backend/model/post.js
app.put("/api/post/:id", (req, res, next) => {
const post1 = new Post({
_id: req.body.id,
title: req.body.title,
message: req.body.message,
});
Post.findOneAndUpdate({ _id: req.params.id } ,post1)
.then((result) => {
console.log(result);
res.status(200).json({ msg: "Updated successfully!" });
});
});
NODE: backend/model/post.js
const mongoose = require("mongoose");
//note "String is a class used in node/mongoDB"
const postSchema = mongoose.Schema({
title: { type: String, required: true },
message: { type: String, required: true },
});
// this will automaticly be stored in collection "posts"
module.exports = mongoose.model('Post', postSchema);
ERROR IN BROWSER:
// HEADERS:
Request URL:http://localhost:3000/api/posts/5ef676c71105924a08b9e919
Request Method:PUT
Remote Address:127.0.0.1:3000
Status Code:
404
Version:HTTP/1.1
Referrer Policy:strict-origin-when-cross-origin
// REQUEST:
Request Payload:
{"id":"5ef676c71105924a08b9e919", "title":"first Post ", "message":"This is just some text"}
// RESPONCE:
Cannot PUT /api/posts/5ef676c71105924a08b9e919
BUT AT URL ALL IS FINE ON GET:
{"msg":"Post fetched successfully!","posts":{"_id":"5ef676c71105924a08b9e919","title":"first Post ","message":"This is just some text","__v":0}}
Your api put request is targeting the wrong url
angular
this.http.put(`http://localhost:3000/api/posts/${postId}`, post)
backend
app.put("/api/post/:id", (req, res, next) => {
one is post the other its posts. they need to be the same.
It seems like you are trying to update one post's Record so you can simply try this
router.put('/api/post/:id', async (req, res, next) => {
return Post.updateOne({
_id: req.params.id
}, {
$set: {
title: req.body.title,
message: req.body.message
}
})
.then(result => res.json(result))
.catch(err => console.log(err))
});
There is no need to create a new Post because you are trying to update an existing record based on the id and also you are sending routs path like api/post but you are getting a response from the server api/posts so check your route path as well.
There a lot of great examples in adding data in Schemas using population
But how to use this in Express including evaluation existing data and error handling? I already create an user but now I want to add a log to a existing user.
This is my Schema:
const logSchema = new Schema({
logTitle: String,
postedBy: {
type: mongoose.Schema.Types.ObjectId, ref: 'User'
}
});
const userSchema = new Schema({
_id: Schema.Types.ObjectId,
firstName: {
type: String,
required: true
}
});
mongoose.model('User', userSchema);
mongoose.model('Logs', logSchema);
Despite all the good examples I lost my way. It 's hard to use the nice examples in good working Express code.
const mongoose = require('mongoose')
const Log1 = mongoose.model('Logs');
const logCreate = function (req, res) {
const userid = req.params.userid;
Log1.create({
logTitle: req.body.logTitle,
postedBy: userid._id
});
module.exports = {logCreate
};
Do I first create a new log in 'Logs' and then evaluate the existing user? Can somebody give me a push in the right direction? Thanks in advance
You have to add an objectid to the postedBy field. Let's say you have the following routes:
router
.route('/logs/')
.get(ctrlLogs.logsGetAll)
.post(ctrlLogs.logsAddOne);
router
.route('/logs/:logid')
.get(ctrlLogs.logsGetOne);
Then we can define the controller functions as (this is ctrlLogs):
const mongoose = require('mongoose');
const Log = mongoose.model('Log');
module.exports.logsAddOne = (req, res) => {
Log.create({
logTitle: req.body.logTitle,
postedBy: req.body.postedBy
}, (err, newLog) => {
let response = {};
if (err) response = { status: 500, message: err };
else response = { status: 201, message: newLog };
return res.status(response.status).json(response.message);
});
};
module.exports.logsGetAll = (req, res) => {
Log
.find({})
.populate('postedBy')
.exec((err, logs) => {
let response = {};
if (err) response = { status: 500, message: err };
else if (!logs) response = { status: 404, message: [] };
else response = { status: 200, message: logs };
return res.status(response.status).json(response.message);
});
};
module.exports.logsGetOne = (req, res) => {
Log
.findById(req.params.logid)
.populate('postedBy')
.exec((err, log) => {
let response = {};
if (err) response = { status: 500, message: err };
else if (!log) response = { status: 404, message: `Log with id ${req.params.logid} not found.` };
else response = { status: 200, message: log };
return res.status(response.status).json(response.message);
});
};
I've removed a lot of whitespace and curly braces for brevity. You should also not create stuff with values directly from req.body or query directly with req.params.logid; the values have to be validated first. You can use a library such as express-validator for validation.
We can see that by posting a request to /logs with the following request body:
{
"logTitle": "test log 32",
"postedBy": "5a2d1ec83ef998431c726dfc"
}
we will create a log where the user with id 5a2d1ec83ef998431c726dfc is set as the postedBy user. If I get /logs/5a2d240c66d7b473a0aa6ec8 (the new log) I get:
{
"_id": "5a2d240c66d7b473a0aa6ec8",
"logTitle": "test log 32",
"postedBy": {
"_id": "5a2d1ec83ef998431c726dfc",
"firstName": "test",
"__v": 0
},
"__v": 0
}
We can see that the populated log returns the user as well.
I just wrote a ultrasimple nodejs backend with basic crud operations. However on the put statement i don't receive the body of my request:
app.put('/note-update/:id', function (req, res) {
var noteId = req.params.id;
console.log(req.body)
db.collection('notes').update({
_id: noteId
}, req.body, (err, result) => {
res.send(
(err === null) ? {
msg: req.body
} : {
msg: err
}
);
});
});
Here is the call i execute with ajax:
var note = {
_id: "599e660cbc845b4e2952715f",
name: "Genauer Detailbeschrieb",
note: "Ey-10"
}
$.ajax({
type: 'PUT',
url: '/note-update/599e660cbc845b4e2952715f',
dataType: 'JSON',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(note)
})
as you can see i have a console.log(req.body) and all i get is {}
Are you using the bodyparser?
app.use(bodyParser.json());
Plz show more code for your node setup if it doesn't work.
I am new to nodejs/mongo/mongoose and i am trying to do a very simple thing. I have the following schemas:
var authorSchema = mongoose.Schema({
name: String,
});
Author = mongoose.model('Author', authorSchema);
var bookSchema = mongoose.Schema({
title: String,
isbn: String,
pages: Number,
author: { type : mongoose.Schema.ObjectId, ref : 'Author', index: true }
});
Book = mongoose.model('Book', bookSchema);
I want to create a list of authors with id, name and book count for each author. I have something like this:
exports.author_list = function(req, res){
Author.find({}, function (err, authors){
var author_array = Array();
for (var i=0;i<authors.length;i++){
var author_obj = new Object();
author_obj.id = authors[i]._id;
author_obj.name = authors[i].name;
author_obj.count = 0; //here is the problem
author_array[i] = author_obj;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.write(JSON.stringify({ authors: author_array }));
res.end();
});
}
I know how to do a query for the count. My problem is how to do a loop of the authors and populate the output with asynchronous callbacks. What is the proper way to implement this in nodejs fashion?
Thanks
I think you'd want to use something like async to coordinate those requests; map() seems to be a good choice:
Author.find({}, function (err, authors) {
async.map(authors, function(author, done) {
Book.count({author: author._id}, function(err, count) {
if (err)
done(err);
else
{
done(null, {
id : author._id,
name : author.name,
count : count
});
}
});
}, function(err, author_array) {
if (err)
{
// handle error
}
else
{
/*
res.writeHead(200, { 'Content-Type': 'application/json' });
res.write(JSON.stringify({ authors: author_array }));
res.end();
*/
// Shorter:
res.json(author_array);
}
});
});