Queries de pipeline de agregação do MongoDB versus queries SQL
Joe Karlsson7 min read • Published Feb 07, 2022 • Updated May 10, 2022
Avalie esse Tutorial
Vamos ser verdadeiros: muitos desenvolvedores que estão chegando ao MongoDB estão se juntando à comunidade com uma sólida experiência em SQL. Eu pessoalmente me incluiria neste subconjunto de desenvolvedores MongoDB. É útil mapear termos e conceitos com os quais você esteja familiarizado no SQL para ajudar a "traduzir" seu trabalho para a linguagem de query do MongoDB (MQL). Mais especificamente, nesta postagem, mostrará a tradução do Aggregation Pipeline do MongoDB do SQL.
O framework de agregação permite que você analise seus dados em tempo real. Usando-o, você pode criar um pipeline de agregação que consiste em um ou mais estágios. Cada estágio transforma os documentos e passa a saída para o próximo estágio.
Se você estiver familiarizado com o pipe Unix |, poderá pensar no aggregation pipeline como um conceito muito semelhante. Assim como a saída de um comando é passada como entrada para o próximo comando quando você usa o piping, a saída de um estágio é passada como entrada para o próximo estágio quando você usa o pipeline de agregação.
SQL é uma linguagem declarativa. Você precisa declarar o que deseja ver - é por isso que SELECT vem em primeiro lugar. Você precisa pensar em conjuntos, o que pode ser difícil, especialmente para programadores funcionais. Com o pipeline de agregação do MongoDB, você pode ter estágios que refletem como você pensa — por exemplo, "Primeiro, vamos agrupar por X. Em seguida, obteremos os 5 principais de cada grupo. Depois, organizaremos por preço." Esta é uma query difícil de fazer no SQL, mas muito mais fácil usar a estrutura de pipeline de agregação.
O framework de agregação tem uma variedade de estágios disponíveis para você usar. Hoje, discutiremos os fundamentos de como usar $match, $group, $sort e $limit. Observe que o framework de agregação tem muitos outros estágios avançados, incluindo $count, $geoNear, $graphLookup, $project, $unwind e outros.
Se você quiser conferir outra ótima introdução ao MongoDB Aggregation Pipeline, não deixe de conferir Introdução ao MongoDB Aggregation Framework.
A tabela a seguir fornece uma visão geral dos termos, funções e conceitos de agregação SQL comuns e dos operadores de agregação MongoDB correspondentes:
Termos, funções e conceitos do SQL | Operadores de agregação do MongoDB |
---|---|
WHERE | $match |
AGRUPAR POR | $group |
HAVING | $match |
SELECT | $project |
LIMIT | $limit |
OFFSET | $skip |
ORDENAR POR | $sort |
SUM() | $sum |
COUNT() | $sum e $sortByCount |
JOIN | $lookup |
SELECIONAR EM NEW_TABLE | $out |
MESCLAR NA TABELA | $merge (Disponível a partir do MongoDB 4.2) |
UNION ALL | $unionWith (Disponível a partir do MongoDB 4.4) |
Muito bem, agora que cobrimos o básico das agregações do MongoDB, vamos pular para alguns exemplos.
Os exemplos SQL assumem duas tabelas, collection e músicas, que se juntam pelascolunas snapshot.album_id e concerns.id . Veja como são as tabelas:
id | Nome | banda_name | Preço | Status |
---|---|---|---|---|
1 | músicas lo-fi Chill Hoop para aprender | Silicon Infinite | 2.99 | uma |
2 | Pedras da Lua | Silicon Infinite | 1.99 | B |
3 | Sabor | Orgânico | 4.99 | uma |
id | title | peças | album_id |
---|---|---|---|
1 | Batidas na neve | 133 | 1 |
2 | Rolling By | 242 | 1 |
3 | Nuvens | 3191 | 1 |
4 | Mas o primeiro café | 562 | 3 |
5 | Outono | 901 | 3 |
6 | Torradas com leite | 118 | 2 |
7 | Mic Roxo | 719 | 2 |
8 | Jantar de uma nota | 1242 | 2 |
Usei um site chamado SQL Fiddlee usei PostgreSQL 9.6 para todos os meus exemplos. No entanto, fique à vontade para executar esses trechos de exemplo de SQL onde você se sentir mais à vontade. Na verdade, este é o código que usei para configurar e popular minhas tabelas com nossos dados de amostra:
1 -- Creating the main albums table 2 CREATE TABLE IF NOT EXISTS albums ( 3 id BIGSERIAL NOT NULL UNIQUE PRIMARY KEY, 4 name VARCHAR(40) NOT NULL UNIQUE, 5 band_name VARCHAR(40) NOT NULL, 6 price float8 NOT NULL, 7 status VARCHAR(10) NOT NULL 8 ); 9 10 -- Creating the songs table 11 CREATE TABLE IF NOT EXISTS songs ( 12 id SERIAL PRIMARY KEY NOT NULL, 13 title VARCHAR(40) NOT NULL, 14 plays integer NOT NULL, 15 album_id BIGINT NOT NULL REFERENCES albums ON DELETE RESTRICT 16 ); 17 18 INSERT INTO albums (name, band_name, price, status) 19 VALUES 20 ('lo-fi chill hop songs to study to', 'Silicon Infinite', 7.99, 'A'), 21 ('Moon Rocks', 'Silicon Infinite', 1.99, 'B'), 22 ('Flavour', 'Organical', 4.99, 'A'); 23 24 INSERT INTO songs (title, plays, album_id) 25 VALUES 26 ('Snow Beats', 133, (SELECT id from albums WHERE name='lo-fi chill hop songs to study to')), 27 ('Rolling By', 242, (SELECT id from albums WHERE name='lo-fi chill hop songs to study to')), 28 ('Clouds', 3191, (SELECT id from albums WHERE name='lo-fi chill hop songs to study to')), 29 ('But First Coffee', 562, (SELECT id from albums WHERE name='Flavour')), 30 ('Autumn', 901, (SELECT id from albums WHERE name='Flavour')), 31 ('Milk Toast', 118, (SELECT id from albums WHERE name='Moon Rocks')), 32 ('Purple Mic', 719, (SELECT id from albums WHERE name='Moon Rocks')), 33 ('One Note Dinner Party', 1242, (SELECT id from albums WHERE name='Moon Rocks'));
Os exemplos do MongoDB assumem uma coleção
albums
que contém documentos com o seguinte esquema:1 { 2 name : 'lo-fi chill hop songs to study to', 3 band_name: 'Silicon Infinite', 4 price: 7.99, 5 status: 'A', 6 songs: [ 7 { title: 'Snow beats', 'plays': 133 }, 8 { title: 'Rolling By', 'plays': 242 }, 9 { title: 'Sway', 'plays': 3191 } 10 ] 11 }
Para esta publicação, criei todos os meus protótipos em um playground de plug-ins do MongoDB Visual Studio Code. Para obter mais informações sobre como usar um MongoDB Playground no Visual Studio Code, não deixe de conferir esta publicação: Como usar o plug-in de código do MongoDB Visual Studio. Depois de configurar seu playground, você poderá usar este trecho para configurar e semear sua collection. Você também pode acompanhar esta demonstração usando o MongoDB Web shell.
1 // Select the database to use. 2 use('mongodbVSCodePlaygroundDB'); 3 4 // The drop() command destroys all data from a collection. 5 // Make sure you run it against the correct database and collection. 6 db.albums.drop(); 7 8 // Insert a few documents into the albums collection. 9 db.albums.insertMany([ 10 { 11 'name' : 'lo-fi chill hop songs to study to', band_name: 'Silicon Infinite', price: 7.99, status: 'A', 12 songs: [ 13 { title: 'Snow beats', 'plays': 133 }, 14 { title: 'Rolling By', 'plays': 242 }, 15 { title: 'Clouds', 'plays': 3191 } 16 ] 17 }, 18 { 19 'name' : 'Moon Rocks', band_name: 'Silicon Infinite', price: 1.99, status: 'B', 20 songs: [ 21 { title: 'Milk Toast', 'plays': 118 }, 22 { title: 'Purple Mic', 'plays': 719 }, 23 { title: 'One Note Dinner Party', 'plays': 1242 } 24 ] 25 }, 26 { 27 'name' : 'Flavour', band_name: 'Organical', price: 4.99, status: 'A', 28 songs: [ 29 { title: 'But First Coffee', 'plays': 562 }, 30 { title: 'Autumn', 'plays': 901 } 31 ] 32 }, 33 ]);
1 SELECT COUNT(*) AS count 2 FROM albums
1 db.albums.aggregate( [ 2 { 3 $group: { 4 _id: null, // An _id value of null on the $group operator accumulates values for all the input documents as a whole. 5 count: { $sum: 1 } 6 } 7 } 8 ] );
1 SELECT SUM(price) AS total 2 FROM albums
1 db.albums.aggregate( [ 2 { 3 $group: { 4 _id: null, 5 total: { $sum: "$price" } 6 } 7 } 8 ] );
1 SELECT band_name, 2 SUM(price) AS total 3 FROM albums 4 GROUP BY band_name
1 db.albums.aggregate( [ 2 { 3 $group: { 4 _id: "$band_name", 5 total: { $sum: "$price" } 6 } 7 } 8 ] );
1 SELECT band_name, 2 SUM(price) AS total 3 FROM albums 4 GROUP BY band_name 5 ORDER BY total
1 db.albums.aggregate( [ 2 { 3 $group: { 4 _id: "$band_name", 5 total: { $sum: "$price" } 6 } 7 }, 8 { $sort: { total: 1 } } 9 ] );
1 SELECT band_name, 2 count(*) 3 FROM albums 4 GROUP BY band_name 5 HAVING count(*) > 1;
1 db.albums.aggregate( [ 2 { 3 $group: { 4 _id: "$band_name", 5 count: { $sum: 1 } 6 } 7 }, 8 { $match: { count: { $gt: 1 } } } 9 ] );
1 SELECT band_name, 2 SUM(price) as total 3 FROM albums 4 WHERE status = 'A' 5 GROUP BY band_name
1 db.albums.aggregate( [ 2 { $match: { status: 'A' } }, 3 { 4 $group: { 5 _id: "$band_name", 6 total: { $sum: "$price" } 7 } 8 } 9 ] );
1 SELECT band_name, 2 SUM(price) as total 3 FROM albums 4 WHERE status = 'A' 5 GROUP BY band_name 6 HAVING SUM(price) > 5.00;
1 db.albums.aggregate( [ 2 { $match: { status: 'A' } }, 3 { 4 $group: { 5 _id: "$band_name", 6 total: { $sum: "$price" } 7 } 8 }, 9 { $match: { total: { $gt: 5.00 } } } 10 ] );
1 SELECT band_name, 2 SUM(songs.plays) as total_plays 3 FROM albums, 4 songs 5 WHERE songs.album_id = albums.id 6 GROUP BY band_name;
1 db.albums.aggregate( [ 2 { $unwind: "$songs" }, 3 { 4 $group: { 5 _id: "$band_name", 6 qty: { $sum: "$songs.plays" } 7 } 8 } 9 ] );
1 SELECT name, title, plays 2 FROM songs s1 INNER JOIN albums ON (album_id = albums.id) 3 WHERE plays=(SELECT MAX(s2.plays) 4 FROM songs s2 5 WHERE s1.album_id = s2.album_id) 6 ORDER BY name;
1 db.albums.aggregate( [ 2 { $project: 3 { 4 name: 1, 5 plays: { 6 $filter: { 7 input: "$songs", 8 as: "item", 9 cond: { $eq: ["$item.plays", { $max: "$songs.plays" }] } 10 } 11 } 12 } 13 } 14 ] );
Esta publicação não oferece de forma alguma uma visão geral completa de todas as maneiras de usar o MongoDB como um banco de dados baseado em SQL. Isso foi feito apenas para ajudar os desenvolvedores em SQL a começar a fazer a transição para o MongoDB com algumas queries básicas usando o pipeline de agregação. A framework de aggregation tem muitos outros estágios avançados, incluindo $count, $geoNear, $graphLookup, $project, $unwinde outros.
Se você quiser melhorar o uso da Estrutura de agregação do MongoDB, não deixe de conferir a MongoDB University: M121 - A estrutura de agregação do MongoDB. Ou, melhor ainda, tente usar algumas queries avançadas de pipeline de agregação do MongoDB em seu próximo projeto! Em caso de dúvidas, consulte os MongoDB Community. É o melhor lugar para tirar suas dúvidas sobre o MongoDB.
- MongoDB University: M121 - Framework de aggregation do MongoDB : https://university.mongodb.com/cursos/M121/sobre
- Como usar expressões de agregação customizadas no MongoDB 4.4: https://developer.mongodb.com/show-to/use-function-accumulator-operators
- Introdução à estrutura de agregação do MongoDB: https://developer.mongodb.com/quickstart/introdução-aggregation-framework
- Como usar o estágio do pipeline de agregação union all no MongoDB 4.4: https://developer.mongodb.com/show-to/use-union-all-aggregation-pipeline-stage
- Estrutura de agregação com Node.js Tutorial: https://developer.mongodb.com/quickstart/node-aggregation-framework
- Referência rápida do pipeline de agregação: https://docs.mongodb.com/manual/meta/aggregation-quick-reference
- Gráfico de mapeamento SQL para agregação: https://docs.mongodb.com/manual/reference/sql-aggregation-comparison
- Gráfico de mapeamento SQL para MongoDB: https://docs.mongodb.com/manual/reference/sql-comparison
- Questões? Comentários? Adoraríamos nos conectar com você. Participe da conversa nos Fóruns da MongoDB Community: https://developer.mongodb.com/community/forums