0

I'm trying to use MongoDB server-side JavaScript in my nodejs/node-mongodb-native project and just interested how could I save my custom functions in global context of MongoDB and get access to them from db.eval script?

Let's say I have the following unit function:

var myDocumentUtils = {
    doStuff: function (doc) {
       // do stuff with doc ...
       return doc;      
    }
}

And I have the following JavaScript function stored in db.system.js collection:

function processDocument (id) {
    var doc = db.myCollection.findOne({ _id : ObjectId(id)});

    doc = myDocumentUtils.doStuff(doc);   // need access to global myDocumentUtils object     
    db.myCollection.save(doc);

    return doc;
};

I execute processDocument function from my nodejs application like the following:

db.eval('processDocument(54382cb3233283cd3331ca1d)', function (err, doc) {
    if (err) throw err;       
});

So my question is how to save myDocumentUtils in global MongoDB V8 context to be accessible in db.eval function?

Azzabi Haythem
  • 2,318
  • 7
  • 26
  • 32
Erik
  • 14,060
  • 49
  • 132
  • 218

1 Answers1

1

Add the second parameter to processDocument as below:

function processDocument (id, myDocumentUtils) {
    var doc = db.myCollection.findOne({ _id : ObjectId(id)});

    doc = myDocumentUtils.doStuff(doc);   // need access to global myDocumentUtils object     
    db.myCollection.save(doc);

    return doc;
};

Then write db.eval() like this way:

db.eval(function() {
    return processDocument.apply(this, arguments);
}, "54382cb3233283cd3331ca1d", myDocumentUtils);

For your environment, you can add the call back just behind the last parameter myDocumentUtils.


APPEND ---------------------

store below tow functions into db.system.js :

function getMyDocumentUtils() {
    return myDocumentUtils = {
            doStuff: function (doc) {
               // do stuff with doc ...
               return doc;      
            }
        };
}

function processDocument (id) {
    var doc = db.myCollection.findOne({ _id : ObjectId(id)});

    var myDocumentUtils = getMyDocumentUtils(); // added line

    doc = myDocumentUtils.doStuff(doc);   // need access to global myDocumentUtils object     
    db.myCollection.save(doc);

    return doc;
};

Then call db.eval() as your original style.

Wizard
  • 4,341
  • 1
  • 15
  • 13
  • thanks for the response but I can't pass JavaScript object to eval functions because I use nodejs. Is there any solutions yet? – Erik Oct 11 '14 at 13:21
  • @Erik, as you are able to store `processDocument` into database, could you also store another function used to return `myDocumentUtils`? This function can be called by `processDocument`. – Wizard Oct 11 '14 at 14:01
  • could you provide some example please because I little don't understand your suggestion :( – Erik Oct 11 '14 at 14:13
  • @Wizardt Thanks you. I do understand your advice and this very cool for me. As I also understand getMyDocumentUtils returns function that evaluates on every call? It it possible to evaluate this function one for performance reasons? – Erik Oct 11 '14 at 14:52
  • Can I store two javascript functions in `db.system.js`? – Erik Oct 11 '14 at 15:09
  • @Erik, if you need to call `getMyDocumentUtils` frequently, it will be evaluated every time. To avoid this situation, could you write and store function `doStuff()` directly? I mean you can call `doStuff()` directly from `processDocument()`. – Wizard Oct 11 '14 at 15:44
  • @Erik, you can store any JS function into `db.system.js` by `db.system.js.insert({_id:"functionName", value:})`. And they are global. – Wizard Oct 11 '14 at 15:46
  • Thanks for the help. So if I will store `db.system.js.insert({_id:"functionName1", value:})` and `db.system.js.insert({_id:"functionName2", value:})` in separate documents, they are accessible for each other? – Erik Oct 11 '14 at 18:03