While using sails 1.0 I run into a problem.
The sails documentation describes that the create function's callback (or promise) has an argument describing the inserted record. In my case (see code below) this value is always "undefined". I can verify that the entry is however added to the database. (Both using postgresql and the localdiskdb). - So the model is set up correctly.
The route connects (correctly) to:
add: function (req, res) {
const params = req.allParams();
const {
event_id,
name,
date,
} = params;
const dat = {
name:name,
id:Number(event_id),
date_start:new Date(Number(date)),
};
console.log(dat);
console.log(typeof dat.location);
Event.create(dat)
.then(function (result){
console.log(result)
return res.ok();
})
.catch(function (err){
console.log(err);
return res.send(err);
});
}
So why is the result in my callback undefined?
With Sails.js v1, you will have to include the .fetch() function to send back records that were updated/destroyed/created when performing an .update(), .create(), .createEach() or .destroy() query. Otherwise, no data will be returned (or if you are using callbacks, the second argument to the .exec() callback will be undefined.)
The official example:
var newUser = await User.create({ fullName: 'Alice McBailey' }).fetch();
For your code above, try:
Event.create(dat).fetch().exec(function(err, result){
if(err) {
console.log(err);
return res.send(err);
}
console.log(result)
return res.ok();
})
For more info, see the official sails documentation on .fetch() here.
Related
Trying to delete a doc Mongoose using findByIdAndDelete but im always getting back a null when I know the doc id am passing to the function exists in MongoDB
I've tried:
findByIdAndRemove
findByIdAndDelete
findOneAndDelete -> this with the code below deletes two docs rather than one!
async function deleteCourse(id)
{
const result = await Course.findByIdAndDelete(id,(err, res) => {
if (err){
console.log(err)
}
else{
console.log("Deleted course: ", res);
}
})
}
deleteCourse('5a68fdf95db93f6477053ddd')
As #Yousaf suggested, you dont need the callback function if you are using async/await function. Also use try/catch to have the same behavior.
async function deleteCourse(id)
{
try {
const result = await Course.findByIdAndDelete(id);
console.log("Deleted course: ", result);
} catch(err) {
console.log(err)
}
}
deleteCourse('5a68fdf95db93f6477053ddd')
I'm trying to pass a query to my database, then send the result to my client side, but it looks like the request is async, because my request happens after that my post request returns the value.
How do I set an await for request?
My database connection
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'my_password',
database: 'MEETME'
});
connection.connect(function(err) {
if (err) {
console.log("error while connecting to database");
console.log(err.code);
}
});
// function that query database <-------
function queryDatabase(userQuery) {
connection.query(userQuery, function(err, result) {
if (err) {
throw err;
}
console.log("before");
return result;
});
}
and this is my post request
//POST
app.post('/signin', function(request, response) {
var query = queryDatabase("SELECT EMAIL FROM MEMBER WHERE ID_MEMBER = 3");
console.log(query);
console.log("after");
response.end(query, 200);
});
the result in the console is:
undefined
after
before
Change the implementation of queryDatabase function to return a promise. Any function that returns a promise can be awaited.
function queryDatabase(userQuery){
return new Promise((resolve,reject) => {
connection.query(userQuery, function(err, result){
if(err){
reject(err);
}
console.log("before");
resolve(result);
});
});
}
app.post('/signin', async function(request, response){
var query = await queryDatabase("SELECT EMAIL FROM MEMBER WHERE ID_MEMBER = 3");
console.log(query);
console.log("after");
response.end(query, 200);
});
Welcome to Node.js where everything is intended to be asynchronous and unless you explicitly structure your code in a way that cascades one event to another there's no obligation on the part of the code to run in any particular order at all.
I'd strongly recommend picking up on Promises as a way of organizing code if you're not familiar with this concept. This wraps up a lot of tricky programming into some neat, tidy methods, and makes chaining, fan-out and fan-in actually pretty simple.
For example, rewritten with Sequelize, a database layer that uses promises:
function queryDatabase(userQuery){
console.log("before");
return connection.query(userQuery);
}
You return the promise, and that's used to chain. If you don't you must accept a callback argument and chain that through. Return values are largely ignored:
function queryDatabase(userQuery, cb){
connection.query(userQuery, function(err, result){
cb(err, result);
});
console.log("before");
}
You can see there's a lot more cruft already, and even more if you needed to build off of that. Inserting optional steps in callback driven code is tricky.
Promises make your code end up looking like this:
app.post('/signin', function(request, response){
queryDatabase("SELECT EMAIL FROM MEMBER WHERE ID_MEMBER = 3")
.then(function(results) {
console.log(results);
console.log("after");
response.end(query, 200);
});
});
It's also trivial to patch in error handling in one place with catch to handle errors.
I am using sequelize with MySQL. For example if I do:
models.People.update({OwnerId: peopleInfo.newuser},
{where: {id: peopleInfo.scenario.id}})
.then(function (result) {
response(result).code(200);
}).catch(function (err) {
request.server.log(['error'], err.stack);
).code(200);
});
I am not getting information back if the people model was succesfully updated or not. Variable result is just an array with one element, 0=1
How can I know for certain that the record was updated or not.
Here's what I think you're looking for.
db.connections.update({
user: data.username,
chatroomID: data.chatroomID
}, {
where: { socketID: socket.id },
returning: true,
plain: true
})
.then(function (result) {
console.log(result);
// result = [x] or [x, y]
// [x] if you're not using Postgres
// [x, y] if you are using Postgres
});
From Sequelize docs:
The promise returns an array with one or two elements. The first element x is always the number of affected rows, while the second element y is the actual affected rows (only supported in postgres with options.returning set to true.)
Assuming you are using Postgres, you can access the updated object with result[1].dataValues.
You must set returning: true option to tell Sequelize to return the object. And plain: true is just to return the object itself and not the other messy meta data that might not be useful.
You can just find the item and update its properties and then save it.
The save() results in a UPDATE query to the db
const job = await Job.findOne({where: {id, ownerId: req.user.id}});
if (!job) {
throw Error(`Job not updated. id: ${id}`);
}
job.name = input.name;
job.payload = input.payload;
await job.save();
On Postgres:
Executing (default): UPDATE "jobs" SET "payload"=$1,"updatedAt"=$2 WHERE "id" = $3
Update function of sequelize returns a number of affected rows (first parameter of result array).
You should call find to get updated row
models.People.update({OwnerId: peopleInfo.newuser},
{where: {id: peopleInfo.scenario.id}})
.then(() => {return models.People.findById(peopleInfo.scenario.id)})
.then((user) => response(user).code(200))
.catch((err) => {
request.server.log(['error'], err.stack);
});
Finally i got it. returning true wont work in mysql , we have to use findByPk in order hope this code will help.
return new Promise(function(resolve, reject) {
User.update({
subject: params.firstName, body: params.lastName, status: params.status
},{
returning:true,
where: {id:id }
}).then(function(){
let response = User.findById(params.userId);
resolve(response);
});
});
same thing you can do with async-await, especially to avoid nested Promises
You just need to create async function :)
const asyncFunction = async function(req, res) {
try {
//update
const updatePeople = await models.People.update({OwnerId: peopleInfo.newuser},
{where: {id: peopleInfo.scenario.id}})
if (!updatePeople) throw ('Error while Updating');
// fetch updated data
const returnUpdatedPerson = await models.People.findById(peopleInfo.scenario.id)
if(!returnUpdatedPerson) throw ('Error while Fetching Data');
res(user).code(200);
} catch (error) {
res.send(error)
}
}
There is another way - use findByPk static method and update not-static method together. For example:
let person = await models.People.findByPk(peopleInfo.scenario.id);
if (!person) {
// Here you can handle the case when a person is not found
// For example, I return a "Not Found" message and a 404 status code
}
person = await person.update({ OwnerId: peopleInfo.newuser });
response(person).code(200);
Note this code must be inside an asynchronous function.
You can fetch the model to update first, and call set() then save() on it. Returning this object will give you the updated model.
Although this might not be the shortest way to do it, I prefer it because you can handle not found and update errors separately.
const instance = await Model.findOne({
where: {
'id': objectId
}
});
if (instance && instance.dataValues) {
instance.set('name', objectName);
return await instance.save(); // promise rejection (primary key violation…) might be thrown here
} else {
throw new Error(`No Model was found for the id ${objectId}`);
}
If you're using postgres and updating one row.
try {
const result = await MODELNAME.update(req.body, {
where: { id: req.params.id },
returning: true
});
if (!result) HANDLEERROR()
const data = result[1][0].get();
res.status(200).json({ success: true, data });
} catch (error) {
HANDLEERROR()
}
I'm writing an node.js API with Mongoose,
But for the purpose of a task, I want to get the object as a variable from my find,
so I have this :
exports.get_info = function(_id) {
Session.findById(_id, function(err, session) {
if (err)
res.send(err);
console.log (session); // the object is good
return session; // trying to return it
});
};
but When I call :
session_ = sessions.get_info(id);
here session_ is undefined ...
Any ideas ?
the right way to do it is :
exports.get_info = function(_id,callback) {
Session.findById(_id, function(err, session) {
if (err)
res.send(err);
console.log (session); // the object is good
callback(null,session); // trying to return it
});
};
in this way, you can get the session like this :
sessions.get_info(id,function(err,session){
if(err) console.log(err);
console.log(session);
});
Mongoose model find it's an sync function, you can't get result immediately. You should use callback or much better solution - promise (mongoose supports promises):
exports.get_info = function(_id) {
return Session.findById(_id);
};
get_info(/* object id */)
.then(session > console.log(session))
.catch(err => console.log(err));
Ive been playing around with mongodb in node.js. I have made a basic collection with some data (i know its there ive checked). When I try to run a find() on the collection it returns undefined. I dont know why this is. The code is below:
function get_accounts(){
var MongoClient = mongodb.MongoClient;
var url = "url";
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
//HURRAY!! We are connected. :)
console.log('Connection established to database');
var collection = db.collection('accounts');
collection.find().toArray(function(err, docs) {
console.log("Printing docs from Array")
docs.forEach(function(doc) {
console.log("Doc from Array ");
console.dir(doc);
});
});
console.log("mission complete");
}
db.close();
}
);
}
If you know why this is happening i would like to hear your thoughts. thanks! The database is a mongolab hosted database if that makes any difference.
You are getting an undefined value because of the asynchronous nature of node.js, nowhere in your code exists logic that tells the console.log statement to wait until the find() statement finishes before it prints out the documents. You have to understand the concept of callbacks in Node.js. There are a few problems here, though, that you could fix. A lot of people getting started with node have the tendency to nest lots of anonymous functions, creating the dreaded "pyramid of doom" or callback hell. By breaking out some functions and naming them, you can make it a lot cleaner and easier to follow:
var MongoClient = require("mongodb").MongoClient
// move connecting to mongo logic into a function to avoid the "pyramid of doom"
function getConnection(cb) {
MongoClient.connect("your-mongo-url", function(err, db) {
if (err) return cb(err);
var accounts = db.collection("accounts");
cb(null, accounts);
})
}
// list all of the documents by passing an empty selector.
// This returns a 'cursor' which allows you to walk through the documents
function readAll(collection, cb) {
collection.find({}, cb);
}
function printAccount(account) {
// make sure you found your account!
if (!account) {
console.log("Couldn't find the account you asked for!");
}
console.log("Account from Array "+ account);
}
// the each method allows you to walk through the result set,
// notice the callback, as every time the callback
// is called, there is another chance of an error
function printAccounts(accounts, cb) {
accounts.each(function(err, account) {
if (err) return cb(err);
printAccount(account);
});
}
function get_accounts(cb) {
getConnection(function(err, collection) {
if (err) return cb(err);
// need to make sure to close the database, otherwise the process
// won't stop
function processAccounts(err, accounts) {
if (err) return cb(err);
// the callback to each is called for every result,
// once it returns a null, you know
// the result set is done
accounts.each(function(err, account) {
if (err) return cb(err)
if (hero) {
printAccount(account);
} else {
collection.db.close();
cb();
}
})
}
readAll(collection, processAccounts);
})
}
// Call the get_accounts function
get_accounts(function(err) {
if (err) {
console.log("had an error!", err);
process.exit(1);
}
});
You might have to add an empty JSON object inside the find.
collection.find({})
Documentation can be found here.
You must enter this code in an async function and you will be fine here data is the your desired value and you must use promises to not make your code look messy.
var accountCollection = db.collection('accounts);
let data = await accountCollection.find().toArray.then(data=>data).catch(err=>err);