NoSQL – MongoDB e C#

Com prometido, neste artigo estarei demonstrando como desenvolver uma integração básica com o Mongo DB (GET/SET) e C#, com os drivers que a própria Mongo DB desenvolve e dá suporte.

O código fonte completo do driver para .NET do Mongo DB pode ser baixado no site:
https://github.com/mongodb/mongo-csharp-driver/downloads

Se você não tem interesse no código fonte, também é possível baixar somente as DLLs (Setup).

A solution do driver é bem organizada (com testes unitários, setup e uma boa documentação), mas o que precisaremos são somente os binários do projeto Driver, assim basta dar um “build” em modo “release” e copiar as DLL para sua aplicação.

Após adicionadas e referenciadas as DLLs em um projeto .NET, no meu caso, uma aplicação WebService, vamos ao desenvolvimento:

O código abaixo demonstra a pesquisa de um único registro com o método Get e o parâmetro id, e com o método Set, a inserção e atualização de dados:

namespace MongoEndPoint
{
    using System.Web.Services;
    using System.Web.Script;
    using MongoDB.Bson;
    using MongoDB.Driver;

    [WebService]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class MongoEndPoint : WebService
    {
        [WebMethod]
        public string Get(int id)
        {
            string connectionString = "mongodb://localhost";

            var server = MongoServer.Create(connectionString);

            server.Connect();

            var db = server.GetDatabase("azul");

            var collection = db.GetCollection("coluna");

            var query = new QueryDocument("id", id);

            var obj = collection.FindOne(query);

            if (obj == null || !obj.Contains("nome")) return null;

            return obj["nome"].AsString;
        }

        [WebMethod]
        public void Set(int id, string nome)
        {
            string connectionString = "mongodb://localhost";

            var server = MongoServer.Create(connectionString);

            server.Connect();

            var db = server.GetDatabase("azul");

            var collection = db.GetCollection("coluna");

            var query = new QueryDocument("id", id);

            var obj = collection.FindOne(query);

            if (obj == null)
            {
                var doc = new BsonDocument();
                doc.Add("id", id);
                doc.Add("nome", nome);
                collection.Insert(doc);
            }
            else
            {
                var doc = new UpdateDocument();
                doc.Add("id", id);
                doc.Add("nome", nome);
                collection.Update(query, doc);
            }
        }
    }
}

Por fim, o método Get:

E o método Set:

Este foi meu último artigo que planejei tratar sobre NoSQL, escrito principalmente para aqueles que acompanham os artigos do blog saibam um pouco sobre o outro “lado da moeda”.

Se eu conhecer ou me apresentarem outro NoSQL que me chame a atenção, estarei escrevendo novemente sobre o assunto, mas por hora espero que tenham gostado destes cinco artigos.

NoSQL – MongoDB Instalação e Comandos Básicos

Neste artigo vou tratar do Mongo DB, um sistema de banco de dados orientado á documentos, isso quer dizer que ele também é um NoSQL, mas diferente do Cassandra, ele é mais flexível em termos de consultas (query) e gerenciamento, além de possuir uma ótima documentação para o pessoal de desenvolvimento (PHP, C++, C#, Java, Ruby, Python…).

Para um primeiro passo, vamos à instalação no Windows, começando pelo download:
http://www.mongodb.org/downloads

Após extrair os arquivos, crie as pastas “data” e “logs”:

Para instalação, é interessante utilizar o prompt do DOS para acompanhar mensagens de erro que venham aparecer. Por questões de acessos, executar o prompt do DOS como Administrador também poderá ajudar, pois será criado um serviço do Windows durante o processo de instalação.

Na pasta “bin” execute o seguinte comando, informando o caminho para um arquivo de logs e a pasta onde ficarão os arquivos de dados.

mongod --bind_ip 127.0.0.1 --logpath c:\mongodb\logs\mongo.log --logappend --dbpath c:\mongodb\data --directoryperdb --install

Se tudo funcionar corretamente, haverá entre os serviços do Windows o Mongo DB, agora basta iniciá-lo:

Para desinstalação, também bem simples, utilize o comando:

mongod --remove

O Mongo DB também possui seu prompt de comando (mongo.exe), que por padrão já se conecta ao servidor local:

Alguns comandos como o help poderão ajudar a entender como “navegar” com o prompt, não chega aos pés do help do “PowerShell”, mas ajuda.

Para demonstrar a criação de um banco de dados e “tabelas”, vamos primeiro relacionar os bancos de dados existentes:

show dbs

Definir qual banco será utilizado (detalhe, ele ainda não precisa existir para ser utilizado) e para “materializá-lo” basta fazer um insert em uma “tabela” que também não precisa existir ainda, que o Mongo DB se encarregará de criar toda a estrutura para salvar seus dados:

use nomeDoBanco

db.coluna.insert({id: 1, nome: 'Paulo'})

Para uma primeira consulta, criaremos um registro com o comando insert e recuperaremos este valor com comando find. Por fim removendo os registros com o comando remove, sob o critério que os registros a serem apagados tenham a “coluna” id com o valor ‘1’:

db.coluna.insert({id: 1, nome: 'valor'})

db.coluna.find()

db.coluna.remove({id: 1})

db.coluna.find()

Removendo todos os dados com o comando remove sem estabelecer critério, vamos ao “UPDATE”, onde com uma variável será possível capturar o registro e realizar as alterações. Para que as alterações tenham efeito, usaremos o comando update segundo um determinado critério (como um WHERE no SQL) e a variável com os valores a serem alterados (como um SET no SQL).

db.coluna.remove()

db.coluna.insert({id: 1, nome: 'valor'})

var variavel = db.coluna.findOne({id: 1})

variavel

variavel.nome = 'novo valor'

variavel

db.coluna.update({id: 1}, variavel}

db.coluna.findOne({id: 1})

Apresentado o Mongo DB, amanhã vou utilizar o “driver” que a própria Mongo DB desenvolve e dá suporte, demonstrando como criar um GET/SET simples com C#.

Antes de eu ter terminado este artigo, nosso amigo Márcio F. Althmann (@mfalthmann) escreveu sobre a experiência dele com o MongoDB e o ASP.NET MVC 3, vale a pena conferir:
http://www.marcioalthmann.net/2011/01/brincando-com-o-mongodb

NoSQL – Apache Cassandra e C#

Para uma demonstração simples de como desenvolver um EndPoint de get/set com o Cassandra em .NET, utilizei a biblioteca Aquiles v0.6.4.2 (http://aquiles.codeplex.com/), que mesmo com pouca documentação, permite uma implementação fácil e bem intuitiva.

Por que criarei um EndPoint/WebService? Pois WebServices permitem facil interação com qualquer aplicação independente de plataforma.

O primeiro passo foi adicionar e referenciar as DLLs da biblioteca em um projeto Web Service:

Configurei o web.config, de acordo com meu cenário (onde o Cassandra esta no ‘localhost’, porta 9160):

  <configSections>
    ...
    <section name="aquilesConfiguration" type="Aquiles.Configuration.AquilesConfigurationSection,Aquiles"/>
  </configSections>

  <aquilesConfiguration>
    <clusters>
      <add friendlyName="LocalCassandra">
        <connection poolType="SIZECONTROLLEDPOOL" factoryType="BUFFERED"/>
        <endpointManager type="ROUNDROBIN" defaultTimeout="6000">
          <cassandraEndpoints>
            <add address="localhost" port="9160"/>
          </cassandraEndpoints>
        </endpointManager>
      </add>
    </clusters>
  </aquilesConfiguration>

E criei um WebService bem simples utilizando o keyspace ToyStore do artigo anterior:

using System;
using System.Web.Services;

namespace CassandraEndPoint
{
    using Aquiles.Command;
    using Aquiles;
    using Aquiles.Helpers.Encoders;

    [WebService]
    public class wsToyStore : WebService
    {
        const string cassandraConn = "LocalCassandra";
        const string columnFamily = "Toys";
        const string keyspace = "ToyStore";

        [WebMethod]
        public string GetToyColumn(string key, string columnName)
        {
            AquilesHelper.Initialize();

            var cmd = new GetCommand
            {
                KeySpace = keyspace,
                ColumnFamily = columnFamily,
                Key = key
            };

            cmd.ColumnName = ByteEncoderHelper.UTF8Encoder.ToByteArray(columnName);

            using (var connection = AquilesHelper.RetrieveConnection(cassandraConn))
            {
                connection.Open();
                connection.Execute(cmd);
                connection.Close();
            }

            if (cmd.Output == null)
                return string.Empty;

            var bytes = cmd.Output.Column.Value;

            var value = ByteEncoderHelper.UTF8Encoder.FromByteArray(bytes);

            return value;
        }

        [WebMethod]
        public void SetToyColumn(string key, string columnName, string value)
        {
            AquilesHelper.Initialize();

            var cmd = new InsertCommand
            {
                KeySpace = keyspace,
                ColumnFamily = columnFamily,
                Key = key
            };

            cmd.Column =
                new Aquiles.Model.AquilesColumn()
                {
                    ColumnName = ByteEncoderHelper.UTF8Encoder.ToByteArray(columnName),
                    Value = ByteEncoderHelper.UTF8Encoder.ToByteArray(value),
                    Timestamp = DateTime.Now.Ticks
                };

            using (var connection = AquilesHelper.RetrieveConnection(cassandraConn))
            {
                connection.Open();
                connection.Execute(cmd);
                connection.Close();
            }
        }
    }
}

E como resultado, o método SetToyColumn para inserir ou alterar o valor de uma coluna.

E o método GetToyColumn, para recuperar estes valores:

A biblioteca mais low-level que pode ser encontrada para trabalhar com Apache Cassandra e C# é a Thrift, mas podem ser encontradas outras mais high-level que até têm suporte á LINQ, como a Cassandraemon.

Abaixo a relação de bibliotecas:

Thrift:
http://incubator.apache.org/thrift

Aquiles:
http://aquiles.codeplex.com

Hector Sharp:
http://www.hectorsharp.com

Fluent Cassandra:
http://github.com/managedfusion/fluentcassandra

Cassandraemon:
http://cassandraemon.codeplex.com

NoSQL – Operações básicas do Apache Cassandra

Caminhando mais um pouco com o Apache Cassandra após a instalação, vamos nos conectar ao servidor e realizar algumas operações, como criar uma “tabela”, inserir, alterar, consultar e remover registros.

Para isso, esteja com o “cassandra.bat” (servidor) rodando e utilize o arquivo “cassandra-cli.bat” (cliente) como prompt de comando para se conectar ao Cassandra, executando as seguintes linhas:

connect localhost/9160

Com o comando abaixo você irá listar as “tabelas” (keyspaces) que você tem em seu servidor:

show keyspaces

Para adicionar um novo keyspace, você terá que parar a aplicação fechando o prompt do “cassandra.bat”, em seguida, ir ao arquivo “conf\storage-conf.xml” e encontrar a tag “Keyspaces”:

Mesmo que poderíamos utilizar o Keyspace1 na demonstração, iremos adicionar uma segunda tag chamada Toys mais simples, que será nossa “tabela” de exemplo:

    <Keyspace Name="ToyStore">
      <ColumnFamily Name="Toys" CompareWith="UTF8Type" />
<ReplicaPlacementStrategy>org.apache.cassandra.locator.RackUnawareStrategy</ReplicaPlacementStrategy>
      <ReplicationFactor>1</ReplicationFactor>
      <EndPointSnitch>org.apache.cassandra.locator.EndPointSnitch</EndPointSnitch>
    </Keyspace>

Iniciando o “cassandra.bat”, conectando-se novamente com o prompt cliente teremos mais um keyspace:

Agora nosso primeiro “insert”, definimos que o registro com chave “Bola” terá “Azul” como valor para a coluna “Cor”:

set ToyStore.Toys['Bola']['Cor'] = 'Azul'

Agora atualizamos a “Cor” para “Vermelho” e adicionamos a coluna “Tamanho” com valor 3 (veja que teremos um erro com o valor 3, visto que definimos que trabalharíamos somente com UTF8Type (ou texto) na definição da ‘tabela’):

set ToyStore.Toys['Bola']['Cor'] = 'Vermelho'
set ToyStore.Toys['Bola']['Tamanho'] = 3

Para recuperar estes valores, utilizamos o comando get informando a chave do registro:

get ToyStore.Toys['Bola']

Ou também informando a coluna desejada:

get ToyStore.Toys['Bola']['Cor']

Por fim, um count:

count ToyStore.Toys['Bola']

E excluindo o registro:

del ToyStore.Toys['Bola']

Referência:
http://www.divconq.com/2010/how-to-add-and-retrieve-data-from-a-cassandra-database

NoSQL – Instalando o Apache Cassandra

Depois de uma breve explicação sobre o outro lado da moeda, vamos instalar e configurar o Apache Cassandra.

Primero passo, baixar uma versão binária estável:
http://cassandra.apache.org/download
(ex.: apache-cassandra-0.6.8-bin.tar.gz)

Descompactar:

Se você tentar executar o “cassandra.bat” na pasta bin:

Teremos o primeiro erro:

Então, antes verifique se você tem o Java 6 instalado em seu equipamento, se não tive instale:

Depois de instalar, verifique se dentre as variáveis de sistema existe JAVA_HOME definido.

1. Propriedades do computador:

2. Verifique se existe a variável JAVA_HOME configurada ou adicione uma nova:

3. Informe o nome da variável apontando para a pasta raiz do Java:

Com o Java instalado e configurado, vamos configurar os paths do Cassandra no arquivo storage-conf.xml da pasta conf:

Procure as seguintes linhas:

Onde estiver escrito “/var/lib/cassandra”, altere para o caminho da aplicação no Windows, exemplo “C:/Cassandra”:

Agora execute o cassandra.bat da pasta bin, e se tudo estiver ok, você terá a seguinte resposta:

INFO 22:42:28,061 Binding thrift service to localhost/127.0.0.1:9160
INFO 22:42:28,066 Cassandra starting up…

Pronto, servidor Apache Cassandra funcionando!

Referência:
http://support.qualityunit.com/knowledgebase/developers/cassandra/cassandra-installation-on-windows-7.html

Falando em NoSQL

Para que os leitores do blog também possam conhecer um pouco do outro lado da moeda, trabalharei alguns posts sobre o Apache Cassandra, que vende a ideia do NoSQL como uma tecnologia ótima para soluções de armazenamento de dados simples (key/value) e espalhados por vários servidores (cluster), com uma interação bem crua (get/set) simplesmente para manipular e consultar dados, lembrando também que um de seus principais clientes são o Facebook e o Twitter.

Mais informações:
http://cassandra.apache.org

Antes de utilizar o Apache Cassandra em produção, procure conhecer suas limitações (http://wiki.apache.org/cassandra/CassandraLimitations) e conversar bem com os profissionais de TI que têm familiaridade com esta tecnologia.