Query MongoDB - .NET SDK
Nesta página
- Casos de uso
- Pré-requisitos
- Configurar
- Dados de exemplo
- Mapeamento de classes
- Criar documentos
- Inserir um único documento
- Insira vários documentos
- Ler documentos
- Encontrar um único documento
- Localizar vários documentos
- Contagem de documentos na coleção
- Atualize documentos
- Atualizar um único documento
- Atualizar vários documentos
- Documentos do Upsert
- Exclua documentos
- Excluir um único documento
- Excluir vários documentos
- Documentos agregados
- Agrupar documentos em uma coleção
- Filtrar documentos
- Dados do projeto
Você pode executar queries dos dados armazenados no MongoDB Atlas diretamente do código do aplicação .NET usando oMongoClient do Realm .NET SDK com a API de query. O Atlas App Services fornece regras de acesso a dados em coleções para recuperar resultados com segurança com base no usuário conectado ou no conteúdo de cada documento.
As seguintes ações permitem o acesso a um cluster do MongoDB Atlas vinculado a partir de um aplicativo .NET usando o Realm .NET SDK.
Observação
Cada operação descrita nesta página usa uma query para corresponder a determinados documentos na coleção na qual a operação é executada. Quando um filtro corresponde a vários documentos em uma coleção, eles são retornados em uma ordem indeterminada a menos que você especifique um parâmetro de classificação. Isto significa que, se você não especificar uma classificação para as funções findOne()
, updateOne()
ou deleteOne()
, sua operação poderá corresponder a qualquer documento que corresponda à query. Para mais informações sobre classificação, consulte cursor.sort().
Casos de uso
Existem várias razões pelas quais você pode querer fazer uma query em uma fonte de dados MongoDB. Trabalhar com dados em seu cliente via Atlas Device Sync nem sempre é prático ou possível. Talvez você queira fazer uma query no MongoDB quando:
O conjunto de dados for grande ou o dispositivo cliente tiver restrições para carregar todo o conjunto de dados
Você estiver criando ou atualizando dados de usuário personalizados
Você estiver recuperando documentos que não sejam modelados no Realm
Sua aplicação precisa acessar collections que não têm esquemas rigorosos
Um serviço que não é do Realm gera coleções que você deseja acessar
Embora não exaustivos, esses são alguns casos de uso comuns para a query direta do MongoDB.
Pré-requisitos
Antes de executar queries do MongoDB a partir do seu aplicativo .NET , você deve configurar o MongoDB Data Access no seu App Services App. Para saber como configurar seu aplicativo de backend para permitir que o Realm SDK consulte o Atlas, consulte Configurar o acesso aos dados do MongoDB na documentação do Atlas App Services .
Configurar
Para trabalhar diretamente com os dados em seu MongoDB Atlas cluster, primeiro instancie um objeto MongoClient , passando o nome do serviço Atlas em seu aplicativo Realm . Em seguida, você instancia um MongoClient.Database e um MongoClient.coleção para cada coleção com a qual deseja trabalhar. O código a seguir usa o nome de serviço padrão "mongodb-atlas" Atlas e cria um MongoClient.Collection
para a coleção "plants" no banco de dados "inventory":
mongoClient = user.GetMongoClient("mongodb-atlas"); dbPlantInventory = mongoClient.GetDatabase("inventory"); plantsCollection = dbPlantInventory.GetCollection<Plant>("plants");
Dados de exemplo
Os exemplos nesta página usam a seguinte coleção MongoDB que descreve várias plantas para venda em uma cadeia de lojas de plantas:
{ _id: ObjectId("5f87976b7b800b285345a8c4"), name: "venus flytrap", sunlight: "full", color: "white", type: "perennial", _partition: "Store 42" }, { _id: ObjectId("5f87976b7b800b285345a8c5"), name: "sweet basil", sunlight: "partial", color: "green", type: "annual", _partition: "Store 42" }, { _id: ObjectId("5f87976b7b800b285345a8c6"), name: "thai basil", sunlight: "partial", color: "green", type: "perennial", _partition: "Store 42" }, { _id: ObjectId("5f87976b7b800b285345a8c7"), name: "helianthus", sunlight: "full", color: "yellow", type: "annual", _partition: "Store 42" }, { _id: ObjectId("5f87976b7b800b285345a8c8"), name: "petunia", sunlight: "full", color: "purple", type: "annual", _partition: "Store 47" }
Mapeamento de classes
Ao trabalhar com objetos no MongoDB, você deve criar classes .NET (POCOs) que correspondem aos objetos BSON. Isto permite a você serializar e desserializar os objetos diretamente, ao invés de trabalhar com objetos genéricos do BsonDocument
. Em todos os exemplos nesta página, estamos utilizando a seguinte classe de mapeamento do Plant
para este propósito:
public partial class Plant : IRealmObject { [ ] public ObjectId Id { get; set; } = ObjectId.GenerateNewId(); [ ] public string? Name { get; set; } [ ] [ ] public string? Sunlight { get; set; } [ ] [ ] public string? Color { get; set; } [ ] [ ] public string? Type { get; set; } [ ] public string? Partition { get; set; } } public enum Sunlight { Full, Partial } public enum PlantColor { White, Green, Yellow, Purple } public enum PlantType { Perennial, Annual }
Observação
Se você optar por fornecer construtores personalizados, você deverá declarar um construtor público sem argumentos.
Para obter mais informações sobre o uso de classes de mapeamento, consulte Mapeando Classes na documentação do driver MongoDB .NET .
Criar documentos
Para criar um documento no datastore do MongoDB, você instancia a classe de mapeamento e passa o novo objeto para InsertOneAsync(). Você também pode criar vários documentos e inseri-los em uma única chamada usando InsertManyAsync().
Inserir um único documento
Você pode inserir um único documento usando InsertOneAsync().
O trecho a seguir insere um único documento descrevendo uma planta "Venus Flytrap" em nossa coleção de "plantas":
var plant = new Plant { Name = "Venus Flytrap", Sunlight = Sunlight.Full.ToString(), Color = PlantColor.White.ToString(), Type = PlantType.Perennial.ToString(), Partition = "Store 42" }; var insertResult = await plantsCollection.InsertOneAsync(plant); var newId = insertResult.InsertedId;
Insira vários documentos
Você pode inserir vários documentos ao mesmo tempo usando InsertManyAsync().
O trecho a seguir insere quatro objetos Plant
na coleção "plants" instanciando os objetos, adicionando-os a um List<Plant>
e passando essa lista para InsertManyAsync()
:
var sweetBasil = new Plant { Name = "Sweet Basil", Sunlight = Sunlight.Partial.ToString(), Color = PlantColor.Green.ToString(), Type = PlantType.Annual.ToString(), Partition = "Store 42" }; var thaiBasil = new Plant { Name = "Thai Basil", Sunlight = Sunlight.Partial.ToString(), Color = PlantColor.Green.ToString(), Type = PlantType.Perennial.ToString(), Partition = "Store 42" }; var helianthus = new Plant { Name = "Helianthus", Sunlight = Sunlight.Full.ToString(), Color = PlantColor.Yellow.ToString(), Type = PlantType.Annual.ToString(), Partition = "Store 42" }; var petunia = new Plant { Name = "Petunia", Sunlight = Sunlight.Full.ToString(), Color = PlantColor.Purple.ToString(), Type = PlantType.Annual.ToString(), Partition = "Store 47" }; var listofPlants = new List<Plant> { sweetBasil, thaiBasil, helianthus, petunia }; var insertResult = await plantsCollection.InsertManyAsync(listofPlants); var newIds = insertResult.InsertedIds;
Ler documentos
Para recuperar documentos do armazenamento de dados, você cria um filtro BsonDocument
que define as propriedades que você deseja pesquisar e, em seguida, passa esse filtro para FindOneAsync () ou FindAsync (). Você também pode obter a contagem de todos os documentos que correspondem ao filtro chamando CountAsync().
Encontrar um único documento
O exemplo a seguir mostra como encontrar uma planta onde a propriedade "nome" é "petunia":
var petunia = await plantsCollection.FindOneAsync( new { name = "Petunia" }, null);
Localizar vários documentos
O exemplo a seguir mostra como encontrar todas as plantas onde a propriedade "type" é "perennial":
var allPerennials = await plantsCollection.FindAsync( new { type = PlantType.Perennial.ToString() }, new { name = 1 });
Importante
Estamos usando o terceiro parâmetro de FindAsync()
, que especifica a ordem de classificação. Se você estiver queryndo mais de um documento, inclua a ordem de classificação para garantir resultados consistentes.
Contagem de documentos na coleção
O exemplo a seguir retorna uma contagem de todas as plantas na coleção:
var allPlants = await plantsCollection.CountAsync();
Atualize documentos
Para atualizar um documento existente no datastore MongoDB, você cria um filtro BsonDocument
que define as propriedades que deseja pesquisar e, em seguida, cria um segundo BsonDocument
que define as propriedades que deseja alterar. Se você estiver atualizando apenas um documento, passará ambos os objetos para UpdateOneAsync(). Se você quiser atualizar vários documentos em massa, chame UpdateManyAsync().
Atualizar um único documento
O código a seguir localiza a planta cuja propriedade "name" é "petunia" e altera sua propriedade "sunlight" para "parcial":
var updateResult = await plantsCollection.UpdateOneAsync( new { name = "Petunia" }, new BsonDocument("$set", new BsonDocument("sunlight", Sunlight.Partial.ToString())) );
Atualizar vários documentos
O código a seguir encontra todas as plantas com um valor " _partition " de " store 47 " e as altera para " area 51 ":
var filter = new { _partition = "Store 47" }; var updateDoc = new BsonDocument("$set", new BsonDocument("_partition", "Area 51")); var updateResult = await plantsCollection.UpdateManyAsync( filter, updateDoc);
Documentos do Upsert
UpdateOneAsync() e UpdateManyAsync() têm uma propriedade booleana opcional que especifica se a atualização deve ser um upsert (ou seja, se o documento não existir, ele deve ser criado). Por padrão, nenhum upsert é realizado.
O exemplo a seguir procura uma planta cuja propriedade name
é "Pothos", type
propriedade é "perene" e sunlight
propriedade é "cheia". Se uma planta corresponder a esses critérios, o método atualizará o valor de _partition
da planta para "Armazenar 42". Se nenhuma planta existir na coleção com esse nome, o método criará uma nova planta com todas as propriedades definidas, incluindo a atualização.
var filter = new BsonDocument() .Add("name", "Pothos") .Add("type", PlantType.Perennial.ToString()) .Add("sunlight", Sunlight.Full.ToString()); var updateResult = await plantsCollection.UpdateOneAsync( filter, new BsonDocument("$set", new BsonDocument("_partition", "Store 42")), upsert: true); /* The upsert will create the following object: { "name": "pothos", "sunlight": "full", "type": "perennial", "_partition": "Store 42" } */
Exclua documentos
O processo de exclusão de documentos é muito parecido com o de criação (ou atualização) de documentos: você cria um BsonDocument
que define as propriedades que deseja combinar e, em seguida, chama DeleteOneAsync(). ou DeleteManyAsync().
Excluir um único documento
O exemplo a seguir exclui o primeiro documento encontrado com um valor de propriedade "nome" de "Thai Basil":
var filter = new BsonDocument("name", "Thai Basil"); var deleteResult = await plantsCollection.DeleteOneAsync(filter);
Excluir vários documentos
O exemplo a seguir exclui todos os documentos que têm um valor de propriedade "tipo" de "anual":
var filter = new BsonDocument("type", PlantType.Annual); var deleteResult = await plantsCollection.DeleteManyAsync(filter);
Documentos agregados
As operações de agregação executam todos os documentos em uma coleção por meio de uma série de estágios de agregação de dados chamados de pipeline de agregação. A agregação permite filtrar e transformar documentos, coletar dados resumidos sobre grupos de documentos relacionados e outras operações de dados complexas.
As operações de agregação aceitam uma array de estágios de agregação como entrada e retornam uma tarefa que resulta em uma coleção de documentos processados pelo pipeline.
Observação
O Compass fornece um utilitário para criar pipelines de agregação e exportá-los para C# e outros idiomas. Para obter mais informações, consulte Construtor de aggregation pipeline.
Agrupar documentos em uma coleção
O .NET SDK suporta agregação em uma coleção com o método AggregateAsync() e sua sobrecarga genérica.
O exemplo a seguir agrupa todos os documentos da coleção plants por seu valor type
, agrega uma contagem do número de cada tipo e os classifica em ordem crescente:
var groupStage = new BsonDocument("$group", new BsonDocument { { "_id", "$type" }, { "count", new BsonDocument("$sum", 1) } }); var sortStage = new BsonDocument("$sort", new BsonDocument("_id", 1)); var aggResult = await plantsCollection.AggregateAsync(groupStage, sortStage); foreach (var item in aggResult) { var id = item["_id"]; var count = item["count"]; Console.WriteLine($"Plant type: {id}; count: {count}"); }
O exemplo acima cria o pipeline com uma série de BsonDocuments aninhados, que podem ficar complicados para gravar e depurar. Se você já estiver familiarizado com a API Consultas, poderá passar consultas como uma string pelo método BSONDocument_parse(). O exemplo a seguir executa a mesma agregação do exemplo anterior:
var groupStep = BsonDocument.Parse(@" { $group: { _id: '$type', count: { $sum: 1 } } } "); var sortStep = BsonDocument.Parse("{$sort: { _id: 1}}"); aggResult = await plantsCollection.AggregateAsync(groupStep, sortStep); foreach (var item in aggResult) { var id = item["_id"]; var count = item["count"]; Console.WriteLine($"Id: {id}, Count: {count}"); }
Filtrar documentos
Você pode utilizar o estágio $match para filtrar documentos utilizando a sintaxe de query padrão do MongoDB.
O exemplo a seguir mostra como filtrar documentos ao usar Agregação. Como sabemos que esse pipeline de agregação retorna uma coleção de Plant
objetos, usamos a substituição genérica do método AggregateAsync():
var matchStage = new BsonDocument("$match", new BsonDocument("type", new BsonDocument("$eq", PlantType.Perennial))); // Alternate approach using BsonDocument.Parse(...) matchStage = BsonDocument.Parse(@"{ $match: { type: { $eq: '" + PlantType.Perennial + @"' } }}"); var sortStage = BsonDocument.Parse("{$sort: { _id: 1}}"); var aggResult = await plantsCollection.AggregateAsync<Plant>(matchStage, sortStage); foreach (var plant in aggResult) { Console.WriteLine($"Plant Name: {plant.Name}, Color: {plant.Color}"); }
Dados do projeto
Você pode utilizar o estágio $project para incluir ou omitir campos específicos de documentos ou calcular novos campos utilizando operadores de agregação. As projeções funcionam de duas formas:
Inclua campos explicitamente com um valor de 1. Isso tem o efeito colateral de excluir implicitamente todos os campos não especificados.
Exclua campos de forma implícita com um valor de 0. Isso tem o efeito colateral de incluir implicitamente todos os campos não especificados.
Esses dois métodos de projeção são mutuamente exclusivos: se você incluir campos explicitamente, não poderá excluir campos explicitamente e vice-versa.
Observação
O campo _id
é um caso especial: ele é sempre incluído em todas as consultas, a menos que seja explicitamente especificado de outra forma. Por esse motivo, você pode excluir o campo _id
com um valor 0
e, ao mesmo tempo, incluir outros campos, como _partition
, com um 1
. Somente o caso especial de exclusão do campo _id
permite tanto a exclusão quanto a inclusão em um estágio $project
.
O exemplo seguinte mostra como utilizar o projeto ao utilizar Agregação. Neste exemplo, estamos:
Excluindo a propriedade "Id",
Incluindo as propriedades "Partição", "Tipo" e "Nome",
Criação de uma nova propriedade chamada "storeNumber", que é criada dividindo o valor _partition no espaço em branco e retornando apenas a segunda parte.
var projectStage = new BsonDocument("$project", new BsonDocument { { "_id", 0 }, { "_partition", 1 }, { "type", 1 }, { "name", 1 }, { "storeNumber", new BsonDocument("$arrayElemAt", new BsonArray { new BsonDocument("$split", new BsonArray { "$_partition", " " }), 1 }) } }); var sortStage = BsonDocument.Parse("{$sort: { storeNumber: 1}}"); var aggResult = await plantsCollection.AggregateAsync(projectStage, sortStage); foreach (var item in aggResult) { Console.WriteLine($"{item["name"]} is in store #{item["storeNumber"]}."); }
O seguinte mostra como você também pode construir o projectStage
utilizando o método BsonDocument.Parse()
:
projectStage = BsonDocument.Parse(@" { _id:0, _partition: 1, type: 1, name: 1, storeNumber: { $arrayElemAt: [ { $split:[ '$_partition', ' ' ] }, 1 ] } }");