Skip to content

Instantly share code, notes, and snippets.

@fredericorecsky
Created March 16, 2012 18:20
Show Gist options
  • Save fredericorecsky/2051627 to your computer and use it in GitHub Desktop.
Save fredericorecsky/2051627 to your computer and use it in GitHub Desktop.
perl e mongoDB
Perl e MongoDB
Introdução
Há algum tempo atrás começou uma onda de NOSQL e eu a principio só me mantive
observando a distancia. A questão é que como toda coisa nova acaba sendo
sobreutilizada ou utilizada em funções erradas.
No caso existem na internet diversos textos sobre o Mongo, usos e etc. Nesse
artigo vou abordar um uso bem simples mas que por conta das caracteristicas do
mongodb o tornaram quase que uma luva.
Essas caracteristicas são schema free e documented oriented. No caso estou
desenvolvendo um leitor de rss/atom/xml e que eu preciso escrever pequenos
"pontos de dados" e que roda em cluster. Também ele tem diversos crawlers
internos dos quais cada um tem sua configuração.
É possivel fazer utilizando mysql ou postgres ou qualquer outro, mas a
simplicidade de se erguer um servidor mongo sem esquema definido e que
possibilita salvar documentos json direto facilita muito o desenvolvimento.
Especialmente para empresas que tem seus negocios apenas baseado em aplicações
internet que não tem de fato a arquitetura final definida.
Requisitos
Claro que Perl, uma instancia de MongoDB e o modulo do MongoDB do cpan.
* http://www.mongodb.org/
* http://search.cpan.org/~kristina/MongoDB-0.45/lib/MongoDB.pm
Para começar estou assumindo que o programa perl está na mesma maquina em que
o mongo está rodando, mas é trivial configurar para um servidor diferente.
Basicão
<code>
use strict;
use warnings;
use MongoDB;
my $connection = MongoDB::Connection->new( host => 'localhost', port => 27017);
my $database = $connection->get_database('sppm');
my $collection = $database->get_collection('equinocio');
my $data = $collection->find_one({ type => "artigo" });
</code>
Além do header classico, temos a declaração do modulo do MongoDB e as strings de
conexão e de escolha de database e collection. Collection é um nome bonito para
o que seria uma tabela num banco de dados classico.
Note que se o database não existir será autovivificado, assim como a collection.
Se você rodar esse exemplo $data estara vazio por motivos obvios :).
Vamos assumir que esse script roda eventualmente pegando a tabela de artigos da
sppm e avisa se há novos. A Tabela de artigos tem esse schema:
artigo, data, link
Obvio que eu não gostaria de varrer todos os registros toda vez, assim como que
por algum motivo valido eu não quero ou não posso alterar o banco de dados.
Então eu gostaria que esse script, salvasse a data em que ele leu da ultima vez
a tabela para que na proxima continuasse de onde parou.
Então depois de varrer a tabela eu gostaria de salvar somente o ultimo timestamp
em que o script o fez.
<code>
my $timestamp_id = $collection->insert({ last_verified => '1999/12/31 23:59:59' });
</code>
Isso insere o valor "last_verified" na collection equinocio e retorna uma id, no
caso, "4f6367450be985cd5c000000". Note que ao inserir uma nova chave é gerado
um novo id. Esse id é o id do conjunto de chave valor. E voce pode ter duas
chaves valores iguais.
Se executar duas vezes e for ao console do mongo db:
<console>
> db.equinocio.find()
{ "_id" : ObjectId("4f6367450be985cd5c000000"), "last_verified" : "1999/12/31 23:59:59" }
{ "_id" : ObjectId("4f6368b7279b784b6b000000"), "last_verified" : "1999/12/31 23:59:59" }
</console>
Temos duas entradas para "last_verified".
Collections
No nosso caso queremos apenas salvar a data que nós varremos o banco de dados
pela ultima vez. Então vamos apagar as entradas e vamos criar só uma. Quando
o script for executado ele tentara primeiro recuperar last_verified e depois
escrevera o resultado.
A classe que manipula Collections no Mongo é MongoDB::Collection:
http://search.cpan.org/~kristina/MongoDB-0.45/lib/MongoDB/Collection.pm
Vamos apagar todos os last_verified para começar de novo, primeiro vamos
achar todos objetos "last_verified".
<code>
my $data = $collection->find({ last_verified => '1999/12/31 23:59:59' } );
</code>
$data é um objeto MongoDB::Cursor, um iterador para varios items numa lista de
resultados. Como eu executei varias vezes temos uma coleção de timestamps
repetidos...
jeferson@ps80344:~/Reader/bin$ perl mongo.pl
$VAR1 = {
'_id' => bless( {
'value' => '4f6367450be985cd5c000000'
}, 'MongoDB::OID' ),
'last_verified' => '1999/12/31 23:59:59'
};
$VAR1 = {
'_id' => bless( {
'value' => '4f6368b7279b784b6b000000'
}, 'MongoDB::OID' ),
'last_verified' => '1999/12/31 23:59:59'
};
$VAR1 = {
'_id' => bless( {
'value' => '4f636a8cd8947c5c7e000000'
}, 'MongoDB::OID' ),
'last_verified' => '1999/12/31 23:59:59'
};
Vamos apaga-los e manter somente um. A classe Cursor permite que se apague (drop)
todo o collection de uma vez:
$collection->drop;
Mas isso é muito simples, vamos apagar todos menos um. De quebra aprendemos sobre
o OID.
OID
Cada documento armazenado contem um id unico, Object Id, ( vulgo OID ). Ele é
um hash key para cada set de key values e é unico. Para apagar vamos iterar sobre
o resultado ( Cursor ) e apagar todos menos um. Para apagar devemos passar uma
query para o metodo remove. Isso significa que se para apagar sub-sets de dados
semelhantes temos que recolher os ids e apaga-los individualmente.
Então temos:
<code>
my $data = $collection->find();
my @all_copies = $data->all;
pop @all_copies;
for my $object ( @all_copies ){
$collection->remove( { _id => $object->{ _id } } ) ;
}
</code>
Primeiro recuperamos todos os registros com um find() sem parametros. Salvamos
todos os OID num array e removemos um com pop. Esse removido sera salvo. Depois
iteramos os objetos e os removemos.
$object->{ _id } = Mongo::OID dentro do resultado do Cursor.
O cursor retorna o OID mais um hash com os keys values. Não é muito sabio usar
'_id' como chave quando estiver utilizando-o.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment