Fundamentos do pipeline de agregação do MongoDB C#
Avalie esse Tutorial
Embora as declarações CRUD básicas, como localizar, inserir, atualizar e excluir, possam ajudar muito na criação de seu aplicação, mais cedo ou mais tarde os usuários quererão examinar os dados de diferentes formas. Como exemplo, se você tiver muitos dados em uma coleção de séries temporais, o cálculo dos principais indicadores de desempenho ajudará os usuários a obter conclusões significativas dos dados, por exemplo:
- Qual foi o valor médio do sensor ontem?
- Qual foi a faixa de valores no último mês?
- Quantas leituras foram recebidas na última hora?
É aqui que entramas operações de agregação e ajudam a transformar e resumir os dados para que eles apresentem as informações de uma forma fácil de entender e respondam a perguntas sem ter que examinar os valores individuais. Por exemplo, as agregações podem ser usadas para calcular KPIs, para agrupar dados, em operações de paginação e muitos outros cenários.
Este tutorial coloca o foco em como usar agregações com o driver MongoDB C#; Se você quiser aprender sobre as operações de agregação em detalhes, dê uma olhada no e-book Practical MongoDB Aggregations.
Você pode executar agregações dinamicamente ao consultar seus dados. Na verdade, ao usar o driver MongoDB C#, você pode executar agregações sem nem notar, pois o driver geralmente usa agregações ocultas em vez de comandos de localização simples.
especialmente para operações complexas, é prática comum executar agregações em segundo plano e armazenar os dados em uma coleção de anteontualmente. Isso pode ser feito encerrando o pipeline com um estágio
$merge
ou $out
que grava o resultado da agregação em uma coleção.Esse padrão é chamado de visualizações materializadas on-demand. O pipeline complexo é executado raramente, enquanto as solicitações de leitura mais comuns não sobrecarregam o servidor. Os dados na visualização materializada on-demand podem ser atualizados periodicamente ou em reação a alterações de dados.
Ao configurar um pipeline de agregação , o MongoDB Compass é um bom ponto de ponto. Você pode abrir a coleção em seu cluster de desenvolvimento e reunir um pipeline de agregação na interface gráfica do usuário. Embora a interface gráfica do usuário ofereça mais orientações, também há um editor de pipeline de agregação baseado em texto que pode ser usado por desenvolvedores mais experientes.
Este tutorial mostra várias maneiras de executar agregações a partir de código C#. As amostras usam o banco de dados
sample_mflix
para que você possa experimentar o código facilmente em seu próprio cluster MongoDB Atlas . Consulte a seçãoIniciar na documentação do MongoDB Atlas sobre como implantar um cluster gratuito e carregar o conjunto de dados de amostra.O banco de banco de dados de amostra contém a collection
movies
com uma estrutura de documento semelhante a esta:1 { 2 "_id": ObjectId("573a139af29313caabcef0ad"), 3 "imdb": { 4 "rating": 8.2, 5 "votes": 297933, 6 "id": 112641 7 }, 8 "year": 1995, 9 "title": "Casino", 10 "cast": [ 11 "Robert De Niro", 12 "Sharon Stone", 13 "Joe Pesci", 14 "James Woods" 15 ] 16 }
Em nosso exemplo, queremos filtrar por um ator, agrupar por ano e ordenar os documentos pela classificação média dos filmes do ano. Isso pode ser feito usando o seguinte pipeline de agregação :
1 [ 2 { 3 $match: { 4 cast: "Robert De Niro" 5 } 6 }, 7 { 8 $group: { 9 _id: "$year", 10 rating: { $avg: "$imdb.rating" } 11 } 12 }, 13 { 14 $sort: { 15 rating: -1 16 } 17 } 18 ]
Ao executar o pipeline no MongoDB Compass, obtemos o seguinte resultado:
1 [ 2 { 3 "_id": 1974, 4 "rating": 9.1 5 }, 6 { 7 "_id": 1980, 8 "rating": 8.3 9 }, 10 { 11 "_id": 1995, 12 "rating": 8.25 13 }, 14 { 15 "_id": 1990, 16 "rating": 8.25 17 }, 18 // ... 19 ]
Para suportar a agregação, criamos os seguintes POCOs em C#:
1 [ ]2 [ ]3 public class Movie 4 { 5 [ ]6 public required string Title { get; set; } 7 8 [ ]9 public required int Year { get; set; } 10 11 [ ]12 public List<string> Cast { get; set; } = new(); 13 14 [ ]15 public Imdb Imdb { get; set; } = new(); 16 } 17 18 [ ]19 public class Imdb 20 { 21 [ ]22 public double Rating { get; set; } 23 } 24 25 public class RatingByYear 26 { 27 public int Year { get; set; } 28 29 public double AvgRating { get; set; } 30 }
A maneira básica e mais avançada de executar um agregação pipeline em C# é usar o método
AggregateAsync
de IMongoCollection<T>
. Esse método usa uma definição de pipeline como parâmetro de entrada mais importante e retorna um cursor. Para nossa amostra, poderíamos representar o pipeline de agregação assim:1 var pipeline = new EmptyPipelineDefinition<Movie>() 2 .Match(x => x.Cast.Contains("Robert De Niro")) 3 .Group( 4 x => x.Year, 5 x => new RatingByYear() 6 { 7 Year = x.Key, 8 AvgRating = x.Average(y => y.Imdb.Rating) 9 }) 10 .Sort(Builders<RatingByYear>.Sort.Descending(x => x.AvgRating)); 11 var result = await (await movies.AggregateAsync(pipeline)).ToListAsync();
Primeiro, definimos o pipeline e adicionamos os estágios necessários ao pipeline. Como você pode ver no código acima, você usa expressões Lambda ou o
Builder<T>
que você pode saber ao unir declarações CRUD . Após executar a agregação, usamos ToListAsync
para armazenar o resultado da agregação em uma lista.Para nossa amostra, os estágios básicos
$match
, $group
e $sort
são suficientes, mas há uma grande variedade de métodos que você pode usar para configurar pipelines de agregação complexos. Se não houver nenhum método explícito para um estágio específico do pipeline, você poderá usar o métodoAppendStage
para anexar um estágio definido como BsonDocument
. Analisaremos mais de perto esse método no acompanhamento deste tutorial.A amostra anterior fez uso de uma interface fluente ao definir o pipeline de agregação . Além do
AggregateAsync
, oIMongoCollection<T>
também oferece um métodoAggregate
que é o ponto de ponto para a interface de agregação fluente:1 var result = await movies 2 .Aggregate() 3 .Match(x => x.Cast.Contains("Robert De Niro")) 4 .Group( 5 x => x.Year, 6 x => new RatingByYear() 7 { 8 Year = x.Key, 9 AvgRating = x.Average(y => y.Imdb.Rating) 10 }) 11 .Sort(Builders<RatingByYear>.Sort.Descending(x => x.AvgRating)) 12 .ToListAsync();
Isso reduz o código acima em algumas linhas, mas principalmente oferece a mesma funcionalidade que definir o pipeline manualmente.
O driver MongoDB C# oferece um provedor LINQ poderoso que é capaz de transformar declarações LINQ em um pipeline de agregação MongoDB . Dessa forma, os desenvolvedores podem usar as declarações LINQ em seu código como estão familiarizados; um pipeline de agregação é criado sob o capô e executado no banco de banco de dados quando os resultados são enumerados:
1 var result = movies 2 .AsQueryable() 3 .Where(x => x.Cast.Contains("Robert De Niro")) 4 .GroupBy(x => x.Year) 5 .Select(x => new RatingByYear() 6 { 7 Year = x.Key, 8 AvgRating = x.Average(y => y.Imdb.Rating) 9 }) 10 .OrderByDescending(x => x.AvgRating) 11 .ToList();
Ou, alternativamente, na sintaxe da query:
1 var result = (from m in movies.AsQueryable() 2 where m.Cast.Contains("Robert De Niro") 3 group m by m.Year into grp 4 select new RatingByYear() 5 { 6 Year = grp.Key, 7 AvgRating = grp.Average(y => y.Imdb.Rating) 8 } 9 into x 10 orderby x.AvgRating descending 11 select x) 12 .ToList();
Embora ainda haja uma chance de que uma query LINQ específica não possa ser transformada em um pipeline de agregação , esses casos se tornaram muito raros com o provedor LINQ v3 e, muitas vezes, podem ser resolvidos reestruturando a instrução LINQ. Para outros casos, o fornecedor é mantido pelo MongoDB e estendido regularmente se houver algo faltando para dar suporte a uma query LINQ.
Como você pode ver, é muito fácil configurar e executar pipelines de agregação com o driver MongoDB C#. Na verdade, há diversas maneiras de atingir esse objetivo. Qual método é o melhor para usar em seu projeto?
O LINQ é amplamente usado em projetos C# e é uma técnica de query que os desenvolvedores aprenderam muito cedo em sua viagem com C#. O uso da abordagem baseada em LINQ permite que os desenvolvedores se beneficiam do poder dos agregação pipelines sem o conhecimento profundo do MongoDB .
É claro que essa abstração também significa menos controle sobre os agregação pipelines; especialmente em cenários complexos, o uso dos métodos
IMongoCollection<T>
oferece a flexibilidade de reunir o pipeline para que ele se ajuste perfeitamente à finalidade.Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.