Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Idiomaschevron-right
Rustchevron-right

Introdução a pipelines de agregação em Rust

Mark Smith15 min read • Published Feb 05, 2022 • Updated Oct 01, 2024
MongoDBFramework de agregaçãoRust
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Início rápido
star-empty
star-empty
star-empty
star-empty
star-empty
Emblema Rust
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.

Pré-requisitos

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 editor de código de sua escolha. Recomendo o VS Code com a extensão Rust Analyzer.
  • 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.

Comece a usar

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étodofind()do MongoDB, mas usando um aggregation pipeline com os estágios$match, $sorte $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.

Seu primeiro pipeline de agregação

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 arquivoCargo.toml e deve ter um .env arquivo contendo sua variável de ambienteMONGODB_URI .

Encontrando e classificando

Primeiro, cole o seguinte em seu código Rust:
1// Load the MongoDB connection string from an environment variable:
2let 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:
6let options =
7 ClientOptions::parse_with_resolver_config(&client_uri, ResolverConfig::cloudflare())
8 .await?;
9let client = mongodb::Client::with_options(options)?;
10
11// Get the 'movies' collection from the 'sample_mflix' database:
12let movies = client.database("sample_mflix").collection("movies");
O código acima fornecerá uma instância doCollectiondenominadamovie_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#[derive(Deserialize)]
3struct MovieSummary {
4 title: String,
5 cast: Vec<String>,
6 year: i32,
7}
8
9impl 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():
22let 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:
38let mut results = movies.aggregate(pipeline, None).await?;
39// Loop through the results, convert each of them to a MovieSummary, and then print out.
40while 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 $matchno 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étodonext(). O código acima percorre todos os documentos retornados e imprime um breve resumo, consistindo no título, no primeiro ator na matrizcaste 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

Refatorando o código

É 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":
2let stage_match_title = doc! {
3 "$match": {
4 "title": "A Star Is Born"
5 }
6};
7
8// Sort by year, ascending:
9let stage_sort_year_ascending = doc! {
10 "$sort": { "year": 1 }
11};
12
13// Now the pipeline is easier to read:
14let pipeline = vec![stage_match_title, stage_sort_year_ascending];

Limite o número de resultados

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:
  1. Obtenha os documentos do filme "A Star Is Born".
  2. Classificado por ano, ordem decrescente.
  3. 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:
2let stage_sort_year_descending = doc! {
3 "$sort": {
4 "year": -1
5 }
6};
7
8// Limit to 1 document:
9let stage_limit_1 = doc! { "$limit": 1 };
10
11let 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 estruturaMovieSummary 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#[derive(Deserialize)]
2struct MovieSummary {
3 title: String,
4 cast: Vec<String>,
5 year: i32,
6 #[serde(default, rename = "related_comments")]
7 comments: Vec<Comment>,
8}
9
10#[derive(Debug, Deserialize)]
11struct 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:
2let 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:
12let stage_limit_5 = doc! { "$limit": 5 };
13
14let pipeline = vec![
15 stage_lookup_comments,
16 stage_limit_5,
17];
18
19let mut results = movies.aggregate(pipeline, None).await?;
20// Loop through the results and print a summary and the comments:
21while 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çãocomments. 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=[].

Correspondência no comprimento da array

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 campo related_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:
2let 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:
11let 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:
1let 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:
1let mut results = movies.aggregate(pipeline, None).await?;
2// Loop through the results and print a summary and the comments:
3while 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.

Agrupando documentos com

$group
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#[derive(Debug, Deserialize)]
3struct YearSummary {
4 _id: i32,
5 #[serde(default)]
6 movie_count: i64,
7 #[serde(default)]
8 movie_titles: Vec<String>,
9}
10
11// Some movies have "year" values ending with 'è'.
12// This stage will filter them out:
13let 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*/
27let stage_group_year = doc! {
28 "$group": {
29 "_id": "$year",
30 }
31};
32
33let pipeline = vec![stage_filter_valid_years, stage_group_year];
34
35// Loop through the 'year-summary' documents:
36let mut results = movies.aggregate(pipeline, None).await?;
37// Loop through the yearly summaries and print their debug representation:
38while 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_idespecificada e gera um documento para cada valor de_idexclusivo . 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:
1let 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:
1let stage_sort_year_ascending = doc! {
2 "$sort": {"_id": 1}
3};
4
5let 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.

O que você aprendeu?

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!

Próximos passos

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.
A MongoDB University também oferece um curso on-line gratuito sobre MongoDB Aggregation.
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!

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Início rápido
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

Escrevendo uma API com MongoDB no Rust


Jun 10, 2024 | 10 min read
Artigo

Usando MongoDB com Rust Web Development Framework


Aug 29, 2024 | 1 min read
Início rápido

Introdução ao Rust e MongoDB


Sep 23, 2022 | 17 min read
exemplo de código

Projeto de programação para novatos: criar um mecanismo de blog com Rust e MongoDB


Sep 11, 2024 | 0 min read
Sumário