segunda-feira, 12 de janeiro de 2015

A melhor maneira de trabalhar com o MongoDB e o Python é utilizar a biblioteca PyMongo. No post Conexão do R com bancos de dados - MongoDB mostramos como conectar o R ao MongoDB. Hoje, faremos o mesmo com o Python.


O PyMongo pode ser facilmente instalado via easy_install, via Python Package Index (http://pypi.python.org/pypi/setuptools):

 easy_install pymongo  
 Searching for pymongo  
 Reading http://pypi.python.org/simple/pymongo/  
 Reading http://github.com/mongodb/mongo-python-driver  
 Best match: pymongo 2.7  
 Downloading ...  
 Processing pymongo-2.7-py2.6-macosx-10.6-x86_64.egg  
 Moving ...  
 Adding pymongo 2.7 to easy-install.pth file  
 Installed ...  
 Processing dependencies for pymongo  
 Finished processing dependencies for pymongo  

Após a instalação, importamos o módulo e valos utilizar a classe Connection para fazer a conexão com o MongoDB. Vamos atribuir à variável db a conexão feita com o banco testePyMongo.

 from pymongo import Connection  
 db = Connection().testePyMongo  

Existe uma diferença de sintaxe do PyMongo em relação ao shell do MongoDB. O primeiro utiliza o padrão underscore_naming, enquanto o shell utilizada a padronização camelCase. Ou seja, no shell faríamos db.collection.findOne(), enquanto no PyMongo o mesmo código teria a sintaxe db.collection.find_One(). Como exemplo, insira o documento {"a" : [1, 2, 3]} em nossa collection e execute o find_One.

 db.teste.insert({"a": [1, 2, 3]})  
 db.teste.find_one()  

Para nossa aplicação, vamos trabalhar com os dados fictícios de visitas à páginas de um site. Vamos inserir os seguintes documentos em nossa base, em uma collection nomeada de hourly.

 { "hour" : "Tue Jun 15 2010 9:00:00 GMT-0400 (EDT)", "url" : "/foo", "views" : 5 }  
 { "hour" : "Tue Jun 15 2010 9:00:00 GMT-0400 (EDT)", "url" : "/bar", "views" : 5 }  
 { "hour" : "Tue Jun 15 2010 10:00:00 GMT-0400 (EDT)", "url" : "/", "views" : 12 }  
 { "hour" : "Tue Jun 15 2010 10:00:00 GMT-0400 (EDT)", "url" : "/bar", "views" : 3 }  
 { "hour" : "Tue Jun 15 2010 10:00:00 GMT-0400 (EDT)", "url" : "/foo", "views" : 10 }  
 { "hour" : "Tue Jun 15 2010 11:00:00 GMT-0400 (EDT)", "url" : "/foo", "views" : 21 }  
 { "hour" : "Tue Jun 15 2010 11:00:00 GMT-0400 (EDT)", "url" : "/", "views" : 3 }  

Temos a informação do dia e hora e da quantidade de visitas em cada página. Suponha que os dados são coletados a cada hora. Para as visitas totais ao site temos uma collection separada, chamada de  hourly_totals com as informações abaixo.

 { "hour" : "Tue Jun 15 2010 9:00:00 GMT-0400 (EDT)", "views" : 10 }  
 { "hour" : "Tue Jun 15 2010 10:00:00 GMT-0400 (EDT)", "views" : 25 }  
 { "hour" : "Tue Jun 15 2010 11:00:00 GMT-0400 (EDT)", "views" : 24 }  

Vamos agora criar a função track que, toda vez que o site receber uma visita, a hora será armazena e o número de views será incrementado em uma unidade. Nossa collection aqui é a hourly_totals.

 from datetime import datetime  
 def track(url):  
    hour = datetime.utcnow().replace(minute=0, second=0, microsecond=0)  
    db.hourly.update({"hour": hour, "url": url},  
      {"$inc": {"views": 1}}, upsert=True)  
    db.hourly_totals.update({"hour": hour},  
         {"$inc": {"views": 1}}, upsert=True)  

O trecho de código datetime.utcnow().replace(minute=0, second=0, microsecond=0) caputra as informações de data e hora no momento em que é executado e "elimina" as informações de minutos, segundos e micro segundos, resultado apenas no formato desejado para a collection.

O próximo passo é criar um índice para nossas consultas nas duas collections. Uma descrição mais detalhada pode ser encontrada em nosso post Índices no MongoDB e o Comando explain() - CRUD Operations - Parte 2

 from pymongo import ASCENDING  
 db.hourly.create_index([("url", ASCENDING), ("hour", ASCENDING)], unique=True)  
 db.hourly_totals.create_index("hour", unique=True)  

A primeira etapa, de inserir informações no banco de dados está concluída. A próxima é criar o trecho de código que fazer uma consulta no banco e calcula a quantidade de visitas em cada uma das últimas 10 horas.

 from pymongo import DESCENDING  
 for rollup in db.hourly_totals.find().sort("hour", DESCENDING).limit(10):  
    pretty_date = rollup["hour"].strftime("%Y/%m/%d %H")  
    print "%s - %d" % (pretty_date, rollup["views"])  

A variável pretty_date recebe a data formatada para ser exibida de um modo mais fácil de se entender. Repare também que fazemos uma ordenação na informação das horas (hour), alinhada com o índice que foi criado anteriormente.

Um abraço e até o próximo post!

Adaptado de: “MongoDB: The Definitive Guide by Kristina Chodorow and Michael Dirolf (O’Reilly).  Copyright 2010 Kristina Chodorow and Michael Dirolf, 978-1-449-38156-1.”

0 comentários:

Postar um comentário