作为一个基本的例子,我保存了这个函数:
db.system.js.save({_id: "sum", value: function (x, y) { return x + y; }});
但是当我尝试调用$where时,我得到一个不存在的引用。
<?php
$collection = $link -> selectCollection('foo' ,'bar');
$collection -> find(array(
'$where' =>'sum(this.x, this.y)'
));
?>
和错误
ReferenceError: sum is not defined :
我应该保存它还是以其他方式访问它?
您是否连接到
使用 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 评估的情况下,实际上很少有情况真正需要服务器存储函数。
但是您在此处的基本错误是因为该函数位于不同的命名空间中,或者实际上您在两者之间重新启动了服务器。但总的来说,你可能不应该使用存储函数。