Python e MongoDB

Filed Under (Desenvolvimento) by Samir on 24-05-2010

Tagged Under : ,

Parece que agora a nova tendência é mais e mais pessoas começarem a adotar bancos de dados NoSql e o MongoDB vem se destacando cada vez mais pela simplicidade, estabilidade e muito mas muito rápido!

Tem uma apresentação muito boa da PyCon 2010 onde Rick Copeland que trabalha na SourceForge, relata como migraram o portal utilizando Python, TurboGears e MongoDB, veja aqui.

Bom, como eu sempre destetei SQL a vida toda e acho que nunca vou aprender a gostar, comecei a estudar a possibilidade de migrar o MongoDB no sistema que venho trabalhando (segredo de estado!)…afinal minha vontade sempre foi ter algo mais voltado para Orientação Objetos e como eu sempre tive que recorrer a ORM’s da vida…, era sempre aquela duplicação de código interminável, mas enfim, depois de trabalhar por 2 semanas quase 15 horas por dia consegui migrar tudo e pra minha sorte, consegui reduzir drasticamamente o código do projeto. Com base nessa pequena experiência que passei, vou relatar as possibilidades que testei em Python e não foram muitas.

PyMongo:

O PyMongo é o driver oficial desenvolvido pela equipe do MongoDB, achei um pouco confuso no início, porque na verdade não se cria Models e nenhum tipo de Mapeamento de Objeto Relacional. Você simplesmente se conecta no banco, invoca a collection relacionada (ou tabela para melhor entendimento), passa um dicionário de dados em Python e manda salvar.

Exemplo:

import datetime
from pymongo import Connection

connection = Connection()
db = connection.test_database

post = {"author": "Samir", "text": "Python e MongoDB", "tags": ["mongodb", "python", "pymongo"], "date":datetime.datetime.utcnow()}
db.posts.save(post)

Esse modelo pode funcionar muito bem se você quebrar o código em partes, ou seja, um módulo ou classe que gerencia a conexão com banco de dados e se preferir pode-se criar classes para se representar uma Collection como no exemplo, criar uma classe Post, isso pode ser uma boa prática, mas não caia na besteira de mapear a classe com as colunas de uma Collection, você vai duplicar seu código atoa e só complicar as coisas, pois o MongoDB não segue a filosofia do modelo Relacional.

Depois de alguns testes e pesquisando mais opções eu decici não trabalhar com o driver diretamente, a única razão foi porque o PyMongo trabalha de forma síncrona e no meu projeto tudo é assíncrono e vou relatar isso logo abaixo.

MongoEngine

O MongoEngine foi outra opção que testei, ele é uma espécie de ORM que executa sobre o PyMongo, porém é um projeto muito recente e com pouca atividade, não aconselho a usar ainda.

A ideia do MongoEngine é trabalhar exatamente como o ORM do Django, você mapeia uma classe e usa os métodos para consultar e salvar objetos. Até ai tudo bem, mas de novo cai no velho problema, não tem o menor sentido usar ORM com o MongoDB, é claro que para fins de documentação esse pode ser o modelo ideal.

Exemplo:

from mongoengine import *
connect('test_database')

# Models
class User(Document):
    email = StringField(required=True)
    first_name = StringField(max_length=50)
    last_name = StringField(max_length=50)

class Post(Document):
    title = StringField(max_length=120, required=True)
    content = StringField(max_length=255, required=True)
    author = ReferenceField(User)
    tags = ListField(StringField(max_length=30))

# Salvando objetos
john = User(email='jdoe@example.com', first_name='John', last_name='Doe')
john.save()

post = Post(title='Fun with MongoEngine', author=john)
post.content = 'Content here...'
post.tags = ['mongodb', 'mongoengine']
post.save()

# Consultando...
for post in Post.objects:
    print post.title

TxMongo

O TxMongo foi a melhor opção que encontrei, ele também roda sobre o PyMongo, porém toda sua estrutura é baseada no Twisted. A maior vantagem que percebi é por ele ser assíncrono e ter a possibilidade de criar vários pools de conexões ao mesmo tempo. O PyMongo por padrão cria apenas um pool de conexão o que limita bastante a performance da aplicação para múltiplos requests.

O modelo de implementação é praticamente identico ao PyMongo porém como ele é baseado no Twisted, antes precisa enteder como essa biblioteca funciona, confesso que apanhei um monte para aprender, mas vale a pena! :-D

Exemplo:

import time
import txmongo
from twisted.internet import defer, reactor

@defer.inlineCallbacks
def example():
    mongo = yield txmongo.MongoConnection()

    foo = mongo.foo # `foo` database
    test = foo.test # `test` collection

    # insert some data
    for x in xrange(10000):
        result = yield test.insert({"something":x*time.time()}, safe=True)
        print result

if __name__ == '__main__':
    example().addCallback(lambda ign: reactor.stop())
    reactor.run()

Conclusão:

Bom depois de testar essas possibilidades, o projeto vem sendo desenvolvido com ExtJS para o tudo o que imaginar no FrontEnd e no BackEnd substitui o Django pelo Cyclone que é um mini framework web assíncrono também baseado no Twisted que se integra perfeitamente com o TxMongo. No próximo post, pretendo exemplificar como integrar essas bibliotecas. Críticas ou sugestões serão bem vindas ;)

ads
ads
ads
ads