Sergeon
Sergeon

Reputation: 6788

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.

Upvotes: 0

Views: 1792

Answers (1)

Sergeon
Sergeon

Reputation: 6788

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!
    })
})

Upvotes: 1

Related Questions