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

Média de um campo de subdocumento em documentos no Mongo


Você precisará usar a estrutura de agregação. A agregação vai ficar mais ou menos assim:
db.stack.aggregate([
  { $match: { "samples.key" : "test-key" } },
  { $unwind : "$samples" },
  { $match : { "samples.key" : "test-key" } },
  { $project : { "new_key" : "$samples.key", "new_value" : "$samples.value" } },
  { $group : { `_id` : "$new_key", answer : { $avg : "$new_value" } } }
])

A melhor maneira de pensar na estrutura de agregação é como uma linha de montagem. A consulta em si é uma matriz de documentos JSON, onde cada subdocumento representa uma etapa diferente na montagem.

Etapa 1:$match


A primeira etapa é um filtro básico, como uma cláusula WHERE no SQL. Colocamos esta etapa primeiro para filtrar todos os documentos que não contêm um elemento de matriz contendo test-key . Colocar isso no início do pipeline permite que a agregação use índices.

Etapa 2:$descontrair


A segunda etapa, $unwind , é usado para separar cada um dos elementos na matriz "amostras" para que possamos realizar operações em todos eles. Se você executar a consulta com apenas essa etapa, verá o que quero dizer. Resumindo:
{ name : "bob", 
  children : [ {"name" : mary}, { "name" : "sue" } ] 
} 

torna-se dois documentos:
{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }

Etapa 3:$match


A terceira etapa, $match , é uma duplicata exata do primeiro $match palco, mas tem um propósito diferente. Como segue $unwind , esse estágio filtra os elementos anteriores da matriz, agora documentos, que não correspondem aos critérios do filtro. Nesse caso, mantemos apenas documentos em que samples.key = "test-key"

Etapa 4:$project (opcional)


A quarta etapa, $project , reestrutura o documento. Nesse caso, retirei os itens do array para poder referenciá-los diretamente. Usando o exemplo acima..
{ name : "bob", children : [ { "name" : mary } ] }

torna-se
{ new_name : "bob", new_child_name : mary }

Observe que esta etapa é totalmente opcional; etapas posteriores podem ser concluídas mesmo sem este $project após algumas pequenas alterações. Na maioria dos casos $project é inteiramente cosmético; agregações têm inúmeras otimizações sob o capô, como incluir ou excluir campos manualmente em um $project não deve ser necessário.

Etapa 5:$grupo


Finalmente, $group é onde a mágica acontece. O _id valorize o que você estará "agrupando" no mundo SQL. O segundo campo está dizendo para calcular a média sobre o valor que defini no $project Passo. Você pode substituir facilmente $sum para realizar uma soma, mas uma operação de contagem normalmente é feita da seguinte maneira:my_count : { $sum : 1 } .

A coisa mais importante a ser observada aqui é que a maior parte do trabalho que está sendo feito é formatar os dados até um ponto em que a execução da operação seja simples.

Observação final


Por fim, gostaria de observar que isso não trabalhe nos dados de exemplo fornecidos desde samples.value é definido como texto, que não pode ser usado em operações aritméticas. Se você estiver interessado, a alteração do tipo de um campo está descrita aqui:MongoDB Como alterar o tipo de um campo