当我使用nodejs中“$ where”子句中传递的函数查询我的数据库时,它总是返回db中的所有文档。
例如,如果我这样做
var stream = timetables.find({$where: function() { return false; }}).stream();
它将所有文件归还给我。 相反,如果我做
var stream = timetables.find({$where: 'function() { return false; }'}).stream();
该函数实际执行,此代码不返回任何文档。
问题是,如果我在字符串my function中转换上下文的绑定被删除,我需要它们来进行更复杂的查询。例如:
var n = 1;
var f = function() { return this.number == n; }
var stream = timetables.find({$where: f.toString()}).stream();
// error: n is not defined
这是正常行为吗?我怎样才能解决我的问题? 请原谅我的英语不好!
答案 0 :(得分:4)
首先请注意,$where
运算符几乎不应该用于here解释的原因(功劳归于@WiredPrairie)。
回到你的问题,你想采取的方法即使在mongodb shell中也是行不通的(mongodb shell明确允许使用$where
运算符的裸js函数)。提供给$where
运算符的javascript代码在mongo服务器上执行,无法访问封闭环境(“上下文绑定”)。
> db.test.insert({a: 42})
> db.test.find({a: 42})
{ "_id" : ObjectId("5150433c73f604984a7dff91"), "a" : 42 }
> db.test.find({$where: function() { return this.a == 42 }}) // works
{ "_id" : ObjectId("5150433c73f604984a7dff91"), "a" : 42 }
> var local_var = 42
> db.test.find({$where: function() { return this.a == local_var }})
error: {
"$err" : "error on invocation of $where function:\nJS Error: ReferenceError: local_var is not defined nofile_b:1",
"code" : 10071
}
此外,看起来node.js本机mongo驱动程序的行为与shell不同,因为它不会自动序列化您在查询对象中提供的js函数,而是可能完全删除该子句。这将为您留下相当于timetables.find({})
的内容,它将返回集合中的所有文档。
答案 1 :(得分:2)
这个适用于我,只是尝试将查询作为字符串存储在一个变量中,然后在查询字符串中连接您的变量,
var local_var = 42
var query =" {$ where:function(){return this.a ==" + local_var +"}}"
db.test.find(查询)
答案 2 :(得分:2)
将查询存储到varibale中,并在查找查询中使用该变量。它有效.....:D
答案 3 :(得分:1)
上下文将始终是mongo数据库的上下文,因为该函数在那里执行。无法共享两个实例之间的上下文。你必须重新思考你的查询方式并提出不同的策略。
答案 4 :(得分:1)
您可以使用包装器传递基本的JSON对象,即。 (原谅咖啡脚本):
# That's the main wrapper.
wrap = (f, args...) ->
"function() { return (#{f}).apply(this, #{JSON.stringify(args)}) }"
# Example 1
where1 = (flag) ->
@myattr == 'foo' or flag
# Example 2 with different arguments
where2 = (foo, options = {}) ->
if foo == options.bar or @_id % 2 == 0
true
else
false
db.collection('coll1').count $where: wrap(where1, true), (err, count) ->
console.log err, count
db.collection('coll1').count $where: wrap(where2, true, bar: true), (err, count) ->
console.log err, count
您的功能将按以下方式传递:
function () {
return (function (flag) {
return this.myattr === 'foo' || flag;
}).apply(this, [true])
}
...和示例2:
function () {
return (
function (foo, options) {
if (options == null) {
options = {};
}
if (foo === options.bar || this._id % 2 === 0) {
return true;
} else {
return false;
}
}
).apply(this, [ true, { "bar": true } ])
}
答案 5 :(得分:0)
这是应该的样子。驱动程序不会将客户端代码转换为mongo函数javascript代码。
答案 6 :(得分:0)
我假设您正在使用Mongoose来查询您的数据库。
如果您查看实际的Query对象实现,您会发现只有 strings 是where prototype的有效参数。
当使用where子句时,您应该将它与标准运算符一起使用,例如gt,lt在where函数创建的路径中运行。
请记住Mongoose查询,例如在Mongo中,例如,您可能想以更具描述性的方式重新考虑您的查询规范。