É inegável a importância dos bancos de dados relacionais dentro do mundo corporativo. O surgimento desta tecnologia revolucionou o tratamento de informações nos mais variados ramos de atuação, conferindo agilidade e flexibilidade às organizações em suas operações cotidianas. Este uso em larga escala de bases relacionais deve certamente continuar, tendo como pilares a linguagem SQL e a praticidade desta última na manipulação de dados.
Por mais que a tecnologia relacional atenda a um amplo escopo de necessidades, em alguns cenários bem específicos esta abordagem pode não ser a solução mais adequada:
- Questões como uma alta disponibilidade e a capacidade de um sistema de banco de dados se adaptar a níveis de uso crescentes (escalabilidade) costumam exigir pesados investimentos em infraestrutura. Nem sempre existirão recursos disponíveis (financeiros ou não) para atender a tais demandas imediatamente;
- A estrutura rígida de linhas e colunas das tabelas relacionais também será um fator limitante em determinados contextos. A adaptação de uma base convencional para agrupamentos de dados mais complexos pode se revelar uma tarefa bastante árdua, sobretudo se o conteúdo em questão apresentar um formato variável.
Uma opção às dificuldades aqui levantadas seria o uso de uma solução NoSQL (sigla interpretada por alguns como “Not only SQL”). Tecnologias em conformidade com este paradigma costumam adotar uma estrutura diferente daquela tipicamente relacional, de forma a oferecer assim uma resposta a requisitos como alta disponibilidade, escalabilidade e a necessidade de uma estrutura para armazenamento mais flexível. Diversos são os bancos de dados NoSQL disponíveis no mercado, com o MongoDB correspondendo a uma das alternativas mais populares entre desenvolvedores de software.
O objetivo deste artigo é trazer uma visão geral do MongoDB, bem como de que maneira o mesmo pode ser utilizado na implementação de projetos baseados no .NET Framework.
Um pouco mais sobre o MongoDB
O nome MongoDB tem sua origem na palavra inglesa “humongous”, termo este geralmente empregado para expressar algo considerado gigantesco. Trata-se de uma solução gratuita e open source mantida por uma empresa chamada MongoDB Inc. (anteriormente conhecida como 10gen), encontrando-se atualmente (Fevereiro/2016) na versão 3.2.
Do ponto de vista estrutural o MongoDB conta com as seguintes características:
- Ao invés de registros organizados em tabelas relacionais formadas por colunas com um tipo pré-definido, um banco do MongoDB é composto por coleções; cada coleção, por sua vez, é constituída por uma série de documentos (Imagem 1). Por esse motivo este produto é classificado como um banco de dados NoSQL baseado em documento;
- Os documentos no MongoDB são formados por campos (o equivalente a colunas no modelo relacional), empregando um formato conhecido como BSON para o armazenamento de informações. Já o padrão BSON (abreviação de binary JSON) representa uma variação da especificação JSON com suporte à manipulação de dados binários, além de tipos convencionais como strings ou valores numéricos;
- A utilização de uma estrutura baseada em JSON torna o MongoDB um banco schemaless, ou seja, sem um esquema rígido. Isto permite a utilização de um formato flexível para os diferentes documentos que venham a compor uma coleção, diferentemente das colunas que seguem um padrão pré-definido para todos os registros em uma tabela relacional;
- Todo documento criado no MongoDB conta com um campo chamado “_id”, o qual nada mais é do que um identificador único e gerado automaticamente no momento da inclusão deste elemento;
- Além dos aspectos mencionados, o MongoDB possui ainda o suporte a informações geoespaciais (incluindo latitude e longitude) e permite a criação de índices para a otimização de consultas.
Imagem 1. Estrutura geral de um banco de dados no MongoDB
OBSERVAÇÃO: maiores detalhes sobre a arquitetura empregada pelo MongoDB podem ser encontrados na seção “Referências”.
Instalando o MongoDB no Windows
O download da versão do MongoDB para Windows pode ser efetuado através do seguinte link:
ATENÇÃO: Os procedimentos descritos nesta seção foram realizados em uma máquina com o Windows 10 Professional instalado (estas ações são válidas, a princípio, em outras versões do Windows suportadas pelo MongoDB).
Por motivos de simplificação, a instalação do MongoDB foi efetuada no diretório C:\MongoDB\. Também será necessário criar o diretório C:\data\db\, o qual corresponde ao espaço utilizado pelo MongoDB para a geração de arquivos com dados e logs.
Para ativar o uso do MongoDB acionar o executável mongod.exe, instalado em C:\MongoDB\bin\. Com isto o servidor deste banco NoSQL estará no ar (Imagem 2). Vale destacar que a execução do arquivo mongod.exe pode acontecer tanto via prompt de comando, quanto por meio do agendamento de uma tarefa no Windows.
Imagem 2. O utilitário mongod.exe em execução
A execução de ações em bancos de dados do MongoDB pode ser feita por meio do utilitário de linha de comando mongo.exe (também criado em C:\MongoDB\bin\). Na Imagem 3 é possível observar esta aplicação em ação.
Imagem 3. O utilitário mongo.exe em execução
MongoDB e o .NET Framework
O package para acesso ao MongoDB em soluções .NET (MongoDB.Driver) pode ser instalado via NuGet no Visual Studio, como indicado na Imagem 4. Para os exemplos descritos nesta seção foi utilizada a versão 2.2.3 deste driver.
Imagem 4. Adicionando o MongoDB.Driver a uma aplicação .NET
Ao se realizar este procedimento serão adicionadas ao projeto as referências destacadas na Imagem 5:
Imagem 5. Bibliotecas do MongoDB adicionadas a uma aplicação .NET
Para os exemplos envolvendo a integração MongoDB-C# será utilizada a classe Cidade, cuja definição encontra-se na Listagem 1:
- A propriedade _id corresponde ao identificador único de um documento, tendo sido declarada como do tipo ObjectId (namespace MongoDB.Bson);
- Também foram definidos campos representando o nome e o estado de uma cidade.
[sourcecode language=”csharp”]
using MongoDB.Bson;
namespace TesteMongoDB
{
class Cidade
{
public ObjectId _id { get; set; }
public string Nome { get; set; }
public string Pais { get; set; }
}
}
[/sourcecode]
Listagem 1: Classe Cidade
A Listagem 2 demonstra a inclusão de uma cidade em um banco de dados chamado ExemploCSharp:
- Uma primeira variável foi declarada de forma a armazenar a conexão de acesso local ao servidor do MongoDB (por default, o mesmo é instalado na porta 27017);
- Será gerada então uma instância da classe MongoClient (namespace MongoDB.Driver), que servirá de base para o acesso aos bancos NoSQL existentes em um servidor;
- Uma referência a um banco de dados será obtida invocando o método GetDabase do objeto MongoClient; esta operação recebe como parâmetro o nome de uma base, trazendo como resultado uma instância do tipo IMongoDatabase (namespace namespace MongoDB.Driver);
- Com a referência de IMongoDatabase será acionado o método GetCollection, com este último recebendo como parâmetros a classe que representa um documento e o nome da coleção a ser manipulada. O retorno desta ação será uma referência baseada na interface genérica IMongoCollection (namespace MongoDB.Driver);
Uma instância do tipo Cidade é então criada, com o preenchimento das propriedades que serão persistidas no banco de dados. Por fim, o método InsertOne será executado, procedendo com a inclusão dos dados na base; neste momento constará na propriedade _id o valor único gerado pelo MongoDB para esse novo documento.
[code language=”csharp”]
…
string connectionString = “mongodb://localhost:27017”;
MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);
var cidades = db.GetCollection<Cidade>(“cidades”);
Cidade cidade = new Cidade();
cidade.Nome = “Roma”;
cidade.Pais = “Italia”;
cidades.InsertOne(cidade);
ObjectId _idInclusao = cidade._id;
…
[/code]
Listagem 2: Adicionando um novo documento
É importante ressaltar que, na eventualidade de um banco e/ou coleção ainda não existir fisicamente, o procedimento descrito nesta segunda listagem fará com que tais elementos sejam automaticamente criados. Na Imagem 6 está o resultado de uma consulta à coleção “cidades” após a execução deste último trecho de código:
Imagem 6. Coleção após da inclusão de uma primeira cidade
O próximo passo agora será alterar a classe cidade, adicionando à mesma um campo que referencie o estado/província (Listagem 3):
[code language=”csharp” highlight=”9"]
using MongoDB.Bson;
namespace TesteMongoDB
{
class Cidade
{
public ObjectId _id { get; set; }
public string Nome { get; set; }
public string Estado { get; set; }
public string Pais { get; set; }
}
}
[/code]
Listagem 3: Classe Cidade após inclusão do campo Estado
A Listagem 4 apresenta um trecho de código que efetuará um teste já contemplando o uso da propriedade Estado:
[code language=”csharp” highlight=”12"]
…
string connectionString = “mongodb://localhost:27017”;
MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);
var cidades = db.GetCollection<Cidade>(“cidades”);
Cidade cidade = new Cidade();
cidade.Nome = “Sao Paulo”;
cidade.Estado = “Sao Paulo”;
cidade.Pais = “Brasil”;
cidades.InsertOne(cidade);
ObjectId _idInclusao = cidade._id;
…
[/code]
Listagem 4: Adicionando um segundo documento
Para localização de documentos o driver do MongoDB disponibiliza o método Find, que deverá ser invocado a partir de uma coleção (Listagem 5). A expressão lambda informada como parâmetro neste exemplo retornará sempre true, de forma a retornar todos os elementos existentes:
[code language=”csharp” highlight=”8,9"]
…
string connectionString = “mongodb://localhost:27017”;
MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);
List<Cidade> cidades = db.GetCollection<Cidade>(“cidades”)
.Find(_ => true).ToList();
…
[/code]
Listagem 5: Retornando todos os elementos de uma coleção
Expressões lambda mais específicas podem ser utilizadas, de forma a permitir a localização de itens específicos (Listagem 6):
[code language=”csharp” highlight=”8,9"]
…
string connectionString = “mongodb://localhost:27017”;
MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);
Cidade cidade = db.GetCollection<Cidade>(“cidades”)
.Find(c => c.Nome == “Roma”).ToList().First();
…
[/code]
Listagem 6: Localizando um documento específico
Na Listagem 7 é possível observar um exemplo envolvendo a atualização de um documento:
- Inicialmente será localizado o elemento a ser modificado, empregando-se para isto o método Find em conjunto com uma expressão lambda;
- Modificações são então realizadas na referência obtida;
- Na sequência o método ReplaceOne é invocado. O primeiro parâmetro informado representa uma expressão lambda baseada na propriedade _id, ao passo que o segundo valor é a própria instância do tipo Cidade com os dados a serem atualizados.
[code language=”csharp” highlight=”10,11,12,13,14"]
…
string connectionString = “mongodb://localhost:27017”;
MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);
var cidades = db.GetCollection<Cidade>(“cidades”);
Cidade cidade = cidades
.Find(c => c.Nome == “Sao Paulo”).ToList().First();
cidade.Estado = “SP”;
cidades.ReplaceOne(c => c._id == cidade._id, cidade);
…
[/code]
Listagem 7: Atualizando um documento
As modificações efetuadas até este ponto podem ser visualizadas na Imagem 7.
Imagem 7. Coleção após inclusões e alterações
Finalmente a Listagem 8 traz um caso de exclusão de um documento:
- Trata-se de um processo bastante similar àquele descrito para alterações, envolvendo novamente o uso do método Find;
- O método DeleteOne é acionado, recebendo como parâmetro uma expressão lambda cujo filtro fará uso da propriedade _id e procedendo com a remoção do elemento em questão.
[code language=”csharp” highlight=”8,9,10"]
…
string connectionString = “mongodb://localhost:27017”;
MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);
var cidades = db.GetCollection<Cidade>(“cidades”);
cidades.DeleteOne(c => c.Nome == “Roma”);
…
[/code]
Listagem 8: Excluindo um documento
Na Imagem 8 está o resultado após a exclusão realizada neste último passo.
Imagem 8. Coleção após a exclusão
Conclusão
Assim como outras soluções NoSQL, o MongoDB se destaca pela sua flexibilidade, compatibilidade com diversas plataformas de desenvolvimento e poder de processamento. Contudo, será necessário sempre se proceder com uma análise bem criteriosa quanto à adoção deste banco de dados. É importante ter em mente que o modelo relacional não perderá sua importância e, em muitos casos, ainda continuará a ser a alternativa mais adequada na implementação de novos projetos.
Espero que este post tenha sido útil.
Até uma próxima oportunidade!
Referências
Exemplo de utilização do MongoDB em uma aplicação .NET
https://gallery.technet.microsoft.com/Exemplo-de-utilizao-do-a3cb1f6c
Configuração do ambiente para MongoDB no Windows
https://pablojuancruz.wordpress.com/2014/09/03/configurando-ambiente-mongodb-no-windows/
FAQ: MongoDB Fundamentals
https://docs.mongodb.org/manual/faq/fundamentals/
The MongoDB Manual
https://docs.mongodb.org/manual/