24
Python e MongoDB
Filed Under (Desenvolvimento) by Samir on 24-05-2010
Tagged Under : mongodb, python
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!
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












Como vai, Samir? Tudo certo?
O mais incrível é existirem projetos que usam raw SQL (misturado ao código). Onde nem mesmo se deram ao trabalho (ou mesmo sabem da existência) de testar ou desenvolver algo perto de um ORM.
Parabéns pelas abordagens do site. E, igualmente, pelo formato utilizado. Realmente, é bastante agradável na leitura.
Com certeza, SQL é meio… meio… meio mesmo. Acho que você entendeu.
É… Pois bem. Agora, algumas outras questões…
Deu fim ao uso de django? Algum ou alguns motivos em especial?
Em suas andanças pelo mongo world (?!) topou com ming ou mongokit?
E o cyclone não seria um network toolkit?
Adiantando o passo, já pensou em nginx (proxy reverso) com tornado (requesthandler assincrono) e django?
Agora, realmente o trabalho no txmongo e mesmo os demais, do Alexandre Fiori são invejáveis.
Mas é isso, então. Só trocando uma idéia mesmo.
Aguardando o próximo post, e alguma resposta.
[]s
Até mais.
Opa, obrigado pelo feedback. Bom como expliquei no post, eu deixei o Django de lado, pois sem o ORM dele perde-se muito dos seus recursos, dai acabei encontrando o Cyclone a melhor opção.
O ming e mongokit não testei para lhe falar a verdade, posso dar uma olhada depois. Por enquanto o txmongo está perfeito no meu caso.
E sobre o Nginx eu uso sim essa arquitetura, a única diferença é que removi o Apache no lugar do Cyclone pois o mesmo já possui um webserver embutido. Eu estou preparando um post/tutorial sobre esse assunto, aguarde