MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Usando funções JavaScript armazenadas no pipeline de agregação, MapReduce ou runCommand


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.