我有一个MongoDB查询,它搜索搜索变量中定义的值的所有属性。它的工作方式如下:
db.collection.findOne({
$where: function() {
var search = 'searchstring';
for (var key in this) {
if (this[key] === search) {
return true;
}
return false;
}
}
});
但是,我想在查询之外定义搜索变量。
但是当我这样做时,我收到一个错误,指出它没有被引用(即范围问题(:
"ReferenceError: search is not defined near '[key] === search
如何使用变量或将变量传递给查询筛选器?
你可以尝试这样的事情:
var searchstring = 'whatever';
var params = {};
params.$where = 'function() {' +
'var search = "' + searchstring + '";' +
'for (var key in this) {' +
'if (this[key] === search) {' +
'return true;' +
'}' +
'return false;' +
'}' +
'}';
db.collection.findOne(params);
(字符串化你的函数并与外部变量连接(
通过猫鼬为我工作
search
是您在客户端中定义的变量,可以是shell或任何客户端API。
为 $where
子句定义的函数不会在客户端执行,而是在mongodb
服务器上执行。因此,当函数在服务器端被解释并查找search
变量时,它从未在服务器上定义过,因此您会收到错误。
在您的情况下,您希望变量 search
,在服务器上执行之前由客户端替换为其内容。这是不可能的,除非您在客户端构建函数内容本身。
客户端永远不会真正解释你在匿名函数中编写的任何内容。服务器这样做。您看到的错误来自服务器。您可以通过触发此查询并查看服务器日志来验证它:
2015-12-22T19:03:44.011-0800 I QUERY [conn1] assertion 16722 ReferenceError:
searc is not defined
at _funcs1 (_funcs1:1:39) near 's.key === searc){retu' ns:test.t query:{ $w
here: function (){if(this.key === searc){return true}} }
有一种更好的方法来使用 $exists
运算符编写您希望实现的目标。
var search = "title";
var find = {};
find[search] = {$exists:true};
db.collection.findOne(find);
这是有效的,因为您可以在将查询参数传递给 findOne()
方法之前完全在客户端构建查询参数。
您可以使用mongodb地图缩减和范围功能解决此问题。作用域允许您将变量传递到映射归约作业中。
function map() {
for (var key in this) {
if (this[key] === search) {
return emit(this._id, this);
}
}
}
function reduce(key, values) {
return values[0];
}
db.collection.mapReduce(map, reduce, {
out: {inline: 1},
scope: {
search: 'searchstring'
}
}
);