Qualquer função que você salvar em
system.js
está disponível para uso por instruções de processamento "JavaScript", como $where
operador e mapReduce
e pode ser referenciado pelo _id
o valor foi atribuído. db.system.js.save({
"_id": "squareThis",
"value": function(a) { return a*a }
})
E alguns dados inseridos na coleção "amostra":
{ "_id" : ObjectId("55aafd2bacbed38e06f9eccf"), "a" : 1 }
{ "_id" : ObjectId("55aafea6acbed38e06f9ecd0"), "a" : 2 }
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
Então:
db.sample.mapReduce(
function() {
emit(null, squareThis(this.a));
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
);
Dá:
"results" : [
{
"_id" : null,
"value" : 14
}
],
Ou com
$where
:db.sample.find(function() { return squareThis(this.a) == 9 })
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
Mas em "nenhum" caso você pode usar globais como o banco de dados
db
referência ou outras funções. Ambos $where
e mapReduce
documentação contém informações dos limites do que você pode fazer aqui. Portanto, se você pensou que faria algo como "pesquisar dados em outra coleção", pode esquecê-lo porque é "Não permitido". Toda A ação do comando MongoDB é na verdade uma chamada para uma ação "runCommand" "sob o capô" de qualquer maneira. Mas, a menos que o que esse comando esteja realmente fazendo seja "chamar um mecanismo de processamento JavaScript", o uso se torna irrelevante. Existem apenas alguns comandos que fazem isso, sendo
mapReduce
, group
ou eval
e, claro, as operações de localização com $where
. A estrutura de agregação não usar JavaScript de qualquer maneira. Você pode estar se equivocando assim como outros fizeram uma declaração como esta, que não faz o que você pensa que faz:
db.sample.aggregate([
{ "$match": {
"a": { "$in": db.sample.distinct("a") }
}}
])
Portanto, "não está sendo executado dentro " o pipeline de agregação, mas sim o "resultado" desse
.distinct()
chamada é "avaliada" antes que o pipeline seja enviado ao servidor. Assim como com uma variável externa é feito de qualquer maneira:var items = [1,2,3];
db.sample.aggregate([
{ "$match": {
"a": { "$in": items }
}}
])
Ambos essencialmente enviam para o servidor da mesma maneira:
db.sample.aggregate([
{ "$match": {
"a": { "$in": [1,2,3] }
}}
])
Portanto, "não é possível" "chamar" qualquer função JavaScript no pipeline de agregação, nem há realmente nenhum ponto em "passar" resultados em geral de algo salvo em
system.js
. O "código" precisa ser "carregado no cliente" e apenas um mecanismo JavaScript pode realmente fazer alguma coisa com ele. Com a estrutura de agregação, todos os "operadores" disponíveis são, na verdade, funções codificadas nativamente, em oposição à interpretação JavaScript de "forma livre" fornecida para
mapReduce
. Então, em vez de escrever "JavaScript", você usa os próprios operadores:db.sample.aggregate([
{ "$group": {
"_id": null,
"sqared": { "$sum": {
"$multiply": [ "$a", "$a" ]
}}
}}
])
{ "_id" : null, "sqared" : 14 }
Portanto, há limitações sobre o que você pode fazer com funções salvas em system.js, e as chances são de que o que você deseja fazer seja:
- Não permitido, como acessar dados de outra coleção
- Não é realmente necessário, pois a lógica geralmente é independente
- Ou provavelmente melhor implementado na lógica do cliente ou outra forma diferente
Apenas sobre o único uso prático que eu posso realmente pensar é que você tem um número de operações "mapReduce" que não podem ser feitas de outra maneira e você tem várias funções "compartilhadas" que você prefere apenas armazenar no servidor do que manter dentro de cada chamada de função mapReduce.
Mas, novamente, a razão de 90% para mapReduce sobre a estrutura de agregação é geralmente que a "estrutura do documento" das coleções foi mal escolhida e a funcionalidade JavaScript é "necessária" para percorrer o documento para pesquisa e análise.
Portanto, você pode usá-lo sob as restrições permitidas, mas na maioria dos casos você provavelmente não deveria estar usando isso, mas corrigindo os outros problemas que fizeram você acreditar que precisava desse recurso em primeiro lugar.