Node js updating a value returns null - javascript

I am trying to update a value using express and node js API calls. This is what my route looks like:
var express = require('express');
var router = express.Router();
router.put('/updateValue/:id', function(req, res, next) {
value.findByIdAndUpdate(req.params.id, req.body, {
new: true
}, function(err, post) {
if (err) {
res.json('value with the entered ID does not exist');
console.log(err);
} else {
res.json(post);
}
});
});
And this is what my value schema looks like:
var value = new mongoose.Schema({
milliseconds: {
type: Number
}
});
I can add a value which works great.
What works:
Updating the value with the correct id
Updating the value with a shorter ID returns an error (as expected)
Updating the value with a longer ID returns an error (as expected)
What does not work:
When I try to update the value using the same length ID, however changing a figure or two - then I get null returned in the 'post'
Should it not also return an error? Since the value does not get updated due to an incorrect ID?
Any explanation would be appreciated!

if (err) {
res.json('value with the entered ID does not exist');
console.log(err);
}
Above code will be run only when mongoose throw error like in your case
Updating the value with a shorter ID returns an error (as expected)
Updating the value with a longer ID returns an error (as expected)
In console you are getting message like: Cast to ObjectId failed for value
But when you send request with correct format of objectId but with value which is not present in your database update query will return null.
As while updating you first find the document and then update on it, but it is not an error,if document is not present.
You can do your code like this:
router.put('/updateValue/:id', function(req, res, next) {
value.findByIdAndUpdate(req.params.id, req.body, {
new: true
}, function(err, post) {
if (err) {
res.json(err);
console.log(err);
} else {
if(post){
res.json(post);
}else{
res.json('value with the entered ID does not exist');
}
}
});
});
In my suggestion everything we take in the request must be validate before going to your database call.Because, getting an error from mongoose is not a good way to write api.
So,in your case you can validate req.params.id is an ObjectId or not
Example for validating:
var mongoose = require('mongoose');
function validate(req.params.id){
var data=req.params.id;
return mongoose.Types.ObjectId.isValid(data) ? null : 'Should be an object id.';
}
This is just an example of function you can modify and use it in accordance to your code.

According to mongoose doc, if you use the new: true modifier you will get a null result if mongo does not find your document.
It's not a bug it's a feature.

Related

I get a cast exception when using Campground.findById(req.params.id, function(err, foundCampground) and I don't know why

I'm quite new to web dev and I'm actually doing a bootcamp course on udemy, but they won't respond to my problem and I can't find it on the internet.
I'm using mongoose and this is my code:
var campgroundSchema = new mongoose.Schema({
name: String,
image: String,
description: String
});
var Campground = mongoose.model("Campground", campgroundSchema);
app.get("/campgrounds/:id", function(req, res){
//fubd tge canogriybd wutg provied ID
Campground.findById(req.params.id, function(err, foundCampground){
if(err){
console.log(err);
} else {
res.render("show", {campground: foundCampground});
}
});
});
It is throwing a cast exception:
CastError: Cast to ObjectId failed for value " 5bdf29526cb8bc0a83765ab6" at path "_id" for model "Campground"
at MongooseError.CastError (/home/ubuntu/workspace/YelpCamp/v2/node_modules/mongoose/lib/error/cast.js:29:11)
I've search high and low and I cannot find an answer to my problem. Please help!
I think you are providing an invalid Id. If you provide any invalid id mongoose can't cast it and find it. Please double check your id and send another request.
And try findOne() once also.

Missing argument list bracket error

app.get("/editMBTI", editMBTIFunc(req, res)
{
// making MongoClient available to all the EJS Files
// app.locals.MongoClient= MongoClient;
MongoClient.connect(url, function (err, client) {
assert.equal(null, err);
console.log("Connected Successfully to the Database server");
const db = client.db(dbName);
//getting the whole collection of MBTI sets
var cursor = db.collection("mbti_testcontent").find();
cursor.each(function (err, doc) {
console.log(doc);
//send the above retrieved doc to the editMBTI.ejs file(front- end)
res.render('editMBTI', {
'mbti_content': doc,
'db_url': url,
'dbName': dbName
});
});
});
});
The above is the code and the image of the terminal(https://i.stack.imgur.com/XcOti.png). Why is the missing argument bracket error poping up in the editMBTI api ? I have closed all the brackets that were opened. Where is it missing ?
Change this line:
app.get("/editMBTI", editMBTIFunc(req, res)
to this:
app.get("/editMBTI", function editMBTIFunc(req, res)
FYI, a tool like JSHint or JSLint will often give you more detailed info about where something is wrong (which is what I used to see this more easily).

Getting empty JSON from mongolab after GET request in node

My problem: I'm trying to HTTP.GET a random questionSchema from my database but it returns "". In my database (that is hosted in mongolab I have a few different collections, but in my questions collection I only have 3 different JSONs with 3 different questions.
I have a Schema that looks like this:
var questionSchema = new Schema({
description: String
});
module.exports = mongoose.model('Question', questionSchema);
In my routes.js I put the following:
app.get('/api/getrandomquestion', function (req, res) {
if (req.params.description) {
res.json(req.description);
} else {
res.json("");
}
});
I also have a service called QuestionService.js which is supposed to query the DB and give me back a random JSON document out of all (3) the documents that exist there. This is the code of the service:
var numberOfItemsToFind = 3;
Question.find({}, { '_id': 1}, function(err, data){
if (err) res.send(err);
var arr = shuffle.(data.slice(0));
arr.splice(numberOfItemsToFind, arr.length - numberOfItemsToFind);
var return_arr = [];
async.each(arr, function(item, callback){
Question.findById(item._id, function(err, data){
if (err) res.send(err);
return_arr.push(data);
callback();
});
}, function(err){
res.json(return_arr);
});
});
And lastly, I put these together with my questionCtrl:
controller('QuestionCtrl', function ($scope, $http, $modal) {
$http.get('/api/getrandomquestion').success(function (question) {
$scope.description = question.description;
});
});
I am using POSTMAN to make a HTTP.GET request to localhost:3000/getrandomquestion and I'm getting back just the "" as I stated.
Any help towards solving my problem (empty JSON instead of a real one) will be greatly appreciated!
The problem is in your routes.js:
app.get('/api/getrandomquestion', function (req, res) {
if (req.params.description) {
res.json(req.description);
} else {
res.json("");
}
});
req.params.description is undefined. So the if statement failed.
If param description is not necessary, You should probably define your GET API like this:
app.get('/api/getrandomquestion', function (req, res) {
QuestionService.getRandomQuestion(function(questions){
res.json(questions);
//res.send(questions);
});
});
Basically your backend receive a GET getrandomquestions API call, you just forward to fetch MongoDB using QuestionService.

Sails.js / Waterline .add() and .remove() only works on second call

I'm trying to use a Many-to-Many association between 2 models and I have to call .add() or .remove() twice for it to work properly:
// User.js Model
module.exports = {
attributes: {
connections: {
collection: 'connection',
via: 'users'
}
}
}
// Connection.js Model
module.exports = {
attributes: {
users: {
collection: 'user',
via: 'connections'
}
}
}
This is the code I have in my UsersController.js:
User.findById(req.params.user)
.populate('connections')
.exec(function(err, users) {
if (err) return res.status(404).end(); // Not really a 404 but good for now
var user = users[0];
user.connections.add(req.body.connection_id);
user.save(function(err) {
// In my tests err is null/undefined
return res.status(204).end();
}
});
I get a 204 back with no errors in the log or nothing else failed. When I check in my MongoDB database, the user's connections field is just an empty array. If I send the same request again, then I get a an error saying the connection_id already exists for that user. I look into the database, and now the connection appears in the user's connections field. It does the same thing when I remove a connection, I have to send it twice for it to take effect. Anyone have any ideas?
Here are the module versions I'm using:
Node.js version: 0.12.0
Sails.js version: 0.11.0
sails-mongo version: 0.10.5
Sounds like something related to synchronous vs asynchronous methods... meaning you are exiting the method before a certain request is completed. However not sure where that is happening. See if this helps:
var connectionId = req.param('connection_id');
var userId = req.param('user');
User.find(userId)
.populate('connections')
.exec(function(err, users) {
if (err) return res.status(404).end(); // Not really a 404 but good for now
//BTW might be good to double check doing console.log("users: "+JSON.stringify(users));
var user = users[0];
user.connections.push(connectionId);
//Is it really there? console.log("user: "+JSON.stringify(user));
user.save(function(err) {
// In my tests err is null/undefined
return res.status(204).end();
}
});

How to push out requested data from mongodb in node.js

I'm working with Node.js, express, mongodb, and got stuck on this data passing between frontend and backend.
Note: code below is middleware code for front- and backend communication
Here I successfully get the input value from the frontend by using req.body.nr
exports.find_user_post = function(req, res) {
member = new memberModel();
member.desc = req.body.nr;
console.log(req.body.nr);
member.save(function (err) {
res.render('user.jade', );
});
};
Here is the problem, I need to use the input value I got to find the correct data from my database(mongodb in the backend) and push out to the frontend.
My data structure {desc : ''}, the desc is correspond to the input value so it should look something like this {desc: req.body.nr} which is probably incorrect code here?
exports.user = function(req, res){
memberModel.find({desc: req.body.nr}, function(err, docs){
res.render('user.jade', { members: docs });
});
};
Would love to have some help.
Thanks, in advance!
Have a look at this great tutorial from howtonode.org.
Because as you can see he uses a prototype and a function callback:
in articleprovider-mongodb.js
ArticleProvider.prototype.findAll = function(callback) {
this.getCollection(function(error, article_collection) {
if( error ) callback(error)
else {
article_collection.find().toArray(function(error, results) {
if( error ) callback(error)
else callback(null, results)
});
}
});
};
exports.ArticleProvider = ArticleProvider;
in app.js
app.get('/', function(req, res){
articleProvider.findAll( function(error,docs){
res.render('index.jade', {
locals: {
title: 'Blog',
articles:docs
}
});
})
});
Also make sure you have some error checking from the user input as well as from the anybody sending data to the node.js server.
PS: note that the node, express and mongo driver used in the tutorial are a bit older.

Categories