Python MongoDB Driver (pymongo), con ejemplos (Video)


El proyecto de este post lo puedes descargar pulsando AQUI.

En esta entrada vamos hacer un sencillo ejemplo de como utilizar el driver (o librerias) de Python (pymongo) para trabajar con MongoDB, en el que veremos como se hace la conexión al servidor y un sencillo CRUD. El objetivo de este tutorial es el de proporcionar un ejemplo que sirva como base para todos aquellos que empeceis a trabajar con MongoDB utilizando Python y podais profundizar más, haciendo consultas más complejas, etc. Como podreis ver en este tutorial las consulas o queries (o mejor dicho, las funciones que permiten hacer las consultas) que se realizan por código Python en Mongo tienen una sintaxis muy cercana a la utilizada al hacer las consultas por la shell, a diferencia de lo que pasa con otros drivers como el de Java; por tanto puede resultar sencillo trabajar con Python y MongoDB.

Aunque el objetivo de este tutorial no es el de enseñar los conceptos, queries, características de MongoDB, etc. si que empezaremos mostrando una "tabla de equivalencia" entre los conceptos de las Bases de Datos Relacionales y MongoDB para que podáis serguir el tutorial.

MongoVSsql

Lo primero que tenemos que hacer antes de empezar a "picar código" es instalarnos las librerias de Python para MongoDB. Para ello debemos de hacer un "pip install" para descargarnos e instalar los paquetes de de MongoDB. No es objetivo de este tutorial explicar como instalar la paqueteria proveniente de "Pypi", ya que entendemos que al seguir este tutorial se tienen unos conocimientos mínimo de Python, por tanto intalamos las librerias de MongoDB para Python de la siguiente manera abriendo un terminal:

$ pip install pymongo

En principio sino indicamos la versión a la hora de instalar las librerias, Pypi nos instalará la última versión estable de "pymongo"; pero si quereis, podeis indicarle la versión de la libreria (en este ejemplo la 2.8) de la siguiente forma:

$ pip install pymongo==2.8

En este tutorial vamos ha guardar en una colección de la base de datos que llamaremos "Futbolistas", información relacionada sobre futbolistas. Para ello lo primero que vamos ha hacer para estructurar bien el proyecto es definir la clase Futbolista que tendrá la siguiente forma:

def __init__(self, nombre, apellidos, edad, demarcacion, internacional):
    self.nombre = nombre
    self.apellidos = apellidos
    self.edad = edad
    self.demarcacion = demarcacion
    self.internacional = internacional

Para hacer un poco más completo este ejemplo, vamos a definir varios tipos de datos para ver como guardarlos y manejarlos. En este ejemplo los atributos 'nombre' y 'apellidos' serán de tipo "String", el atributo 'edad' de tipo "Integer", 'demarcacion' será un array e 'internacional' será un atributo de tipo "Boolean". Hacemos esta aclaración de tipos de datos ya que Python es un lenguaje de tipado dinámico y por tanto no hay que declarar el tipo de dato de cada atributo, aunque en este ejemplo lo vamos a mencionar para saber con que tipos de datos vamos a trabajar.

En nuestro script principal (Main.py) vamos a declarar una lista de objetos de la clase Futbolista, que serán con los que haremos el CRUD en el ejemplo de este tutorial. La lista con los futbolistas es la siguiente:

# Creo una lista de objetos futbolista a insertar en la BD
futbolistas = [
    Futbolista('Iker','Casillas',33,['Portero'],True),
    Futbolista('Carles','Puyol',36,['Central', 'Lateral'],True),
    Futbolista('Sergio','Ramos',28,['Lateral','Central'],True),
    Futbolista('Andrés','Iniesta',30,['Centrocampista','Delantero'],True),
    Futbolista('Fernando','Torres',30,['Delantero'],True),
    Futbolista('Leo','Baptistao',22,['Delantero'],False)
]

Una vez definido lo que queremos guardar en nuestra base de datos, vamos a ver como nos conectamos a la misma para poder hacer las queries que queramos. En primer lugar hay que hacer una conexión al servidor donde esta alojado nuestro "MongoDB server":

# PASO 1: Conexión al Server de MongoDB Pasandole el host y el puerto
mongoClient = MongoClient('localhost',27017)

En este ejemplo el "server" será nuestra propia máquina "localhost" (Muy importante: debeis de tener instalado MongoDB en vuestra máquina "Instalar mongoDB en Mac OS X") y nos conectaremos por el puerto 27017 que es el puerto que utiliza MongoDB si hacemos la instalación por defecto. Si vuestro MongoDB esta alojado en otra máquina, debéis de poner bien la URL o la IP de la misma, seguido del puerto.

Después de habernos conectado al Server, debemos de conectarnos a la Base de Datos que hemos llamado "Futbol" y después expecificaremos la Colección (en SQL seria la tabla) con la que vamos a trabajar que se llamará "Futbolistas":

# PASO 2: Conexión a la base de datos
db = mongoClient.Futbol

# PASO 3: Obtenemos una coleccion para trabajar con ella
collection = db.Futbolistas

Llegados a este punto ya tenemos hecha nuestra conexión a la base de datos y tenemos una referencia a la colección "Futbolistas" (con la variable 'collection') con la que haremos el CRUD.

Antes de pasar a hacer el CRUD hay que decir que la paqueteria de MongoDB para python "no entiende" de clases u objetos Python y por tanto no podemos pasarle objetos Python a las funciones que nos permitirán hacer queries. Para ello Python tiene un tipo de dato que se adapta muy bien a MongoDB que son los "diccionarios" que son estructuras de datos con pares "<clave, valor>"; por tanto, a la hora de trabajar con Python y MongoDB vamos a utilizar estas estructuras de datos, ya que MongoDB guarda documentos (en formato JSON) con la estructura "<clave,valor>". Para trabajar de una forma más limpia y organizada, he creado una función en la clase "Futbolista" (toDBCollection) que pasa un objeto de la clase Futbolista a un Diccionario con los pares "<clave,valor>" que guradaremos en MongoDB, que es la siguiente:

def toDBCollection (self):
        return {
            "nombre":self.nombre,
            "apellidos":self.apellidos,
            "edad": self.edad,
            "demarcacion":self.demarcacion,
            "internacional":self.internacional
        }

Dado que ya tenemos todo lo necesario para hacer el CRUD, vamos a ello:

CREATE:

Vamos a insertar en la coleccion Futbolistas cada uno de los objetos futbolista que nos hemos creado y que tenemos en la lista 'futbolistas'. Para ello vamos a utilizar la función "insert" que la aplicaremos a la colección Futbolistas. Haciendo un "foreach" de la lista futbolistas, nos inserta en la Base de Datos, los datos de los futbolistas:

# PASO 4.1: "CREATE" -> Metemos los objetos futbolista (o documentos en Mongo) en la coleccion Futbolista
for futbolista in futbolistas:
    collection.insert(futbolista.toDBCollection())

Como vemos al llamar a la función "toDBCollection" trasformamos el objeto a un "diccionario" que "entienden" las librerias de MongoDB. Como resultado de la inserción de los futbolista tenemos lo siguiente en la colección Futbolistas:

{
	"_id" : ObjectId("55084a2d0364d3a7933fe621"),
	"nombre" : "Iker",
	"apellidos" : "Casillas",
	"edad" : 33,
	"demarcacion" : [
		"Portero"
	],
	"internacional" : true
}
{
	"_id" : ObjectId("55084a2d0364d3a7933fe622"),
	"nombre" : "Carles",
	"apellidos" : "Puyol",
	"edad" : 36,
	"demarcacion" : [
		"Central",
		"Lateral"
	],
	"internacional" : true
}
......
......

READ:

Como primera consulta, vamos a leer todos los documentos de la colección Futbolistas. Para hacer las lecturas (o consultas find), Mongo nos devuelve una lista (o un cursor) con objetos con pares "<clave,valor>"; por tanto, hecha la consulta, debemos de recorrer (en este caso con un "foreach") cada uno de los objetos y acceder a su clave para poder imprimirlos por pantalla;

# PASO 4.2.1: "READ" -> Leemos todos los documentos de la base de datos
cursor = collection.find()
for fut in cursor:
    print "%s - %s - %i - %s - %r" \
          %(fut['nombre'], fut['apellidos'], fut['edad'], fut['demarcacion'], fut['internacional'])

Como resultado tenemos lo siguiente:

Iker - Casillas - 33 - [u'Portero'] - True
Carles - Puyol - 36 - [u'Central', u'Lateral'] - True
Sergio - Ramos - 28 - [u'Lateral', u'Central'] - True
Andrés - Iniesta - 30 - [u'Centrocampista', u'Delantero'] - True
Fernando - Torres - 30 - [u'Delantero'] - True
Leo - Baptistao - 22 - [u'Delantero'] - False

Ahora vamos ha hacer una consulta en la que nos muestre los futbolistas que pueden jugar o juegan en la demarcación de Delantero. En este caso ya es una query con una condición, por tanto vamos a ver como se hace:

# PASO 4.2.2: "READ" -> Hacemos una Query con condiciones y lo pasamos a un objeto Futbolista
print "\n\n*** Buqueda de los futbolistas que sean delanteros ***"
cursor = collection.find({"demarcacion":{"$in":["Delantero"]}})
for fut in cursor:
    print "%s - %s - %i - %s - %r" \
          %(fut['nombre'], fut['apellidos'], fut['edad'], fut['demarcacion'], fut['internacional'])

Como resultado tenemos los jugadores que juegan (o pueden jugar) como delanteros

Andrés - Iniesta - 30 - [u'Centrocampista', u'Delantero'] - True
Fernando - Torres - 30 - [u'Delantero'] - True
Leo - Baptistao - 22 - [u'Delantero'] - False

UPDATE:

Pasamos ahora ha hacer una actualización o modificación de los documentos. Para este ejemplo, vamos a sumar '100' a todos aquellos futbolistas cuya edad sea mayor de 30. Las consultas de actualización requieren 4 parámetros; uno que es la búsqueda de los documentos a actualizar o otro que es el campo que se actualiza, y los dos últimos son el "Upsert" (sino existe lo insertas y si existe lo actualizas) y el "multi" (para que se aplique al primer documento encontrado o a todos). Veamos el ejemplo:

# PASO 4.3: "UPDATE" -> Actualizamos la edad de los jugadores.
collection.update({"edad":{"$gt":30}},{"$inc":{"edad":100}}, upsert = False, multi = True)

Con la ejecución de este código se modifican dos documentos que son los siguientes:

{
	"_id" : ObjectId("55084a2d0364d3a7933fe621"),
	"nombre" : "Iker",
	"apellidos" : "Casillas",
	"edad" : 133,
	"demarcacion" : [
		"Portero"
	],
	"internacional" : true
}
{
	"_id" : ObjectId("55084a2d0364d3a7933fe622"),
	"nombre" : "Carles",
	"apellidos" : "Puyol",
	"edad" : 136,
	"demarcacion" : [
		"Central",
		"Lateral"
	],
	"internacional" : true
}

Como vemos la consulta de actualización que hacemos por código es muy similar a la que hariamos por la shell.

DELETE:

Por último vamos a mostrar como borrar documentos. Para ello se utilizará la función "remove" al que se la pasa como parámetro la búsqueda de los documentos a eliminar. En el ejemplo, vamos a eliminar todos los documentos que tenga como valor 'True' el campo 'internacional':

# PASO 4.4: "DELETE" -> Borramos todos los futbolistas que sean internacionales (internacional = true)
collection.remove({"internacional":True})

Vemos como en primer lugar hacemos la búsqueda de los documentos con "internacional = true" y luego el método 'remove' los elimina, quedando por tanto en la base de datos un único documento con "internacional = false" que es el siguiente:

{
	"_id" : ObjectId("550849e303645b46b491c39e"),
	"nombre" : "Leo",
	"apellidos" : " Baptistao",
	"edad" : 22,
	"demarcacion" : [
		"Delantero"
	],
	"internacional" : false
}

Con todo esto ya hemos visto como utilizar las librerias de Python para MongoDB, conectandonos al Server y haciendo un CRUD muy sencillo que se puede complicar todo lo que querais en función de las queries que tengais que hacer, pero como se ha visto, la sintaxis utilizada para hacer las queries es muy similar (a diferencia de otras librerias como la de Java) a la utilizada al hacer las queries por la shell. 

A continuación copio el código completo del proyecto:

Main.py

# -*- coding: utf-8 -*-
__author__ = 'Ricardo Moya'

from pymongo import MongoClient
from Futbolista import Futbolista

# Creo una lista de objetos futbolista a insertar en la BD
futbolistas = [
    Futbolista('Iker','Casillas',33,['Portero'],True),
    Futbolista('Carles','Puyol',36,['Central', 'Lateral'],True),
    Futbolista('Sergio','Ramos',28,['Lateral','Central'],True),
    Futbolista('Andrés','Iniesta',30,['Centrocampista','Delantero'],True),
    Futbolista('Fernando','Torres',30,['Delantero'],True),
    Futbolista('Leo','Baptistao',22,['Delantero'],False)
]


# PASO 1: Conexión al Server de MongoDB Pasandole el host y el puerto
mongoClient = MongoClient('localhost',27017)


# PASO 2: Conexión a la base de datos
db = mongoClient.Futbol


# PASO 3: Obtenemos una coleccion para trabajar con ella
collection = db.Futbolistas


# PASO 4: CRUD (Create-Read-Update-Delete)

# PASO 4.1: "CREATE" -> Metemos los objetos futbolista (o documentos en Mongo) en la coleccion Futbolista
for futbolista in futbolistas:
    collection.insert(futbolista.toDBCollection())



# PASO 4.2.1: "READ" -> Leemos todos los documentos de la base de datos
cursor = collection.find()
for fut in cursor:
    print "%s - %s - %i - %s - %r" \
          %(fut['nombre'], fut['apellidos'], fut['edad'], fut['demarcacion'], fut['internacional'])

# PASO 4.2.2: "READ" -> Hacemos una Query con condiciones y lo pasamos a un objeto Futbolista
print "\n\n*** Buqueda de los futbolistas que sean delanteros ***"
cursor = collection.find({"demarcacion":{"$in":["Delantero"]}})
for fut in cursor:
    print "%s - %s - %i - %s - %r" \
          %(fut['nombre'], fut['apellidos'], fut['edad'], fut['demarcacion'], fut['internacional'])



# PASO 4.3: "UPDATE" -> Actualizamos la edad de los jugadores.
collection.update({"edad":{"$gt":30}},{"$inc":{"edad":100}}, upsert = False, multi = True)



# PASO 4.4: "DELETE" -> Borramos todos los futbolistas que sean internacionales (internacional = true)
collection.remove({"internacional":True})


# PASO FINAL: Cerrar la conexion
mongoClient.close()

Futbolista.py

# -*- coding: utf-8 -*-
__author__ = 'Ricardo Moya'

class Futbolista:

    def __init__(self, nombre, apellidos, edad, demarcacion, internacional):
        self.nombre = nombre
        self.apellidos = apellidos
        self.edad = edad
        self.demarcacion = demarcacion
        self.internacional = internacional

    def toDBCollection (self):
        return {
            "nombre":self.nombre,
            "apellidos":self.apellidos,
            "edad": self.edad,
            "demarcacion":self.demarcacion,
            "internacional":self.internacional
        }

    def __str__(self):
        return "Nombre: %s - Apellidos: %s - Edad: %i - Demarcación: %s - Internacional: %r" \
               %(self.nombre, self.apellidos, self.edad, self.demarcacion, self.internacional)

Comparte esta entrada en:
Safe Creative #1401310112503
Python MongoDB Driver (pymongo), con ejemplos (Video) por "www.jarroba.com" esta bajo una licencia Creative Commons
Reconocimiento-NoComercial-CompartirIgual 3.0 Unported License.
Creado a partir de la obra en www.jarroba.com

7 thoughts on “Python MongoDB Driver (pymongo), con ejemplos (Video)”

  1. Genial artículo!, Me ha venido de lujo. No obstante todavía sería mejor si supiese como recibir en python esos mismos datos de futbolistas pero enviados desde un formulario HTML, en lugar de crearlos en el propio fichero. Alguna breve explicación o referencia que pueda servirme?. Muchas gracias

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies

ACEPTAR
Aviso de cookies