Jam Blog

¡Respaldo de cosas que podria necesitar luego!

Mongoengine un ODM para conectar a MongoDB desde Python

14 January 2011

MongoEngine es un ODM (Object Document Mapper) que nos permite mapear la estructura de nuestra base de datos a objetos en nuestras aplicaciones Python que se conectan a instancias MongoDB, esto con el fin de poder usar la informacion en nuestra base de datos somo si se tratasen de un objeto. Esto nos ofrece la ventaja de que podemos escribir de una manera mas comoda nuestra aplicacion, definir un esquema para la base de datos y mejorar nuestro codigo, entre otras ventajas mas.

Para instar MongoEngine en Linux tan solo debemos escribir en la terminal:

sudo easy_install mongoengine

Nota: debido a que MongoEngine usa el driver PyMongo para conectar nuestras aplicaciones Python a bases de datos NoSQL MongoDB, es capaz de detectar si tenemos o no instalado el driver PyMongo, por lo que si no lo tenemos instalado MongoEngine lo instalara automaticamente. De todos modos puedes instalar PyMongo de forma separada tecleando:

sudo easy_install pymongo

Si leyeron mi articulo anterior sobre Ejemplos de Consultas Map/Reduce en MongoDB de seguro habran leido que al final del articulo mencionaba que en especifico esa consulta map/reduce podriamos mejorarla y hacerlas de una forma mas sencilla y sin funciones JavaScript si usaramos un ODM, pues bien MongoEngine es uno de los ODM con los que podemos mejorar el codigo de la aplicacion RegistroDeTransferencias.

Usando el ODM MongoEngine nuestra aplicacion quedaria similar a esto:

#! /usr/bin/env python
from mongoengine import *
from datetime import *
from time import *

class Rsubida(Document):
 subida = FloatField()
 fecha_agregado = StringField()
 hora_agregado = StringField()

class Rbajada(Document):
 bajada = FloatField()
 fecha_agregado = StringField()
 hora_agregado = StringField()

print "Conectando a la Base de datos en la instancia Local"
#Conectando a la instancia MongoDB local en la base de datos "bdregistrotransgerenciamdb"
connect("bdregistrotransgerenciamdb")

la_subida = float(raw_input('Introdusca la cantidad de datos Enviados: '))
la_bajada = float(raw_input('Introdusca la cantidad de datos Recibidos: '))

fecha = date.today()
fechaagregado = fecha.strftime("%d-%m-%y")
horaagregado = strftime("%I:%M %p")

print "Los datos ingresados son:"
print "Subida: " + str(la_subida)
print "Bajada: " + str(la_bajada)
print "Fecha Agregado " + fechaagregado
print "Hora Agregado " + horaagregado

respuesta = raw_input("Estos datos son correctos? introdusca solo (s/n): ")

if respuesta == "s":
 regsubida = Rsubida(subida = la_subida, fecha_agregado = fechaagregado, hora_agregado = horaagregado)
 regbajada = Rbajada(bajada = la_bajada, fecha_agregado = fechaagregado, hora_agregado = horaagregado)

 regsubida.save()
 regbajada.save()
 print "Registros de Subida y Bajada ALMACENADOS con Exito!"

else:
 print "Cancelado!!!"

#Algunas consultas
respuesta = raw_input("Deseas ver algunas consultas? introdusca solo (s/n): ")

if respuesta == "s":
 #Mostrando todos los registros de bajada en la coleccion
 for rbajada in Rbajada.objects:
 print "Bajada: " + str(rbajada.bajada)

 #Sumatoria de todos los registros de bajada :)
 print "Total datos Bajada: " + str(Rbajada.objects.sum("bajada")) + " MB"
 print "Total datos Subida: " + str(Rsubida.objects.sum("subida")) + " MB"
 tbajada = Rbajada.objects.sum("bajada")
 tsubida = Rsubida.objects.sum("subida")
 total = tbajada + tsubida
 print "Total Consumido: " + str(total) + " MB"

else:
 print "Cancelado!"

Como podemos ver en las primeras lineas del codigo, creamos dos clases llamadas Rsubida y Rbajada, estas clases contienen lo que es la estructura y tipo de datos de lo que contendran nuestros documentos. De esta forma podemos establecer un esquema predeterminado para la informacion que se almacenara en nuestra base de datos. Cabe destacar tambien que por cada clase que se crea, MongoEngine generara una coleccion correspondiente en la base de datos, por lo que en en este ejemplo nuestra base de datos contendra dos colecciones rsubida que contendra los registros de subida y rbajada que contendra los registros de bajada.

Consultas: Aqui esta la parte que mas nos interesa, si nos fijamos en todo el codigo, no vemos por ningun lado las funciones JavaScript Map/Reduce, esto es porque simplemente no las necesitamos para realizar especificamente las consultas que ya teniamos:

#Mostrando todos los registros de bajada en la coleccion
for rbajada in Rbajada.objects:
  print "Bajada: " + str(rbajada.bajada)

el ejemplo de salida de esta seccion del codigo seria algo como esto:

Bajada: 36.3
Bajada: 123.0
Bajada: 66.4

Esta seccion del codigo nos mostrara los registros de bajadas que estan contenido en el campo bajada, notese que en esta ocacion no nos devuelve un documento JSON con los datos solicitados (incluyendo su corchetes y comillas), sino que simplemente nos devuelve el valor en especifico.

La seccion del codigo con la que sustituimos las consultas map/reduce y su codigo en javascript es la siguiente:

print "Total datos Bajada: " + str(Rbajada.objects.sum("bajada")) + " MB"
 print "Total datos Subida: " + str(Rsubida.objects.sum("subida")) + " MB"

lo que nos devolvera algo como:

Total datos Bajada: 225.7 MB
Total datos Subida: 142.3 MB

Coo vez aqui estamos aprovechando una de los beneficios de usar un ODM, y usar el contenido de nuestra base de datos como si de simples objetos se tratasen ya que con simplemente elegir la clase Rbajada y seleccionando su atributo (variable) “bajada” y haciendo uso del metodo sum() podremos realizar la sumatoria de todo los registros de bajada en en la coleccion Rbajada. Todo esto sin usar map/reduce ni funciones javascript :P

Con esto podemos completar la aplicacion y mostrar el total consumido, es decir, la suma de los datos de subida con los datos de bajada.

tbajada = Rbajada.objects.sum("bajada")
tsubida = Rsubida.objects.sum("subida")
total = tbajada + tsubida
print "Total Consumido: " + str(total) + " MB"

los que nos muestra:

Total Consumido: 368.0 MB

Como vemos, un ODM nos puede facilitar mucho la vida y mejorar nuestras aplicaciones, ademas de acortar un poco el codigo ya que si se fijan. hay muchas menos lineas y mas funciones que la version anterior de la aplicacion que no usa MongoEngine.

Esta aplicacion planeo mejorarla cada vez mas mientras continue aprendiendo sobre Python y MongoDB por loq eu e puesto a disposicion su codigo en GitHub para los que quieran descargarlo o solo si les parece util. :)

Saludos y espero les sirva!





  • submit to reddit
comments powered by Disqus

¿Social?