O BigData é um fenômeno que faz parte da nossa vida de forma cada vez mais intrínseca. Boa parte disso são dados não estruturados, ou faz parte de um volume de dados tão grande e/ou não estruturado, que bancos de dados relacionais acabam não atendendo todos os requisitos que se pode ter num projeto que lide com enormes quantidades de informação.

Exatamente por isso, os bancos de dados não relacionais estão aparecendo com uma frequência cada vez maior em projetos que lidam com grandes volumes de dados e ganhando espaço nas empresas que desejam trabalhar com essa característica.

Mas e como os marinheiros de primeira viagem, nesse mundo fascinante, podem fazer para ao menos saber do que se trata tudo isso?

Pensando em como aprender e aproveitar para por em prática algumas ideias, se pesquisarmos sobre os bancos não relacionais, um dos que aparentemente se mostra mais fácil de se aprender e compreender a mecânica do noSQL, é o MongoDB. Chegamos a essa conclusão devido a fatores como ele ser orientado a documentos, manipulação e armazenamento de dados via JSON e ter comandos como find(), ensureIndex(), insert(), update(), save(), remove(), e diversos outros que se não são iguais ao do mundo SQL, lembram alguns comandos Linux, o que torna o aprendizado muito mais fácil.

Muito bem, então o primeiro passo é instalar e ver como que a coisa funciona, certo?

Observação: Os exemplos deste artigo foram desenvolvidos em um sistema operacional Linux, mais especificamente o Ubuntu na sua versão 12.10, onde estão instalados o PHP, o Apache, o MySQL.

A documentação existente no site do MongoDB é muito completa e abrangente, e seguindo os passos descritos ali, provavelmente não se tem problema algum nessa etapa.

Apenas vale destacar que para instalar a última versão estável do banco de dados no Ubuntu, use este comando: sudo apt-get install mongodb-10gen.

Será mais fácil do que tentar instalar usando este comando aqui: sudo apt-get install mongodb-10gen=2.2.

A última versão do banco de dados, no momento da escrita deste artigo, é a 2.4.1.

Ao terminar a instalação, talvez seja necessário editar o arquivo mongodb.conf para alterar o parâmetro "dbpath", esse arquivo fica localizando em /etc.

Por padrão, o MongoDB tenta configurar a pasta padrão onde serão armazenados os bancos de dados, como sendo /data/db e sua inicialização pode falhar se não alterar a pasta padrão no seu arquivo de configuração e ele não tiver poderes para criar a pasta.

Terminada esta etapa, vamos ao PHP. O MongoDB não é um banco de dados suportado por padrão no PHP, para podermos trabalhar com esse banco de dados, é preciso instalar o driver quer permitirá a comunicação entre o PHP e o MongoDB.

Por via das duvidas, antes de baixar qualquer coisa, é recomendado criar uma página contendo o phpinfo(); e assim saber com certeza se o driver já está instalado (ou suportado) na versão do PHP instalado.

Se não houver nenhuma menção ao Mongo no resultado do phpinfo(), será preciso instalar alguns pacotes para poderão ter esse módulo incluído.

Não é nada complicado, só é preciso atenção aos seguintes passos:

Observação: O que será descrito a seguir, também pode ser encontrado neste link: MongoDB PHP Driver.

Será necessário usar o pecl para compilar e instalar o módulo, e para isso é preciso ter instalado os pacotes phpX-dev, phpX-cli e php-pear (o X é a versão raiz do php), o comando para isso no Ubuntu será: sudo apt-get install php5-dev php5-cli php-pear.

O próximo comando (também usando o terminal) será: sudo pecl install mongo.

Depois de terminada a execução deste comando, ele exibirá um lembrete dizendo que precisa adicionar a seguinte linha no php.ini: extension=mongo.so.

Linha a ser inserida
Figura 1: Linha a ser inserida

O php.ini será encontrado em /etc/php5/apache2, mas como pode variar de acordo com a distribuição, basta usar o comando locate: locate php.ini.

Ele vai retornar algumas pastas contendo esse arquivo, mas é preciso alterar somente o que fica na pasta /etc.

Esta linha pode ser adicionada em qualquer parte do php.ini, aqui colocamos na seção Dynamic Extensions, pois havia ali um exemplo de colocar o msql para ser carregado. O bom é que logo a seguir vem a seção dos módulos onde são carregados os vários bancos de dados suportados pelo PHP, então fica fácil lembrar onde colocamos, o que ajuda na organização.

Linha adicionada
Figura 2: Linha adicionada.

Depois de adicionada a linha e salvo o arquivo, será necessário reiniciar o Apache, para as alterações serem efetivadas, para isso, será necessário usar o comando: sudo /etc/init.d/apache2 restart.

Executando o phpinfo() novamente, se tudo ocorreu corretamente, a tela algo semelhante a isso:

Executando phpinfo()
Figura 3: Executando phpinfo().

Agora é possível dar início aos trabalhos com o Mongo e PHP.

Um outro ponto a ser notado aqui, é que, se for trabalhar com um servidor de testes, rodando localmente o MongoDB, é preferível criar um usuário e senha para realizar as operações no banco de dados, (não é necessário, mas é recomendado ter sempre o hábito de colocar a conexão com nome de usuário e senha) basta fazer o procedimento:

Acessar o shell do mongodb no terminal e digitar o comando abaixo:

Listagem 1: Adicionando usuário no MongoDB.

use admin
db.addUser(“Nome_do_usuário”,”senha”)

Se os comandos forem bem sucedidos, a tela será semelhante a seguinte:

Usuário adicionado
Figura 4: Usuário adicionado.

Voltando agora ao PHP, desenvolveremos um exemplo simples e bem conhecido de muitos, que consiste em pegar o streaming do Twiter, ou seja, os tweets feitos por aqueles que seguimos.

Existem vários sites e blogs que mostram como fazer isso, desde a criação de um app na área de desenvolvedores do Twitter até como ter esse streaming dos tweets feitos, pesquisa por termos no Twitter, tweets favoritados, seguidores, e uma infinidade de possibilidades que se não estão claramente descritas nesses tutorais, basta juntar uma breve lida na documentação do Twitter já esclarecerá se é ou não possível realizar o que se deseja.

Por essa razão, este artigo não cobrirá como proceder para criar seu app ou coisas do tipo.

Primeiro é preciso alimentar a base de dados com aquilo que o projeto inicialmente solicitou:

Nome de quem postou o tweet, o tweet propriamente dito, e o link (se houver) formatado.

Listagem 2: Definições para verificação dos tweets.

error_reporting(E_ALL|E_STRICT);
ini_set('display_errors', 1);

echo "<meta http-equiv='refresh' content='1200'/>";
echo "<meta content='text/html; charset=utf-8' http-equiv='Content-Type'/>";

session_start();
include './twitteroauth/twitteroauth.php';

$consumer_key = 'minha_chave';  
    $consumer_secret = 'minha_chave_secreta';  
    $oauth_token = 'meu_token';  
    $oauth_token_secret = 'meu_token_secreto';  
      
    $connection = new TwitterOAuth(  
        $consumer_key,  
        $consumer_secret,  
        $oauth_token,  
        $oauth_token_secret  
    );  
if(!isset($_SESSION['maxid'])):
$result = $connection->get(
    'statuses/home_timeline.json?count=50',
    array()
);
else:
$result = $connection->get(
    'statuses/home_timeline.json?since_id='.$_SESSION['maxid'],
    array()
);
endif;

for($i=1; $i<=1;$i++){
  if(!$result[0]->id ==''):
  $_SESSION['maxid'] = $result[0]->id;
  endif;
}

$mongo = new Mongo( 'mongodb://vini:12345@localhost:27017' );

foreach($result as $node){
  $expreg = "/http:\/\/(www\.|.*?\/)?([a-zA-Z0-9]+|_|-)+(\.(([0-9a-zA-Z]|-|_|\/|\?|=|&|%)+))+/i";
  preg_match_all($expreg, $node->text, $match);
  if((!$match[0])==""):
  foreach ($match[0] as $link)
  {
    $texto = str_replace($link, "<a href=\"" . $link . "\" target=\"_blank\">".$link."</a>", $node->text);
    $mongo->selectDB( 'twitterdb' )->selectCollection( 'tweets' )->insert( array( 'nome' => utf8_decode($node->user->name) , 'tweet' => $texto ) );
      
  }
  else:
  $mongo->selectDB( 'twitterdb' )->selectCollection( 'tweets' )->insert( array( 'nome' => utf8_decode($node->user->name) , 'tweet' => $node->text ) );
  endif;

Parte desse código foi baseado num dos vários exemplos de como criar um aplicativo para Twitter.

O código acima apesar de bem básico, atende o objetivo que é saber como conectar no MongoDB e também como inserir registros (documentos) na tabela (coleção).

Listagem 3: Conectando ao MongoDB.
$mongo = new Mongo( 'mongodb://vini:12345@localhost:27017' );

Aqui é informado que está sendo iniciada uma conexão ao MongoDB, é indicado o nome do usuário e senha, bem como o endereço do servidor e qual a sua porta.

Listagem 4: Selecionando o banco de dados.
 $mongo->selectDB( 'twitterdb' )->selectCollection( 'tweets' )->insert( array( 'nome' => utf8_decode($node->user->name) , 'tweet' => $node->text ) );

Já aqui é informado para selecionar o banco de dados, qual coleção será usada e qual será a operação, bem como seus parâmetros.

Simples, não é mesmo?

E um detalhe: se o banco de dados e a coleção não existirem, ele cria automaticamente, então é preciso prestar muita atenção sempre que for trabalhar com uma base de dados já existente, pois qualquer deslize e não terá o resultado desejado ao manipular as coleções no MongoDB.

Depois de inserir alguns registros, o próximo passo é saber quantos registros foram inseridos até o momento com o código abaixo:

Listagem 5: Verificando os registros inseridos.

$mongo = new Mongo('mongodb://vini:12345@localhost:27017');
$db = $mongo->twitterdb;
$col = $db->tweets;
$total = $col->count(true);
echo ($total) ." registros encontrados.<p>";
$mongo->close();

E para ver os registros dessa coleção?

Igualmente simples:

Listagem 6: Listando os registros inseridos.

echo "<meta content='text/html; charset=utf-8' http-equiv='Content-Type'/>";
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors', 1);
$mongo = new Mongo('mongodb://vini:12345@localhost:27017');
$db = $mongo->twitterdb;
$col = $db->tweets;
$rows = $col->find();
foreach ($rows as $obj) {
  echo $obj['_id'] ."<br/>";
  echo "<b>Nome:</b> " . $obj['nome'] . "<br/>";
  echo "<b>Tweet:</b> " . $obj['tweet'] . "<br/>";
  echo "<br/>";
}
$mongo->close();

Ao testar o código, é retornada uma listagem dos registros de forma ascendente, ou seja, do mais antigo para o mais novo. Se quiser uma listagem descendente, basta modificar a linha:

Listagem 7: Listando os registros de forma descendente.
$rows = $col->find()->sort(array('_id' => -1));

Na linha acima informa-se ao banco de dados que desejamos o resultado da busca ordenado pelo id (criado automaticamente pelo MongoDB) de forma descendente ( -1 ).

Como visto pouco acima, o padrão é ascendente, mas para declarar explicitamente que deseja esse tipo de ordenação, basta colocar o 1 (positivo) como parâmetro no sort.

Todo sistema, por mais básico que seja, oferece uma pesquisa ao usuário, onde é possível procurar pelo termo desejado. E como seria feito isso no MongoDB?

Vejamos:

Listagem 8: Procurando por um registro.
$rows = $col->find(array('nome' => 'Ubuntu Dicas'));

Note que dessa forma o retorno será exatamente o termo procurado, mas e se só informar um dos termos nessa busca, será que esse comando daria certo?

Listagem 9: Pesquisando por um termo parcial sem sucesso.
$rows = $col->find(array('nome' => 'Ubuntu'));

Nada é retornado, pois estamos procurando pelo termo exato.

Como fazer se houver parte do termo procurado ele ser exibido? A solução é um pouco mais complexa, como mostrado abaixo:

Listagem 10: Pesquisa por parte de um campo.
$rows = $col->find(array('nome' => array ('$all' => array(new MongoRegex('/Ubuntu/')))));

Apesar de mais extensa, ela é relativamente simples, pois faz com que se procure no campo nome todos os registros que possuam o termo “Ubuntu”.

O único porém nessa abordagem, se trata da limitação do comando find que é case-sensitive.

Existe a possibilidade de usar o recurso do text search, que é case-insensitive para realizar a busca por determinado termo, porém, ele não é habilitado por padrão, e na documentação sobre os parâmetros) há um alerta sobre os “significantes requerimentos de armazenamento e custos de performance”.

Dessa forma, é um recurso que antes de habilita-lo, é preciso pesar os prós e contras dele na base de dados.

Outra das operações rotineiras de um sistema é a atualização de registros. No dia a dia é preciso alterar um ou outro registro, seja para inserir alguma informação nova, seja para corrigir eventuais erros de digitação. No MongoDB também é oferecida essa possibilidade, conforme mostrado abaixo:

Registro antes de ser alterado
Figura 5: Registro antes de ser alterado.
Listagem 11: Alterando um registro.

$dbid = '515f0c2cd60652eb0f000012';
$iddb = new MongoId($dbid);
$col->update(array('_id'=> $iddb), array('$set' => array("nome"=>"Tech Crunch")));
Registro alterado
Figura 6: Registro alterado.

Note que foi informado o id do documento no qual será feita a alteração. Transforma-se ele num objeto do tipo MongoID e em seguida, é usado esse objeto como parâmetro para o comando update.

Outra possibilidade é acrescentar um parâmetro a mais e alterar todos os documentos que sejam compatíveis com o termo informado:

Registros antes da alteração
Figura 7: Registros antes da alteração.
Listagem 12: Alterando múltiplos registros.
$col->update(array("nome" => "Ubuntu Dicas"), array('$set' => array("nome" => "Ubuntu DicasBR")), array("multiple" => true));
Registros após alteração
Figura 8: Registros após alteração.

E por último, mas não menos importante, a operação de apagar alguns documentos.

Aproveitando a última imagem, removeu-se o primeiro documento pelo seu id:

Listagem 13: Removendo um registro pelo id.

$dbid = '515efdebd606522504000027';
$col->remove(array('_id' => new MongoId($dbid)));
Registro excluído
Figura 9: Registro excluído.

Também é possível remover todos os documentos que são compatíveis com determinado termo, como mostrado abaixo:

Listagem 14: Removendo vários registros.
$col->remove(array("nome" => "Ubuntu DicasBR"));

Com isso terminamos nosso CRUD básico com o MongoDB. Como vimos, é bastante simples utilizar esse banco de dados noSQL com PHP.