Mongodb $onde a pesquisa é sempre verdadeira com os nodejs
Quando questiono a minha base de dados com uma função passada na cláusula "$where" em nodejs, ela devolve-me sempre todos os documentos no db.
por exemplo, se eu fizer
var stream = timetables.find({$where: function() { return false; }}).stream();
Devolve-me todos os documentos.
Em vez disso, se eu fizer
var stream = timetables.find({$where: 'function() { return false; }'}).stream();
a função é realmente executada, e este código não devolve nenhum documento.
o problema é que se eu converter em cadeia a minha função os bindindindindinds do contexto são removidos, e eu preciso deles para uma consulta mais complexa. Para exemplo:
var n = 1;
var f = function() { return this.number == n; }
var stream = timetables.find({$where: f.toString()}).stream();
// error: n is not defined
Isto é um comportamento normal? Como posso resolver o meu problema?
Por favor, desculpem-me pelo meu pobre Inglês!
7 answers
Em primeiro lugar, tenha em mente que o operador $where
quase nunca deve ser usado pelas razões explicadas aqui (o crédito vai para @WiredPrairie).
$where
). O código javascript fornecido ao operador $where
é executado no servidor mongo e não terá acesso ao ambiente envolvente (o "contexto" ligacoes").
> 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
}
Além disso, parece ser o nó.o driver nativo do js mongo comporta-se de forma diferente da shell, na medida em que não serializa automaticamente uma função js que você fornece no objeto de consulta e, em vez disso, provavelmente retira a cláusula completamente. Isto deixá-lo-á com o equivalente a timetables.find({})
que devolverá todos os documentos da colecção.
Este funciona para mim, basta tentar armazenar uma consulta como uma string em uma variável, em seguida, concate a sua variável em query string,
Var local_var = 42
Var query = " {$where: function () {return this.a = " +local_var+"}}"
Db.teste.find (query)
Guarde a sua consulta numa varibale e use essa variável na sua pesquisa de procura. Funciona..... : D
O contexto será sempre o da base de dados mongo, uma vez que a função é executada lá. Não há como compartilhar o contexto entre as duas instâncias. Você tem que repensar a maneira como você consulta e chegar a uma estratégia diferente.
Pode usar uma embalagem para passar os objectos JSON básicos, ou seja. (pardon coffee-script):
# 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
As tuas funções vão passar por algo como:
function () {
return (function (flag) {
return this.myattr === 'foo' || flag;
}).apply(this, [true])
}
...e Exemplo 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 } ])
}
Presumo que esteja a usar Mangusto para consultar a sua base de dados.
Se der uma vista de olhos na implementação do objecto de pesquisa actual, irá descobrir que apenas as cadeias são argumentos válidos para o onde o protótipo .
Ao usar a cláusula onde, você deve usá-la juntamente com os operadores padrão, como gt, lt, que opera no caminho criado pela função onde.
Lembre-se que o mangusto questionando, como em Mongo, é por exemplo, você pode quer reconsiderar a sua especificação de consulta de uma forma mais descritiva.