Introdução a pipelines de agregação em Rust
Mark Smith15 min read • Published Feb 05, 2022 • Updated Oct 01, 2024
Avalie esse Início rápido
Os pipelines de agregação do MongoDB são um de seus recursos mais avançados. Eles permitem escrever expressões, divididas em uma série de estágios, que executam operações, incluindo agregação, transformações e junções nos dados em seus MongoDB databases. Isso permite fazer cálculos e análises entre documentos e coleções dentro do MongoDB database.
Este início rápido é o segundo de uma série de postagens sobre Rust. Eu altamente recomendo que você comece com minha primeira postagem, Operações básicas do MongoDB no Rust, que mostrará como configurar corretamente um cluster gratuito de banco de dados MongoDB Atlas contendo os dados de amostra com os quais você trabalhará aqui. Vá ler e volte. Vou aguardar. Sem ele, você não terá o banco de dados configurado corretamente para executar o código neste guia de início rápido.
Em resumo, você vai precisar de:
- Uma versão atualizada do Rust. Usei 1.49, mas qualquer versão recente deve funcionar bem.
- Um cluster do MongoDB contendo o conjunto de dados
sample_mflix
. Você pode encontrar instruções para configurar isso na primeira publicação no blog desta série.
Os pipelines de agregação do MongoDB são muito poderosos e, portanto, podem parecer um pouco opressores no início. Por esse motivo, começarei lentamente. Primeiro, mostrarei como criar um pipeline que duplica o comportamento que você já pode obter com o método
find()
do MongoDB, mas usando um aggregation pipeline com os estágios$match
, $sort
e $limit
. Em seguida, mostrarei como fazer queries que vão além do que pode ser feito com find
, demonstrando o uso $lookup
para incluir documentos relacionados de outra collection. Por fim, colocarei a "agregação" em "pipeline de agregação" mostrando como usar o $group
para agrupar documentos e formar novos resumos de documentos.Todo o código de amostra desta série de início rápido pode ser encontrado no GitHub. Recomendamos que você confira se tiver dúvidas, caso contrário, vale a pena seguir o tutorial e escrever o código você mesmo!
Todos os pipelines nesta postagem serão executados na coleção do banco de dados sample_mflix
movies
. Ele contém documentos como este (estou mostrando como eles são no Python, porque é um pouco mais legível do que a estrutura equivalente do Rust):1 { 2 '_id': ObjectId('573a1392f29313caabcdb497'), 3 'awards': {'nominations': 7, 4 'text': 'Won 1 Oscar. Another 2 wins & 7 nominations.', 5 'wins': 3}, 6 'cast': ['Janet Gaynor', 'Fredric March', 'Adolphe Menjou', 'May Robson'], 7 'countries': ['USA'], 8 'directors': ['William A. Wellman', 'Jack Conway'], 9 'fullplot': 'Esther Blodgett is just another starry-eyed farm kid trying to ' 10 'break into the movies. Waitressing at a Hollywood party, she ' 11 'catches the eye of alcoholic star Norman Maine, is given a test, ' 12 'and is caught up in the Hollywood glamor machine (ruthlessly ' 13 'satirized). She and her idol Norman marry; but his career ' 14 'abruptly dwindles to nothing', 15 'genres': ['Drama'], 16 'imdb': {'id': 29606, 'rating': 7.7, 'votes': 5005}, 17 'languages': ['English'], 18 'lastupdated': '2015-09-01 00:55:54.333000000', 19 'plot': 'A young woman comes to Hollywood with dreams of stardom, but ' 20 'achieves them only with the help of an alcoholic leading man whose ' 21 'best days are behind him.', 22 'poster': 'https://m.media-amazon.com/images/M/MV5BMmE5ODI0NzMtYjc5Yy00MzMzLTk5OTQtN2Q3MzgwOTllMTY3XkEyXkFqcGdeQXVyNjc0MzMzNjA@._V1_SY1000_SX677_AL_.jpg', 23 'rated': 'NOT RATED', 24 'released': datetime.datetime(1937, 4, 27, 0, 0), 25 'runtime': 111, 26 'title': 'A Star Is Born', 27 'tomatoes': {'critic': {'meter': 100, 'numReviews': 11, 'rating': 7.4}, 28 'dvd': datetime.datetime(2004, 11, 16, 0, 0), 29 'fresh': 11, 30 'lastUpdated': datetime.datetime(2015, 8, 26, 18, 58, 34), 31 'production': 'Image Entertainment Inc.', 32 'rotten': 0, 33 'viewer': {'meter': 79, 'numReviews': 2526, 'rating': 3.6}, 34 'website': 'http://www.vcientertainment.com/Film-Categories?product_id=73'}, 35 'type': 'movie', 36 'writers': ['Dorothy Parker (screen play)', 37 'Alan Campbell (screen play)', 38 'Robert Carson (screen play)', 39 'William A. Wellman (from a story by)', 40 'Robert Carson (from a story by)'], 41 'year': 1937}
Há muitos dados lá, mas vou me concentrar principalmente nos campos
_id
, title
, year
e cast
. Os pipelines de agregação são executados pelo módulo mongodb usando o método aggregate() da coleção.
O primeiro argumento para
aggregate()
é uma sequência de estágios de pipeline a serem executados. Assim como uma query, cada estágio de um aggregation pipeline é um documento BSON. Muitas vezes, você os criará usando a macrodoc!
que foi introduzida na postagem anterior.Um pipeline de agregação opera em todos os dados de uma coleção. Cada estágio do pipeline é aplicado aos documentos que passam, e quaisquer documentos emitidos de um estágio são passados como entrada para o próximo, até que não haja mais estágios restantes. Nesse ponto, os documentos emitidos do último estágio do pipeline são retornados ao programa do cliente, como um cursor, de forma semelhante a uma chamada para
find()
.Estágios individuais, como
$match
, podem atuar como um filtro, para passar apenas documentos que correspondam a determinados critérios. Outros tipos de estágio, como $project
, $addFields
e $lookup
, modificarão o conteúdo de documentos individuais à medida que eles passam pelo pipeline. Por fim, determinados tipos de estágio, como $group
, criarão um conjunto totalmente novo de documentos com base nos documentos passados para ele como um todo. Nenhum desses estágios altera os dados armazenados no próprio MongoDB. Eles apenas mudam os dados antes de devolvê-los ao seu programa!Existem estágios, como $ out, que podem salvar os resultados de um pipeline de volta ao MongoDB, mas não abordarei isso neste início rápido.Estou supondo que você esteja trabalhando no mesmo ambiente usado na última postagem, então você já deve ter a caixa do mongodb configurada como uma dependência em seu arquivo
Cargo.toml
e deve ter um .env
arquivo contendo sua variável de ambienteMONGODB_URI
.Primeiro, cole o seguinte em seu código Rust:
1 // Load the MongoDB connection string from an environment variable: 2 let client_uri = 3 env::var("MONGODB_URI").expect("You must set the MONGODB_URI environment var!"); 4 5 // An extra line of code to work around a DNS issue on Windows: 6 let options = 7 ClientOptions::parse_with_resolver_config(&client_uri, ResolverConfig::cloudflare()) 8 .await?; 9 let client = mongodb::Client::with_options(options)?; 10 11 // Get the 'movies' collection from the 'sample_mflix' database: 12 let movies = client.database("sample_mflix").collection("movies");
O código acima fornecerá uma instância do
Collection
denominadamovie_collection
, que aponta para a coleçãomovies
em seu banco de dados.Aqui está um código que cria um pipeline, executa-o com
aggregate
e, em seguida, faz um loop e imprime os detalhes de cada filme nos resultados. Cole-o em seu programa.1 // Usually implemented outside your main function: 2 3 struct MovieSummary { 4 title: String, 5 cast: Vec<String>, 6 year: i32, 7 } 8 9 impl fmt::Display for MovieSummary { 10 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 11 write!( 12 f, 13 "{}, {}, {}", 14 self.title, 15 self.cast.get(0).unwrap_or(&"- no cast -".to_owned()), 16 self.year 17 ) 18 } 19 } 20 21 // Inside main(): 22 let pipeline = vec![ 23 doc! { 24 // filter on movie title: 25 "$match": { 26 "title": "A Star Is Born" 27 } 28 }, 29 doc! { 30 // sort by year, ascending: 31 "$sort": { 32 "year": 1 33 } 34 }, 35 ]; 36 37 // Look up "A Star is Born" in ascending year order: 38 let mut results = movies.aggregate(pipeline, None).await?; 39 // Loop through the results, convert each of them to a MovieSummary, and then print out. 40 while let Some(result) = results.next().await { 41 // Use serde to deserialize into the MovieSummary struct: 42 let doc: MovieSummary = bson::from_document(result?)?; 43 println!("* {}", doc); 44 }
Este pipeline tem duas etapas. O primeiro é um estágio$match, que é semelhante a fazer query de uma collection com
find()
. Ele filtra os documentos que passam pelo estágio com base em uma query deoperação de leitura . Por ser o primeiro estágio do pipeline, sua entrada são todos os documentos da collectionmovie
. A query para os filtros de estágio $match
no campotitle
dos documentos de entrada, de modo que os únicos documentos que serão gerados desse estágio terão o título de "Nasce uma estrela".O segundo estágio é um estágio $sort. Somente os documentos do filme "Nasce uma Estrela" são passados para esse estágio, de modo que o resultado será todos os filmes chamados "Nasce uma Estrela", agora classificados pelo campo de ano, com o filme mais antigo primeiro.
As chamadas para aggregate() retornam um cursor apontando para os documentos resultantes. O cursor implementa a característica Stream. O cursor pode ser percorrido como qualquer outro fluxo, desde que você tenha importado StreamExt, que fornece o método
next()
. O código acima percorre todos os documentos retornados e imprime um breve resumo, consistindo no título, no primeiro ator na matrizcast
e no ano em que o filme foi produzido.A execução do código acima resulta em:
1 * A Star Is Born, Janet Gaynor, 1937 2 * A Star Is Born, Judy Garland, 1954 3 * A Star Is Born, Barbra Streisand, 1976
É possível criar pipelines de agregação inteiros como uma única estrutura de dados, como no exemplo acima, mas não é necessariamente uma boa ideia. Os pipelines podem ficar longos e complexos. Por esse motivo, recomendo que você crie cada estágio do seu pipeline como uma variável separada e, em seguida, combine os estágios em um pipeline no final, assim:
1 // Match title = "A Star Is Born": 2 let stage_match_title = doc! { 3 "$match": { 4 "title": "A Star Is Born" 5 } 6 }; 7 8 // Sort by year, ascending: 9 let stage_sort_year_ascending = doc! { 10 "$sort": { "year": 1 } 11 }; 12 13 // Now the pipeline is easier to read: 14 let pipeline = vec![stage_match_title, stage_sort_year_ascending];
Imagine que eu quisesse obter a produção mais recente de "A Star Is Born" da coleção de filmes.
Isso pode ser pensado como três etapas, executadas em ordem:
- Obtenha os documentos do filme "A Star Is Born".
- Classificado por ano, ordem decrescente.
- Descarte todos, exceto o primeiro documento.
O primeiro estágio já é o mesmo que
stage_match_title
acima. O segundo estágio é o mesmo que stage_sort_year_ascending
, mas com o valor 1
alterado para -1
. O terceiro estágio é um estágio$limit.O código modificado e novo fica assim:
1 // Sort by year, descending: 2 let stage_sort_year_descending = doc! { 3 "$sort": { 4 "year": -1 5 } 6 }; 7 8 // Limit to 1 document: 9 let stage_limit_1 = doc! { "$limit": 1 }; 10 11 let pipeline = vec![stage_match_title, stage_sort_year_descending, stage_limit_1];
Se você fizer as alterações acima e executar seu código, verá apenas a seguinte linha:
1 * A Star Is Born, Barbra Streisand, 1976
Espere um pouco! Por que não há um documento para a maravilhosa produção com Lady Gaga e Bradley Cooper?
Por que você não usa as habilidades que acabou de aprender para encontrar a data mais recente na collection? Isso lhe dará sua resposta!
Agora você já sabe filtrar, classificar e limitar o conteúdo de uma coleção usando um pipeline de agregação. Mas essas são apenas operações que você já pode fazer com
find()
! Por que você usaria esses pipelines de agregação complexos e novos?Continue lendo, meu caro, e mostrarei o verdadeiro poder dos pipelines de agregação do MongoDB.
Há um segredo sujo escondido no banco de dados
sample_mflix
. Além da coleção movies
, há também uma coleção chamada comments
. Os documentos da coleção comments
têm esta aparência:1 { 2 '_id': ObjectId('5a9427648b0beebeb69579d3'), 3 'movie_id': ObjectId('573a1390f29313caabcd4217'), 4 'date': datetime.datetime(1983, 4, 27, 20, 39, 15), 5 'email': 'cameron_duran@fakegmail.com', 6 'name': 'Cameron Duran', 7 'text': 'Quasi dicta culpa asperiores quaerat perferendis neque. Est animi ' 8 'pariatur impedit itaque exercitationem.'}
É um comentário sobre um filme. Não sei por que as pessoas estão escrevendo comentários em latim para esses filmes, mas vamos em frente. O segundo campo,
movie_id,
, corresponde ao valor _id
de um documento na coleção movies
.Então, é um comentário relacionado a um filme!
O MongoDB permite que você consulte filmes e incorpore os comentários relacionados, como um JOIN em um banco de dados relacional? Sim, permite—com o estágio $lookup.
Mostrarei como obter documentos relacionados de outra coleção e incorporá-los nos documento da sua coleção principal.
Primeiro, modifique a definição da estrutura
MovieSummary
para que ela tenha um campocomments
, carregado de um camporelated_comments
BSON. Defina uma estruturaComment
que contenha um subconjunto dos dados contidos em um documentocomments
.1 2 struct MovieSummary { 3 title: String, 4 cast: Vec<String>, 5 year: i32, 6 7 comments: Vec<Comment>, 8 } 9 10 11 struct Comment { 12 email: String, 13 name: String, 14 text: String, 15 }
Em seguida, crie um novo pipeline do zero e comece com o seguinte:
1 // Look up related documents in the 'comments' collection: 2 let stage_lookup_comments = doc! { 3 "$lookup": { 4 "from": "comments", 5 "localField": "_id", 6 "foreignField": "movie_id", 7 "as": "related_comments", 8 } 9 }; 10 11 // Limit to the first 5 documents: 12 let stage_limit_5 = doc! { "$limit": 5 }; 13 14 let pipeline = vec![ 15 stage_lookup_comments, 16 stage_limit_5, 17 ]; 18 19 let mut results = movies.aggregate(pipeline, None).await?; 20 // Loop through the results and print a summary and the comments: 21 while let Some(result) = results.next().await { 22 let doc: MovieSummary = bson::from_document(result?)?; 23 println!("* {}, comments={:?}", doc, doc.comments); 24 }
O estágio que chamei de
stage_lookup_comments
é um estágio $lookup
. Esse estágio $lookup
pesquisa documentos da coleção comments
que tenham o mesmo ID de filme. Os comentários correspondentes serão listados como uma array em um campo BSON chamado related_comments
, com um valor de array contendo todos os comentários que têm o valor _id
desse filme como movie_id
.Adicionei um estágio
$limit
apenas para garantir que haja uma quantidade razoável de saída sem ser excessiva.Agora, execute o código.
Você pode notar que o pipeline acima funciona bem devagar! Há duas razões para isso:
- Há 23,5k documentos de filmes e 50k comentários.
- Há um índice ausente na coleção
comments
. Ele não está lá de propósito para você aprender sobre índices!
Eu não mostrarei como resolver o problema do índice agora. Escreverei sobre isso em uma publicação posterior desta série, com foco em índices. Em vez disso, mostrarei um truque para trabalhar com pipelines de agregação lentos enquanto você está desenvolvendo.
Trabalhar com pipelines lentos é cansativo enquanto você escreve e testa o pipeline. Mas, se você colocar um estágio temporário
$limit
no início do seu pipeline, ele tornará a query mais rápida (embora os resultados possam ser diferentes porque você não está executando em todo o conjunto de dados).Quando estava escrevendo esse pipeline, eu tinha um primeiro estágio de
{ "$limit": 1000 }
.Quando terminar de criar o pipeline, você pode comentar a primeira etapa para que o pipeline agora seja executado em toda a coleção. Não se esqueça de remover o primeiro estágio, senão você obterá resultados errados!
O pipeline de agregação acima imprimirá resumos de cinco documentos de filmes. Duvido que a maioria ou todos os seus resumos de filmes terminem com isso:
comments=[]
.Se você tiver sorte, poderá ter alguns documentos na array, mas é improvável, pois a maioria dos filmes não tem comentários. Agora, mostrarei como adicionar alguns estágios para corresponder apenas aos filmes que têm mais de dois comentários.
O ideal é que você pudesse adicionar um único estágio
$match
que tivesse o comprimento do campo related_comments
e o comparasse com a expressão { "$gt": 2 }
. Neste caso, são na verdade duas etapas:- Adicione um campo (que chamarei de
comment_count
) contendo o comprimento do camporelated_comments
. - Correspondência onde o valor de
comment_count
é maior que dois.
Este é o código para os dois estágios:
1 // Calculate the number of comments for each movie: 2 let stage_add_comment_count = doc! { 3 "$addFields": { 4 "comment_count": { 5 "$size": "$related_comments" 6 } 7 } 8 }; 9 10 // Match movie documents with more than 2 comments: 11 let stage_match_with_comments = doc! { 12 "$match": { 13 "comment_count": { 14 "$gt": 2 15 } 16 } 17 };
Os dois estágios ocorrem após o estágio
$lookup
e antes do $limit
5:1 let pipeline = vec![ 2 stage_lookup_comments, 3 stage_add_comment_count, 4 stage_match_with_comments, 5 limit_5, 6 ]
Já que estou aqui, vou limpar a saída desse código para formatar os comentários um pouco melhor:
1 let mut results = movies.aggregate(pipeline, None).await?; 2 // Loop through the results and print a summary and the comments: 3 while let Some(result) = results.next().await { 4 let doc: MovieSummary = bson::from_document(result?)?; 5 println!("* {}", doc); 6 if doc.comments.len() > 0 { 7 // Print a max of 5 comments per movie: 8 for comment in doc.comments.iter().take(5) { 9 println!( 10 " - {} <{}>: {}", 11 comment.name, 12 comment.email, 13 comment.text.chars().take(60).collect::<String>(), 14 ); 15 } 16 } else { 17 println!(" - No comments"); 18 } 19 }
Agora, ao executar esse código, você deve ver algo mais ou menos assim:
1 * Midnight, Claudette Colbert, 1939 2 - Sansa Stark <sansa_stark@fakegmail.com>: Error ex culpa dignissimos assumenda voluptates vel. Qui inventore 3 - Theon Greyjoy <theon_greyjoy@fakegmail.com>: Animi dolor minima culpa sequi voluptate. Possimus necessitatibu 4 - Donna Smith <donna_smith@fakegmail.com>: Et esse nulla ducimus tempore aliquid. Suscipit iste dignissimos v
É bom ver que Sansa Stark, de Game of Thrones, realmente sabe tudo de latim, não é?
Agora que mostrei como trabalhar com pesquisas em seus pipelines, mostrarei como usar o estágio
$group
para fazer a agregação real.Começarei com um novo pipeline mais uma vez.
O estágio
$group
é um dos estágios mais difíceis de entender, portanto, vou explicá-lo em detalhes.Comece com o seguinte código:
1 // Define a struct to hold grouped data by year: 2 3 struct YearSummary { 4 _id: i32, 5 6 movie_count: i64, 7 8 movie_titles: Vec<String>, 9 } 10 11 // Some movies have "year" values ending with 'è'. 12 // This stage will filter them out: 13 let stage_filter_valid_years = doc! { 14 "$match": { 15 "year": { 16 "$type": "number", 17 } 18 } 19 }; 20 21 /* 22 * Group movies by year, producing 'year-summary' documents that look like: 23 * { 24 * '_id': 1917, 25 * } 26 */ 27 let stage_group_year = doc! { 28 "$group": { 29 "_id": "$year", 30 } 31 }; 32 33 let pipeline = vec![stage_filter_valid_years, stage_group_year]; 34 35 // Loop through the 'year-summary' documents: 36 let mut results = movies.aggregate(pipeline, None).await?; 37 // Loop through the yearly summaries and print their debug representation: 38 while let Some(result) = results.next().await { 39 let doc: YearSummary = bson::from_document(result?)?; 40 println!("* {:?}", doc); 41 }
Na coleção
movies
, alguns dos anos contêm o caractere "è". Este banco de dados tem alguns valores confusos. Neste caso, há apenas um pequeno número de documentos, e acho que devemos simplesmente removê-los, então adicionei um $match
estágio que filtra todos os documentos com um year
que não é numérico.Execute este código e você deverá ver algo assim:
1 * YearSummary { _id: 1959, movie_count: 0, movie_titles: [] } 2 * YearSummary { _id: 1980, movie_count: 0, movie_titles: [] } 3 * YearSummary { _id: 1977, movie_count: 0, movie_titles: [] } 4 * YearSummary { _id: 1933, movie_count: 0, movie_titles: [] } 5 * YearSummary { _id: 1998, movie_count: 0, movie_titles: [] } 6 * YearSummary { _id: 1922, movie_count: 0, movie_titles: [] } 7 * YearSummary { _id: 1948, movie_count: 0, movie_titles: [] } 8 * YearSummary { _id: 1965, movie_count: 0, movie_titles: [] } 9 * YearSummary { _id: 1950, movie_count: 0, movie_titles: [] } 10 * YearSummary { _id: 1968, movie_count: 0, movie_titles: [] } 11 ...
Cada linha é um documento emitido do pipeline de agregação. Mas você não está mais olhando para documentos de filmes. O estágio
$group
agrupa documentos de entrada pela expressão_id
especificada e gera um documento para cada valor de_id
exclusivo . Nesse caso, a expressão é $year
, o que significa que um documento será emitido para cada valor exclusivo do campoyear
. Cada documento emitido também pode (e geralmente conterá) valores gerados a partir da agregação de dados dos documentos agrupados. Atualmente, os documentos YearSummary estão usando os valores padrão para movie_count
e movie_titles
. Vamos consertar isso.Altere a definição de estágio para o seguinte:
1 let stage_group_year = doc! { 2 "$group": { 3 "_id": "$year", 4 // Count the number of movies in the group: 5 "movie_count": { "$sum": 1 }, 6 } 7 };
Isso adicionará um campo
movie_count
, que contém o resultado da adição de 1
para cada documento no grupo. Em outras palavras, ele conta o número de documentos de filmes no grupo. Se você executar o código agora, deverá ver algo assim:1 * YearSummary { _id: 2005, movie_count: 758, movie_titles: [] } 2 * YearSummary { _id: 1999, movie_count: 542, movie_titles: [] } 3 * YearSummary { _id: 1943, movie_count: 36, movie_titles: [] } 4 * YearSummary { _id: 1926, movie_count: 9, movie_titles: [] } 5 * YearSummary { _id: 1935, movie_count: 40, movie_titles: [] } 6 * YearSummary { _id: 1966, movie_count: 116, movie_titles: [] } 7 * YearSummary { _id: 1971, movie_count: 116, movie_titles: [] } 8 * YearSummary { _id: 1952, movie_count: 58, movie_titles: [] } 9 * YearSummary { _id: 2013, movie_count: 1221, movie_titles: [] } 10 * YearSummary { _id: 1912, movie_count: 2, movie_titles: [] } 11 ...
Há vários operadores acumuladores, como
$sum
, que permitem resumir dados do grupo. Se você quiser criar uma array de todos os títulos de filmes no documento emitido, poderá adicionar "movie_titles": { "$push": "$title" },
ao estágio$group
. Nesse caso, você obteria YearSummary
instâncias assim:1 * YearSummary { _id: 1986, movie_count: 206, movie_titles: ["Defense of the Realm", "F/X", "Mala Noche", "Witch from Nepal", ... ]}
Adicione o seguinte estágio para classificar os resultados:
1 let stage_sort_year_ascending = doc! { 2 "$sort": {"_id": 1} 3 }; 4 5 let pipeline = vec! [ 6 stage_filter_valid_years, // Match numeric years 7 stage_group_year, 8 stage_sort_year_ascending, // Sort by year (which is the unique _id field) 9 ]
Note que o estágio
$match
é adicionado ao início do pipeline e o $sort
é adicionado ao final. Uma regra geral é que você deve filtrar documentos no início do pipeline, para que os estágios posteriores tenham menos documentos para lidar. Isso garante que o pipeline tenha mais chances de aproveitar quaisquer índices apropriados atribuídos à coleção.Lembre-se de que todo o código de amostra desta série de início rápido pode ser encontrado no GitHub.
As agregações usando
$group
são uma ótima maneira de descobrir fatos interessantes sobre seus dados. Neste exemplo, estou ilustrando o número de filmes feitos a cada ano, mas também seria interessante ver informações sobre os filmes de cada país ou mesmo ver os filmes feitos por atores diferentes.Você aprendeu a construir pipelines de agregação para filtrar, agrupar e unir documentos a outras coleções. Esperamos que você tenha aprendido que colocar um estágio
$limit
no início do pipeline pode ser útil para acelerar o desenvolvimento (mas deve ser removido antes de ir para a produção). Você também aprendeu algumas dicas básicas de otimização, como colocar expressões de filtragem no início do pipeline e não no final.Você deve ter notado que há uma tonelada de diferentes tipos de estágio, operadores e operadores de acumuladores. Aprender a usar os diferentes componentes dos pipelines de agregação é uma parte importante do aprendizado para usar o MongoDB efetivamente como desenvolvedor.
Adoro trabalhar com pipelines de agregação e sempre me surpreendo com o que dá para fazer com eles!
Os pipelines de agregação são superpoderosos e, por isso, são um grande tópico a ser abordado. Confira a documentação completa para ter uma ideia melhor de todo o seu escopo.
Observe que os pipelines de agregação também podem ser usados para gerar novos dados e gravá-los de volta em uma coleção, com o estágio $out.
O MongoDB fornece uma ferramenta de GUIgratuita chamada Compass. Ele permite que você se conecte ao cluster MongoDB para que possa navegar pelos bancos de dados e analisar a estrutura e o conteúdo de suas collections. Ele inclui um construtor de pipeline de agregação que facilita a criação de pipelines de agregação. É altamente recomendável instalá-lo ou, se estiver usando o MongoDB Atlas, use seu construtor de pipeline de agregação semelhante em seu navegador. Costumo usá-los para criar pipelines de agregação e eles incluem botões de exportação que exportarão seu pipeline como código Python (que não é muito difícil de transformar em Rust).
Não sei você, mas quando vi alguns dos resultados acima, pensei que seria legal ver isso com um gráfico." O MongoDB fornece um serviço hospedado chamado Charts que por acaso aceita pipelines de agregação como entrada. Então, agora é uma boa hora para tentar!