Profiling mongoose methods - node.js

I want to see logs of calling methods for all my mongoose methods, like this:
# Load Book
LoadBook = (id, cb) ->
console.log 'loading book...'
Book.findById id, (err, book) ->
if err
console.log err
throw err
console.log 'loaded book: ' + book.title
cb book
I guess I can define post and pre methods like this:
BookSchema.pre 'save', (next) ->
console.log 'loading ' + `model_name(don't know how to get it)` + ' ...'
next()
And the same for other methods like findById or remove but it's long. And the error handling works only if I don't use callbacks, but I use it every time. I mean:
Part.on 'error', (err) ->
console.log "Got an error", err
I think it doesn't work when there is a callback, does it?
Perhaps there is some universal profiler in nodejs? I'm using express by the way.

You can enable debug logging in Mongoose by calling:
mongoose.set('debug', true);
With that enabled you'll get a log entry for every MongoDB operation made via Mongoose. Not sure if it's exactly what you want, but it's worth giving it a try.

You can use look module to profile your node.js app. It based on nodetime but works on local server.

Related

how to use mongo db.eval through Mongoose

From my mongo shell I can run functions with db.eval like:
db.eval('return 7;');
And, but for a deprecation warning, the parameter function is run properly.
Now I want to call such a 'script' from node.js, through mongoose.
I've tried to just call db.eval with the stringified function code as parameter (as in here):
mongoose.connect(PATH_TO_A_MONGO_DATABASE);
mongoose.connection.db.eval('return 9;', function(err, result){
console.log(result);
//etc.
});
This silently ignores the callback. No error is thrown, and the callback function is never called.
When doing this, I checked that mongoose.connection.db.eval is actually a function.
Since db.eval also has a Promise interface, also tried:
mongoose.connection.db.eval('return 5;').then(console.log).catch(console.log);
With the same result: no errors, just silence.
So, I guess I'm missing something with the syntax, but I can't find documentation or examples about this. Any similar questions like this or this didn't help.
PD1: I'm willing to do this because I need to call a procedure stored in system.js through mongoose. I can't do that too. However, I can't even run a silly script like return 5;, so I'm asking for the simpler task before. Any advice on how to call server scripts with mongoose is welcome.
PD2: I'm aware stored server scripts in mongo are a bad practice, and that they are deprecated for a reason and so on... but I can't just decide about that. I've been told to do that at my company, and the co-worker who set up the original code of the stored server script is not here now.
Ok, I figured out why my db.eval callbacks was being ignored. It is related with the mongoose connection.
If you start a connection like:
const conn = mongoose.connect(PATH_TO_DB);
And then just make a query:
conn.model(a_collection, a_schema).find({}).exec().then()...
Even if you just call the query right after the connection -it is, logically, an asynchronous process-, mongooose figures that it has to wait to the connection to be in a proper state, then fire the query, then call the callback with the query results.
However, this doesn't work the same way with db.eval(). just trying to call db.eval() right after the call to the connection, the callback is silently ignored:
const conn = mongoose.connect(PATH_TO_DB);
conn.db.eval('return 5;', (err, response) => {
//nothing happends
})
That was the way I was creating the connection and calling db.eval, so I couldn't get db.eval() to work.
In order to fire a db.eval and make it work, it seems that you need to wait for the connection explicitly:
const conn = mongoose.connect(PATH_TO_DB, err => {
mongoose.connection.db.eval('return 5', (err, result) => {
result; //5!
})
});
To make a query before any attemps to call db.eval also works:
const conn = mongoose.connect(PATH_TO_DB);
conn.model(a_collection, a_schema).find({}).exec()
.then(() => {
conn.db.eval('return 5', (err, result) => {
result; //5!
})
})

if statement in node.js with with some mongoose query

Im trying to write an if statement in Node.js with some mongoose query but the if statement does not get executed correctly.
So I'm doing this:
app.get('Job/GetJobs', function(req,res){
if(JobDB.Find()==null){
req.render('home.html');
}
else req.render('Job.html')
})
But the above code works if it was in java but not in Node.js because req.render('home.html'); gets executed before JobDB.find() finishes.
Most functions in Node.js are asynchronous, so you need to use a callback:
app.get('Job/GetJobs', function(req,res){
JobDB.find({}, function(err, result) {
if(!result) req.render('home.html')
else req.render('Job.html')
})
})
(you'll have to include some error handling there)
See the documentation: http://mongoosejs.com/docs/2.7.x/docs/finding-documents.html

Error handling in node-sqlite3

How do I handle error in sqlite3? For example, I have this simple code:
var stmt = db.prepare("update Tickets set " + columns + " where id = (?)");
stmt.run(req.body.id);
stmt.finalize();
db.close();
All four functions prepare, run, finalize, close has the potential to throw error. This is on my express.js server so I'm trying to put a res.error() statement somewhere to return result. I don't want to put it in all of them because I can run into a multiple res.setHeader error.
Is there a document on error handling practice with sqlite3? I can't find it in its API documentation.
Take a look at the api. Each of those functions takes a callback, whose first parameter is an error.
This will help you handle an error, but it will not stop your app from crashing. In order to stop a crash, you'll have to use a try/catch , or preferably learn how to use domains.
Errors are emitted on "error" event.
you may want to try doing something like below after you initialise your db handle.
db.on("error", function(error) {
console.log("Getting an error : ", error);
});

Execute a server-side function from MongoClient in node.js

I've created a set of functions on my MongoDB server that I'd like to be able to use from MongoClient in my nodejs scripts. All of the documentation I've read tells me how to do this, but from the shell only it seems.
How it would normally work in the shell:
mongo database my.script.js
mongo
> use database
> db.loadServerScripts()
> add("This is a string taken in by the add function I just loaded")
This is what I've tried/looked into (mind the CoffeeScript):
MongoClient = require('mongodb').MongoClient
MongoClient.connect 'mongodb://127.0.0.1:27017/database', (e, db) ->
console.log db.eval #Function, but not sure what to call with
console.log db.runCommand #undefined
console.log db.loadServerScripts #undefined
console.log db.load #undefined
console.log db.command #Function, but not sure what to call with
console.log db.add #this is one of my custom functions
Hopefully this is possible with MongoClient. It seems as though I could use eval() if I can manage to load the script, but that's proving to be the difficult part so far. Alternatively, I suppose I could minify my functions and run those through eval(), but I'd prefer not to do that.
You can use eval (it looks like you don't need to load any functions first, the load command is only to make the functions available from the shell):
db.eval('add("This is a string taken in by the add function I just loaded")', function(err, result) {
...
});
Or, if you want to be a bit more flexible in passing arguments:
db.eval('function(x) { return add(x); }', [ ARG ], function(err, result) { ... });
(it seems that you can't just use 'add' as first argument, you need to wrap it in an anonymous function first, but I might be missing something...)

mongodb crashed node with exception within try catch

try
p = req.params.name
Item.update('name': p, req.body , {upsert: true}, (err) ->
if err?
throw err
res.send("ok")
)
catch e
handle_error(e, "Error salvando hoja de vida.", res)
This produces an error in my code right now - that's alright, but why does my nodejs program crash even if I have a try catch here?
The error is:
MongoError: Mod on _id not allowed
(so it must be in the update call)
I am specifically looking for a way to catch an error, I already know how to get rid of it.
Ah yes, you have entered the realm of asynchronous code. The reason you pass a callback into your MongoDB calls like Item.update(..., callback) is because the MongoDB driver is written to be asynchronous. Consider this (mongoose code):
var user = User.findOne({ name: 'joe' });
doSomethingElse();
If it had structured its API like the above code then your entire application would halt until User.findOne() returned the results from the database. Your doSomethingElse() call wouldn't be invoked until the user was retrieved, even if you don't do anything with user inside doSomethingElse. This is a big no no these days and especially in node which has been written to be asynchronous as much as possible. Have a look at the following:
User.findOne({ name: 'joe' }, function (err, user) {
if (err) return console.error(err);
console.log('Do stuff with user... ;)');
});
doSomethingElse();
The above code is asynchronous. The findOne function returns immediately and doSomethingElse is able to begin even before the user is ever retrieved from the database. But of course we still want to do stuff with our user, so in order to accomplish this we pass an anonymous function in to be used as a callback. The MongoDB driver is smart enough to call that function when it's all done retrieving data.
Wrapping the above code in a try/catch would be pointless, unless you suspected the findOne function to throw an exception (Which you shouldn't. It returns immediately remember?).
try {
User.findOne({ name: 'joe' }, function (err, user) {
throw new Error("Something went wrong...");
});
} catch (err) {
console.error(err);
}
The above error would still crash your program because it happened long after findOne returned and your program moved on way beyond that precious try/catch. This is the very reason why your callback function receives an err argument. The MongoDB driver knows that if some error occurs while fetching your data it would be no good to throw an exception and call it good. This is because all this processing has happened later on subsequent trips through the event loop, having left your try/catch behind several iterations ago.
To get around this the MongoDB driver wraps its own internal synchronous code in a try/catch where it actually will handle the exception and then it invokes your callback passing in the error as the first argument. This allows you to check that argument and handle any errors within your callback.
I wrote an entire blog post explaining callbacks, as well as another way of handling asynchronous code called "promises" and I think it would help clarify some things for you :) http://codetunnel.io/what-are-callbacks-and-promises
I hope that helps answer your question.
Maybe I'm wrong (because I don't know Coffeescript), but I suppose the problem is, that your try/catch is outside the callback function. The catch doesn't affect your err -> so the exception is not caught by you, but by node.js.
If I'm wrong, could you perhaps provide the compiled JavaScript code?
Edit
Usually one would handle the error more like this (without try/catch):
Item.update('name': p, req.body , {upsert: true}, (err) ->
if err?
log.error('error updating Item name=' + name)
res.status(500).end()
return
res.send("ok")
)
Probably your handle_error will do this already.
When programming in node.js, I use try/catch only for JSON.parse or if I have a lot of unchecked input which might have wrong types or might be null and I'm too lazy to check all input manually. Surrounding asynchronous functions with try/catch is only helpful if the function has programming errors (e.g. not checking your input correctly).

Resources