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


