Skip to content Skip to sidebar Skip to footer

Calling Db.system.js Function In $where

As a basic example, I have this function saved: db.system.js.save({_id: 'sum', value: function (x, y) { return x + y; }}); But when I try to called in the $where I get a Reference

Solution 1:

Are you connecting to the same database namespace in your PHP code that you connected to using the shell? I think not!

Anyway you misunderstand the concept of $where in this context, since you can only evaluate and not return modified results other than the data already contained in the collection.

The only things that can actually return something different than the existing documents are .mapReduce() and .aggregate().

So to demonstrate, in the "same namespace" if you define a collection:

db.djunk.insert({ "x": 1, "y": 2 })

And then run a .mapReduce()

db.dbjunk.mapReduce(
    function() {
        emit(this._id, sum(this.x,this.y))
    },
    function() {}, // does nothing here where already unique
    { "out": { "inline": 1 } }
)

That would return an actual summed result:

{
    "_id" : ObjectId("571a9bb951d042a7a896fd92"),
    "value" : 3
}

All that $where can do, is "logically" select the document:

db.djunk.find(function() {
    returnsum(this.x,this.y) > 3
})

Which would not meet the condition.

But of course you really don't need to do this, and should generally be avoiding any server execution of JavaScript where possible. It's much slower than native operators, and you can do quite a bit with native operators.

So instead of .mapReduce() call .aggregate():

db.djunk.aggregate([
    { "$project": {
        "total": { "$add": [ "$x", "$y" ] }
    }}
])

And instead of JavaScript evaluation, call .aggregate() again, with $redact for "logical" filtering:

db.djunk.aggregate([
    { "$redact": {
        "$cond": {
            "if": { "$gt": [ { "$add": [ "$x", "$y" ] }, 3 ] },
            "then": "$$KEEP",
            "else": "$$PRUNE"
        }      
    }}
])

So in most cases there is always a better alternative to using JavaScript evaluation. And certainly there are actually very few cases to really need server stored functions in the cases where JavaScript evaluation is actually required.

But your basic error here will be because the function was in a different namespace, or indeed that you restarted the server in between. But the overall point is you probably should not be using stored functions anyway.

Post a Comment for "Calling Db.system.js Function In $where"