在$ where中调用db.system.js函数

时间:2016-04-22 20:10:36

标签: javascript php mongodb mongodb-query

作为一个基本的例子,我保存了这个功能:

db.system.js.save({_id: "sum", value: function (x, y) { return x + y; }});

但是当我试图调用$时,我得到的参考文献不存在。

<?php

$collection = $link -> selectCollection('foo' ,'bar');
$collection -> find(array(
'$where' =>'sum(this.x, this.y)'
));

?>

错误

ReferenceError: sum is not defined :

我应该保存还是以其他方式访问它?

1 个答案:

答案 0 :(得分:1)

您是否在使用shell连接到的PHP代码中连接到相同的数据库命名空间?我想不是!

无论如何,你在这种情况下误解了$where的概念,因为你只能评估而不是返回修改后的结果,而不是已包含在集合。

唯一能够实际返回与现有文档不同的内容的是.mapReduce().aggregate()

如果你定义一个集合,那么在“相同的命名空间”中进行演示:

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

然后运行.mapReduce()

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

那将返回实际的总结结果:

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

$where可以做的所有事情都是“逻辑地”选择文档:

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

哪个不符合条件。

但是当然你真的不需要这样做,并且通常应尽可能避免任何服务器执行JavaScript。它比本机运算符慢得多,你可以用本机运算符做很多事情。

而不是.mapReduce()致电.aggregate()

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

而不是JavaScript评估,请再次致电.aggregate(),使用$redact进行“逻辑”过滤:

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

因此,在大多数情况下,使用JavaScript评估总是有更好的选择。当然,在实际需要进行JavaScript评估的情况下,实际上很少需要服务器存储函数。

但是你的基本错误是因为函数位于不同的命名空间中,或者确实是你重新启动了服务器。但总的来说,你可能不应该使用存储的函数。