0

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.

1
  • 1
    Eval is deprecated ( marked from v3.0.0 ). Which means DO NOT USE IT. Because even if it is not gone yet, it IS going. And when it's gone your code will simply not work. You don't need serverside JavaScript execution anyway. It's simply the wrong approach. Commented Oct 23, 2017 at 10:51

1 Answer 1

1

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!
    })
})
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.