I am using Parse Server on AWS and mLab with great success, except for my Cloud Code. The main issue is surrounding my previous code for Create OR Update an object. I used to do this by querying for a user pointer on the Favourites class. If a row contains a user pointer then I need to update its content, if it doesn't exist a row needs to be created.
Old Parse.com Code
Parse.Cloud.define("saveFavourites", function(request, response) {
console.log(request.params.favourites);
var Favourites = Parse.Object.extend("Favourites");
var query = new Parse.Query("Favourites");
query.equalTo('user', request.user);
query.first({
success: function(results) {
console.log(JSON.stringify(results));
console.log(results)
if (results === undefined) {
var favourites = new Favourites();
favourites.save({
user: request.user,
favourites: request.params.favourites
}, {
success: function(favourites) {
// The object was saved successfully.
},
error: function(favourites, error) {
// The save failed.
// error is a Parse.Error with an error code and message.
}
});
} else {
results.set("favourites", request.params.favourites);
results.set("userId", request.user.id);
results.save();
}
response.success(results);
},
error: function(error) {
error.message("favourites lookup failed");
}
});
});
New Parse Server Code
Parse.Cloud.define("saveFavourites", function(request, response) {
console.log('user is : ' + JSON.stringify(request.user));
var Favourites = Parse.Object.extend("Favourites");
var query = new Parse.Query("Favourites");
query.equalTo("user", request.user);
query.first({
useMasterKey: true
}, {
success: function(results) {
if (results && results.length > 0) {
console.log('running found');
favourites.set("favourites", request.params.favourites);
favourites.set("userId", request.user.id);
favourites.save();
response.success();
} else {
var favourites = new Favourites();
favourites.set("user", request.user);
favourites.set("favourites", request.params.favourites);
favourites.set("userId", request.user.id);
favourites.save();
response.success();
}
},
error: function(error) {
console.log(error.message);
}
});
});
Do not response unless callback finished. Set response.error on each Parse requests error.
Parse.Cloud.define("saveFavourites", function(request, response) {
console.log(request.params.favourites);
var Favourites = Parse.Object.extend("Favourites");
var query = new Parse.Query("Favourites");
query.equalTo('user', request.user);
query.first({
//is this query need masterKey?
useMasterKey: true,
success: function(results) {
console.log(JSON.stringify(results));
console.log(results)
if (results === undefined) {
var favourites = new Favourites();
favourites.save({
user: request.user,
favourites: request.params.favourites
}, {
success: function(favourites) {
// The object was saved successfully.
response.success(results);
},
error: function(favourites, error) {
// The save failed.
// error is a Parse.Error with an error code and message.
response.error(error);
}
});
} else {
results.set("favourites", request.params.favourites);
results.set("userId", request.user.id);
results.save(null, { useMasterKey: true }).then(response.success, response.error);
}
},
error: function(error) {
error.message("favourites lookup failed");
response.error(error);
}
});
});
Related
When creating new document in node js gives MongoError of write ECONNRESET.
Following is the error in console when creating the new document:
error: Error adding new agreementTemplate ! Error :
{"name":"MongoError","message":"write ECONNRESET"}
following is the controller function creating the error.
function addSubChapter(req, res) {
logger.debug('Processing request for creating a new agreement.');
console.log(req.body);
async.waterfall([
function (callback) {
agreementService.getAgreementTemplate( callback);
},
function (data, callback) {
agreementTmplService.AgreementTemplateSetDefaultFalse(function(err, result){
callback(null, data);
});
},
function (data, callback) {
var agreementTemplate =data.result[0];
var chapter ={
name: req.body.name
}
agreementTemplate = agreementTemplate.toObject(); // swap for a plain javascript object instance
delete agreementTemplate["_id"];
agreementTemplate.createdBy= req.body.user;
agreementTemplate.created= new Date();
//agreementTemplate.Chapters.push(chapter);
var chapters = agreementTemplate.Chapters;
for(var i=0;i<chapters.length; i++){
if(chapters[i].name == req.body.chapter){
var subChap ={
name: req.body.name
}
chapters[i].subChapters.push(subChap);
}
}
console.log('----------------------');
console.log(agreementTemplate);
agreementService.createAgreementTemplate(agreementTemplate, callback);
},
function (data, callback) {
agreementTmplService.addSubChapter(req.body, callback);
}
], function (err, result) {
utils.processResponse(err, result, res);
});
}
When creating the agreement template it causes the error, here is the service function:
function createAgreementTemplate(data, callback) {
serviceHelper.createModel(AgreementTemplate, 'agreementTemplate', data, callback);
}
and the createModel function is as follows.
function createModel(model, modelName, modelData, callback) {
logger.debug('Creating new Model : %s', modelName);
var modelObj = model(modelData);
modelObj.save(function (err, newModelObj) {
if (err) {
logger.error('Error adding new %s ! Error : %s', modelName, JSON.stringify(err));
callback(utils.handleMongodbError(err), null);
} else {
logger.info('New Model of type : %s created with id : %s', modelName, JSON.stringify(newModelObj._id));
var result = {};
result.status = httpStatus.OK;
result.result = newModelObj._id;
callback(null, result);
}
});
}
I have a service layer that calls a database layer where a query is run. I am trying to stub the data layer returning a value but I keep getting this error
TypeError: User.find(...).exec is not a function.
I am using the bluebird module and am also using sinon for stubbing
//Service Layer
var dbLayer = require('../dbLayer');
exports.getUsers = function (req, res) {
dbLayer.GetUsersThatNeedToBeApproved(req.body.domain)
.then(function (data) {
res.json(data);
})
.catch(function(error){
routesLogger.logError(req.session.user.role, "getUsers", error);
res.status(400).send({error: StatusCodes.DBERROR});
});
};
//DB Layer
module.exports.GetUsersThatNeedToBeApproved = function (domain) {
return new Promise.resolve(User.find({$and: [{'domain.upgradeRequest': true}, {'domain.access': constants.ACCESSPRIVATE}, {'domain.name': domain}]}).exec())
.then(function (data) {
return data;
}).catch(function (error) {
routesLogger.logError("userDAL", "GetUsersThatNeedToBeApproved", error);
return error;
});
This is my test case
describe("Suite to get users in portal that need to be approved",function(){
var request = null;
var response = httpMocks.createResponse();
it("Should get a list of all users that need to be approved for a specific domain",function(done){
request = {
session: {
user: {
domain:{
name:'domain'
},
email: 'testUser#test.com',
role: 'Admin'
}
}
};
var expectedFindResponse = [
{
email: "test#xxx.com",
role: "T",
domain:{
upgradeRequest:true,
access:'private',
name:'domain'
}
},
{
"email": "test1#xxx.com",
"role": "T",
domain:{
upgradeRequest:true,
access:'private',
name:'domain'
}
}
];
var find = sinon.stub(mongoose.Model, "find").returns(Promise.resolve(expectedFindResponse));
admin.getUsers(request, response);
var responseData = response._getData();
});
});
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));
});
I get the following error when trying to test my method:
TypeError: Cannot call method 'json' of undefined
Below is my code, i'd get the same error for 'status' if i remove res.status from the test method.
How do i define 'json' so i dont get an exception thrown at:
res.status(404).json(error);
when testing this function.
stores.js
{ //the get function declared above (removed to ease of reading)
// using a queryBuilder
var query = Stores.find();
query.sort('storeName');
query.exec(function (err, results) {
if (err)
res.send(err);
if (_.isEmpty(results)) {
var error = {
message: "No Results",
errorKey: "XXX"
}
res.status(404).json(error);
return;
}
return res.json(results);
});
}
storesTest.js
it('should on get call of stores, return a error', function () {
var mockFind = {
sort: function(sortOrder) {
return this;
},
exec: function (callback) {
callback('Error');
}
};
Stores.get.should.be.a["function"];
// Set up variables
var req,res;
req = {query: function(){}};
res = {
send: function(){},
json: function(err){
console.log("\n : " + err);
},
status: function(responseStatus) {
assert.equal(responseStatus, 404);
}
};
StoresModel.find = sinon.stub().returns(mockFind);
Stores.get(req,res);
The status method happens to be a chainable method. The convention for chainable methods is to always return this at the end. In your tests, you mock up the res.status method but forgot to return this;.
res = {
send: function(){ },
json: function(err){
console.log("\n : " + err);
},
status: function(responseStatus) {
assert.equal(responseStatus, 404);
// This next line makes it chainable
return this;
}
}
Could someone explain how this is happening? An array from Express is being destroyed before it is returned. In the example below, I am successfully populating the resData.user.apps array and can see this via the server's console log. However, when the resData object is returned the array is empty:
// Build the response
var resData = {
success: true,
user: {
email: newUserItem.email,
apps: []
}
};
// Add any default applications
Application.find({ isDefault: true, isDeleted: false }, function(err, defaultApps){
if (err){
console.log(err);
return res.status(500).send({ message: 'Failure loading default applications.' });
} else {
if (defaultApps.length < 1){
console.log('No default apps');
} else {
defaultApps.forEach(function(defaultApp){
var app = {
name: defaultApp.formalName,
url: defaultApp.url,
def: true
};
console.log(app);
resData.user.apps.push(app);
console.log('Sanity: ' + JSON.stringify(resData));
});
}
}
});
return res.send(resData);
The problem here is that the find is async so you are writing back the response before the call has completed. Move return res.send(resData); into the find callback.
Application.find({ isDefault: true, isDeleted: false }, function(err, defaultApps){
if (err){
console.log(err);
return res.status(500).send({ message: 'Failure loading default applications.' });
} else {
if (defaultApps.length < 1){
console.log('No default apps');
} else {
defaultApps.forEach(function(defaultApp){
var app = {
name: defaultApp.formalName,
url: defaultApp.url,
def: true
};
console.log(app);
resData.user.apps.push(app);
console.log('Sanity: ' + JSON.stringify(resData));
});
}
res.send(resData);
}
});