PUT method in Node.js/MongoDB - node.js

I'm having issues with a simple PUT method in Node.js (MongoDB collection.update). Any help would be appreciated. At this point, I'm not getting an error, just an empty response.
index.js:
app.put('/UpdateValues/:collection/:entity', function(req, res) {
var params = req.params;
var entity = params.entity;
var collection = params.collection;
var value1 = req.body.value1;
var value2 = req.body.value2;
if (entity) {
collectionDriver.updateValues(collection, entity, value1, value2, function(error, objs) {
if (error) { res.status(400).send(error); }
else { res.status(200).send(objs); }
});
} else {
res.send(400, {error: 'bad url', url: req.url});
}
});
collectionDriver.js:
CollectionDriver.prototype.updateValues = function(collectionName, nameDoc, value1new, value2new, callback) {
this.getCollection(collectionName, function(error, the_collection) {
if (error) callback(error);
else {
the_collection.update(
{ name: nameDoc },
{ $set: {
value1: value1new,
value2: value2new
}},
function( err, result ) {
if ( err ) throw err;
}
);
}
});
};
Testing with:
$ curl -i -X PUT -H 'Content-Type: application/json' -d '{"value1":"1","value2":"1"}' http://localhost/UpdateValues/collection/test

Reference the callback you are passing in within your function. Presently you do not. You also seem like you are expeting the modified document in response, so you need .findOneAndUpdate() instead:
CollectionDriver.prototype.updateValues = function(collectionName, nameDoc, value1new, value2new, callback) {
this.getCollection(collectionName, function(error, the_collection) {
if (error) callback(error);
the_collection.findOneAndUpdate( // <-- new method
{ name: nameDoc },
{ $set: {
value1: value1new,
value2: value2new
}},
{ returnOriginal: false }, // <-- tells to return modified document
callback // <--- passes to callback you passed in
);
});
});

Related

Angular HTTP PUT not reaching expressjs

I have a PUT request that I'm trying to have hit the backend, but for some reason, it never reaches it. What's odd is the if(req.body.bidderId){} hits no problem, but not the if(req.body.watchingGroup){}
The watching angular service uses identical code to the bidderId so I don't know what's different between the two where only one would reach the endpoint? Whats wrong with the addToWatchList call? I did testing and both console.log statements in code block return the correct value. So the data is ready to be passes, but is never received.
console.log("MADE IT TO LISTINGS BACKEND");
never outputs for watchingGroup scenario
watching.service.ts
addToWatchList(id: string, watchingGroup: string[]) {
const watching: Watching = {
id: id,
watchingGroup: watchingGroup
};
console.log("Here are the values being passed to backend");
console.log(watching.id);
console.log(watching.watchingGroup);
console.log(watching);
return this.http.put(`http://localhost:3000/api/listings/${watching.id}`, watching,
);
}
app.js
app.put("/api/listings/:id", (req, res) => {
console.log("MADE IT TO LISTINGS BACKEND");
if (req.body.biddingGroup) {
console.log("bidding has been received");
Post.findByIdAndUpdate(
{ _id: req.params.id },
{
currentBid: req.body.currentBid,
lastBidTimeStamp: Date.now(),
bidderId: req.body.bidderId,
auctionEndDateTime: req.body.auctionEndDateTime,
biddingGroup: req.body.biddingGroup,
lastBidTimeStamp: req.body.lastBidTimeStamp
},
function(err, docs) {
if (err) res.json(err);
else {
console.log(docs);
}
}
);
}
if (req.body.watchingGroup) {
console.log("watching has been received");
Post.findByIdAndUpdate(
{ _id: req.params.id },
{
watchingGroup: req.body.watchingGroup
},
function(err, docs) {
if (err) res.json(err);
else {
console.log(docs);
}
}
);
}
});
addToWatchList
addToWatchList(
auctionId: string,
watchingGroup: string[]
) {
this.watchItStatus = true;
this.userId = localStorage.getItem("userId: ");
var unique = watchingGroup.filter(function(elem, index, self) {
return index === self.indexOf(elem);
});
this.uniqueResult = unique;
watchingGroup.push(this.userId);
this.watchListService.addToWatchList(auctionId, this.uniqueResult);
}
As i suspected you're not subscribing to it. It's weird but you need to subscribe to it.
this.watchListService.addToWatchList(auctionId, this.uniqueResult).subscribe(
(res) => {
// Handle success response
console.log("SUCCESS");
},
(err) => {
// Handle error response
console.log("ERROR");
}
);

wait for result from an async method

I'm trying to call an async method from for loop, but it doesn't wait for the result from that method.
Below is my code:
async function fetchActivityHandler (req, reply) {
esClient.search({
index: 'user_activity',
type: 'document',
body: {
_source : ["userId","appId","activity","createdAt","updatedAt"],
query: {
bool : {
must:[
{match : { 'userId': req.params.id }}
]
}
}
}
},async function (error, response, status) {
if (error){
console.log('search error: '+error)
}
else {
var activities = [];
//await Promise.all(response.hits.hits.map(async function(hit){
for (const hit of response.hits.hits) {
var activity = hit._source
var app = await fetchAppDetails(activity.appId);
console.log(app);
activity = {...activity,app : app}
activities.push(activity);
console.log(activity);
}
reply.status(200).send(activities);
}
});
}
async function fetchAppDetails (appId) {
esClient.get({
index: 'app',
type: 'document',
id: appId
}, function (err, response) {
console.log(response._source);
return (response._source);
});
}
What may be the problem. I'm using async and await, but it is not working.
Await works with promise. You should wrap your function with promise to get this work. Hope this will help you. Also you do not need to use async on fetchActivityHandler function. Only in the callback which you have already used.
function fetchAppDetails (appId) {
return new Promise((resolve,reject)=>{
esClient.get({
index: 'app',
type: 'document',
id: appId
}, function (err, response) {
if(err){
reject(err);
}
else{
resolve(response)
}
});
});
}

Async parallel with object only last result

I'm having an issue with async parallel. This is my current code:
// Tasks object for async
var Tasks = {};
// Go through the items
for(index in items) {
var itemName = items[index];
Tasks[index] = function(callback) {
self._requestItem(currency, appID, itemName, function(err, item) {
if( err) {
callback(err, null);
return;
}
callback(null, { "name": itemName, "data": item });
});
}
}
// Go through tasks, using async parallel
this._async.parallel(Tasks, function(err, results) {
console.log(err, results);
});
Each items entry is unique. But when the parallel finishes it shows every result like the last one. For example if I have 3 items in items then async results outputs 0, 1 the same as 2.
null { '0':
{ name: 'Test 3',
data:
{ success: true,
price: 17.02 } },
'1':
{ name: 'Test 3',
data:
{ success: true,
price: 17.02 } },
'2':
{ name: 'Test 3',
data:
{ success: true,
price: 17.02 } } }
Why does it do this? If I use 2 items in items it again copies the result from 1 to 0.
Adding snippet of _requestItem as requested.
Manager.prototype._requestItem = function(currency, appID, itemName, callback) {
var self = this;
this._request({
uri: this._uri,
baseUrl: this._baseUrl,
json: true
}, function(err, res, body) {
if( ! err && res.statusCode !== 200) {
if(self._errorCodes[res.statusCode] !== undefined) {
callback(self._errorCodes[res.statusCode], null);
} else {
callback('Unsuccessful response (' + res.statusCode + '). Is the API having issues?', null);
}
} else if( ! err && res.statusCode === 200) {
callback(null, body);
} else {
callback(err, null);
}
});
}
No matter what is the content of the body of the _requestItem() function the value of the name attribute on the response array elements shouldn't be the same if the elements of the items array are unique.
The only error i can see is the fact that index is declared as a global variable but this shouldn't be the cause of the problem.
I suggest you to inspect the content of the items variable before the code enters the for loop (to see if it has been corrupted before this point). Debugging is a good idea in this case.
A better implementation would be:
var tasks = items.map(function(itemName){
return function(callback) {
self._requestItem(currency, appID, itemName, function(err, item) {
if( err) {
callback(err, null);
return;
}
callback(null, { "name": itemName, "data": item });
});
}
});
// Go through tasks, using async parallel
this._async.parallel(tasks, function(err, results) {
console.log(err, results);
});

how to do update operation in express.js

I have a simple student database program in express.js using mongodb.How can the updation operation be performed for the following program:
my app.js programs is as follows:
var studentDb=new StudentDb('localhost',27017);
app.get('/',function(req,res){
studentDb.findAll(function(error,stu){
res.end(JSON.stringify({
title:'students',
students:stu
}));
});
});
app.get('/student/new',function(req,res)
{
var rollno=req.param('rollno');
studentDb.findByrollno(rollno,function(error,docs)
{
if( error ) { res.end(JSON.stringify(error)); }else{
if(docs.length==1)
{res.end('already has one.');}
else
{ studentDb.save({
title:req.param('title'),
name:req.param('name'),
rollno:req.param('rollno')
},
function(error,docs)
{
console.log(docs);
});setTimeout(function(){ res.redirect('/');},5000);}}
});
});
app.delete('/student/new', function (req, res) {
studentDb.findByrollno(req.param('rollno'), function (error, docs) {
studentDb.delete(req.param('rollno'),function (error,students) {
if (error) {
console.log(error);
} else {
console.log("deleted rollno: " + req.param('rollno'));
} res.end(JSON.stringify(students));
});
});
});
here is my studentdb.js file
var Db = require('mongodb').Db;
var Connection = require('mongodb').Connection;
var Server = require('mongodb').Server;
var JSON = require('mongodb').JSON;
var ObjectID = require('mongodb').ObjectID;
StudentDb = function(host, port) {
this.db= new Db('studentdata', new Server(host, port, {safe: false}, {auto_reconnect: true}, {}));
this.db.open(function(){});
};
StudentDb.prototype.getCollection= function(callback) {
this.db.collection('students', function(error, student_collection) {
if( error ) callback(error);
else callback(null, student_collection);
});
};
StudentDb.prototype.findAll = function(callback) {
this.getCollection(function(error, student_collection) {
if( error ) callback(error)
else {
student_collection.find().toArray(function(error, results) {
if( error ) callback(error)
else callback(null, results)
});
}
});
};
StudentDb.prototype.findByrollno = function(rollno,callback) {
this.getCollection(function(error, student_collection) {
if( error ) callback(error)
else {
student_collection.find({rollno:rollno}).toArray(function(error, results) {
if( error ) callback(error)
else callback(null, results)
});
}
});
};
StudentDb.prototype.save = function(students, callback) {
this.getCollection(function(error, student_collection) {
if( error ) callback(error)
else {
if( typeof(students.length)=="undefined")
students = [students];
for( var i =0;i< students.length;i++ ) {
student = students[i];
student.created_at = new Date();
}
student_collection.insert(students, function() {
callback(null, students);
});
}
});
};
StudentDb.prototype.delete = function(rollno,callback) {
this.getCollection(function(error, student_collection) {
if( error ) callback(error)
else {
student_collection.remove({rollno:rollno},function(error, results) {
if( error ) callback(error)
else callback(null, results)
});
}
});
};
i need to update a field in the student database.but i am unaware of using the update query.pls help me.
You mean you don't know how to implement a StudentDb.update method? You just need to make an object using Mongo's update operators. There are good docs on how to use these here. This method will update one student setting any fields you set in the updatedFields object in the student:
// updatedFields should be an object with fields to set on the student
// e.g. updatedFields = {name: "Bob", favouriteSubject: "Computing"}
StudentDb.prototype.update = function(rollno, updatedFields, callback) {
this.getCollection(function(error, student_collection) {
if( error ) callback(error)
else {
student_collection.updateOne(
{rollno: rollno},
{$set: updatedFields},
callback
);
}
});
};
Note that since your callbacks follow the callback(err, result) convention there's no need to call them yourself you can pass them to Mongo to call them for you.
From the MongoDb docs:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
Source: MongoD docs
You can create a new method on your StudentDb object prototype for handling update operations:
StudentDb.prototype.update = function (rollno, updatedFields, callback) {
this.getCollection(function(error, student_collection) {
if( error ) callback(error);
else {
student_collection.update({rollno: rollno}, updatedFields, function (err, updatedStudent) {
if (err) callback(err);
else callback(null, updatedStudent);
});
}
Add a new handler to your router using the PUT HTTP verb:
app.put('/student/new', function (req, res) {
studentDb.update(req.param('rollno'), req.body, function (err, student){
if (err) {
console.error(err);
} else {
res.send(JSON.stringify(student));
}
});
});
As a sidenote, you can check out the mongoose module for nodejs, working directly with the MongoDB native driver is a bit more verbose.
Also seeing that you are fairly new to nodejs, I suggest reading a bit more about RESTful services, the 'Content-Type' HTTP header and send your data in JSON format.
Improve your error handling when responding to HTTP requests (e.g. if the update operation fails, let the client know about it):
studentDb.update(req.param('rollno'), req.body, function (err, student){
if (err) {
console.error(err);
res.status(500).json(err); // respond with HTTP status 500 (internal server error)
} else {
console.log("updated rollno: " + req.param('rollno'));
} res.send(JSON.stringify(student));
});

Callback function in Nodejs

I have function
var checkTokenIsExpired = function(name, token, response) {
LoginToken.find( { name: name, series: token }, function(error, info){
console.log("info: ", info[0]['expire']);
if (error) {
// response.send("error: %s}", error);
response(error);
}
if (info.length > 0) {
var expire = new String(info[0]['expire']);
// expire = expire.substr(0,26);
var date = new Date(expire);
if (date >= new Date()) {
// response.send("{info: success" );
response("success");
}
else{
// response.send("error: token-has-expired");
response("token-has-expired");
}
console.log("Response: ", info);
}
else {
response(null);
}
} );
}
To check token is expired or not? It will return a string.
And I call this function in here
exports.updateAccount = function(newData, callback)
{
Accounts.find({name:newData.body.name}, function(err, docs){
if (err) {
callback.send('{error: ' + String(err) + "}");
}
if (docs.length==0 || !docs) {
callback.send("{error: NULL }");
}
else {
checkTokenIsExpired(newData.body.name, newData.body.token, function(error, info){
if (error){
callback.send("{error: " + error + "}");
// I want to get info here }
console.log("check token: ", info);
// check info of token is expired or not
if (info!=null && info!="token-has-expired") {
var updateString = "";
if (newData.body.screen_name){
Accounts.update( {'name': newData.body.name},
{
"screen_name" : newData.body.screen_name
},
{ 'upsert' : true },
function (err, numberAffected, raw) {
if (err) return handleError(err);
});
}
if (newData.body.email){
Accounts.update( {'name': newData.body.name},
{
"email": newData.body.email
},
{ 'upsert' : true },
function (err, numberAffected, raw) {
if (err) return handleError(err);
});
}
if (newData.body.password == ''){
} else{
var password = encodePassword(newData.body.password, docs[0]['salt']);
Accounts.update( {'name': newData.body.name},
{
"hassedPass" : password,
},
{ 'upsert' : true },
function (err, numberAffected, raw) {
if (err) return handleError(err);
});
}
}
});
}
I want to get the info when call checkTokenIsExpired but when I console.log("info", info) it return undefined.
in checkTokenIsExpired, you need to pass info to the response callback otherwise it is not in scope of your second code.
at least in the case where you have success:
response("success", info);
Instead of passing "success", you'd typically pass null to indicate there is no error.
I have solved problem
checkTokenIsExpired(newData.body.name, newData.body.token, function(error, info)
because it will take 1 parameter but I put 2
Change it into checkTokenIsExpired(newData.body.name, newData.body.token, function(info)
It will correct :D

Resources