quinta-feira, 29 de agosto de 2013

     Olá. No post de hoje vamos estudar o framework de agregação do MongoDB. Os Aggregations são operações que processam os documentos de uma colletion de acordo com uma estrutura de pipeline que usamos para ordenar as etapas de computação dos dados. Podemos agrupar documento semelhantes, tratar os conteúdos de arrays, realizar cálculos matemáticos, concatenar strings, dentre muitas outras aplicações.

     Para quem é familiarizado com a linguagem SQL, abaixo temos uma tabela mostrando as operações equivalentes no MongoDB. Fonte da tabela e exemplos: docs.mongodb.org


     Vamos para a prática. Utilizaremos o dataset zips, que mostramos em nosso post CRUD Operations no MongoDB - Parte 1. Lembrando a estrutura do documento:

{
     "_id": "10280",
     "city": "NEW YORK",
     "state": "NY",
     "pop": 5574,
     "loc": [
          -74.0163,
          40.7105
          ]
}

      Nos orientando pela tabela acima, vamos encontrar os estados com população superior a 10 milhões de habitantes. Para isso:

db.zipcodes.aggregate( {$group:
                                      {_id: "$state",
                                        totalPop: {$sum: "$pop"}
                                       }
                                      },
                                     { $match: {totalPop: {$gte: 10000000}
                                                     }
                                      }
                                    )

     Com esta estrutada, podemos entender como funciona o pipeline do aggregation framework. O operador $group agrega todos os documentos e cria novos documentos por estado, indicado pelo _id: "$state". Em seguida, somamos o campo pop e inserimos o resultado em totalPop. Por fim, usamos o $match para encontrar apenas os estados com totalPop maior ou igual a 10 milhões. Em SQL, teríamos:

SELECT state, SUM(pop) AS totalPop
                FROM zips
                GROUP BY state
                HAVING totalPop > (10000000)

     Aumentando a complexidade, vamos encontrar as maiores e menores cidade, em população, por estado:

db.zips.aggregate( { $group:
                                 { _id: { $state: "$state", city, "$city"},
                                    pop: {$sum: "$pop"} } },
                             { $sort: {pop: 1} },
                             { $group:
                                 { _id: "$_id.state",
                                    biggestCity: { $last: "$_id.city" },
                                    biggestPop: { $last: "$pop" },
                                    smallestCity: { $first: "$_id.city" },
                                    smallestPop: { $first: "$pop" },

                             { $project:
                                  { _id: 0,
                                     state: "$_id",
                                     biggestCity: {name: "$biggestCity", pop: "$biggestPop" },
                                     smallestCity: {name: "$smallestCity", pop: "$smallestPop" } } } 
                             )

     Nesta query, temos o uso do $sort, para ordenar os primeiros grupos de estado e cidade criados em $group. Em seguida, agrupamos novamente por estados, que agora são um subdocumento (pois estamos o segundo $group) $_id.city e utilizamos $last e $first, para pegar os maiores e menores resultados, respecitivamente. Adicionalmente temos, dentro do pipeline, o $projec, que "muda" o modo como exibimos os resultados. Aqui, renomeamos os campos de exibição para name, mostrando o nome da cidade, e  pop, mostrando a população.

  O aggregation framework é muito poderoso, principalmente quando o utilizamos como alternativa ao mapReduce. Abordaremos este conceito em posts futuros.

     Posts relacionados:


     Um abraço e até o próximo post!


0 comentários:

Postar um comentário