Con el potente crecimiento de las redes sociales, se ha necesitado dar respuestas rápidas a una cantidad elevada de clientes, con peticiones de enormes colecciones de datos.
Viendo que los tradicionales SGBD Relacionales emplean demasiado tiempo en controlar la consistencia de los datos (relaciones, restricciones), se necesita un mayor rendimiento a la hora de obtener muchos datos en tiempo real. De estas necesidades surgen las bases de datos NoSQL (Not Only SQL).
Se caracterizan por no emplear SQL como lenguaje principal de consulta. Existen diferentes tipos de bbdd NoSql:
MongoDB es un sistema gestor de bases de datos NoSQL de código abierto, orientado a documentos. Utiliza documentos basados en JSON (JavaScript Object Notation) para almacenar informacion en la base de datos.
La principal diferencia con los tradicionales sistemas relacionales, es la flexibilidad a la hora de modificar la estructura de los datos almacenados. Los documentos almacenados en una base de datos (colección) pueden tener diferentes campos.
Como se ha comentado, MongoDB almacena la información y forma el esquema de la base de datos mediante el uso de documentos BSON (Binary JSON). Los ficheros JSON son relaciones clave-valor y tienen el siguiente aspecto:
Estructura Documento BSON
Así, el esquema en MongoDB es totalmente flexible puesto que depende solamente del documento insertado, pudiendo tener cada documento distinta cantidad de campos. De esa forma es mucho más fácil mapear los documentos con objetos en nuestra aplicación, puesto que es fácil adaptarnos a los cambios que estos últimos puedan sufrir.
SGBD Relacional | MongoDB |
---|---|
Base de Datos | Base de Datos |
Tabla | Colección |
Fila o Registro | Documento |
Relación | Sub-documento integrado (Enbedded) o referenciado |
BSON es una representación binaria de documentos tipo JSON. Permite integrar sub-documentos así como el uso de arrays, pero también permite representar tipos de datos a diferencia de JSON.
Estos documentos de texto son ligeros y utilizan una cláve única por cada documento (campo _id). Cada documento está formado por campos únicos (claves) a los que se les da un valor, lo que permite la recuperación de la información de forma muy rápida.
En MongoDB, cada documento almacenado en una colección requiere un identificador único que actúa de forma similar a una clave primaria. Si se omite este campo en un documento insertado en una colección, MongoDB genera automáticamente un valor ObjectId
para el campo _id
.
El tipo de datos ObjectID
de los documentos BSON es un valor de 12 bytes único, fácil y rápido de generar, y está ordenado.
Una vez descargado el servidor MongoDB Server, para ponerlo en marcha tendremos que crear la ruta donde queremos que se almacenen nuestras bases de datos. Y a continuación, lanzar el servidor ejecutando el siguiente comando:
Hay que tener en cuenta que, por defecto, MongoDB escuchará en el puerto 27017:
c:\Users\Fer\> mongod --dbpath=ruta_base_de_datos
fer@zenbook:$ ./mongod --dbpath=ruta_base_de_datos
Si no queremos especificar una ruta propia donde guardar las bases de datos, por defecto en Windows se guardarán en “C:\data\db\”. Debemos crear al menos dicho directorio.
Para ejecutar el servidor de forma fácil, en Windows podemos hacer un acceso directo en el escritorio del programa mongod.exe
, indicándole en las propiedades del accesso directo la ruta de destino con las opciones necesarias. Por ejemplo si mi directorio de bases de datos esta en “C:\users\Fer\mongodb\data\db” indicaré en las propiedades: “C:\Program Files\MongoDB\Server\3.6\bin\mongod.exe” –dbpath C:\users\Fer\mongodb\data\db
MongoDB también incluye su propio cliente GUI para administrar las bases de datos. Se llama MongoDB Compass y se incluye con el paquete de instalación de Mongo DB:
Además, MongoDB también dispone de una consola cliente que podemos lanzar ejecutando el comando mongo
, que intentará conectar directamente con un servidor ubicado en el propio equipo y con el puerto por defecto, el 27017. También podemos especificar esos parámetros desde la línea de comandos al ejecutarlo (junto con usuario y contraseña si fuera necesario también):
c:\Users\Fer\> mongo --host 192.168.100.23 --port 27017 -u usuario -p password
fer@zenbook:$ ./mongo --host 192.168.100.23 --port 27017 -u usuario -p password
Una vez ejecutado entraremos en la consola de MongoDB donde, entre otros, tenemos los siguientes comandos disponibles:
> show dbs biblioteca 0.203GB ejemplo 0.203GB local 0.078GB
> use biblioteca
switched to db biblioteca
> show collections
libros
system.indexes
> db.dropDatabase() { "dropped" : "biblioteca", "ok" : 1 }
> help db.help() help on db methods db.mycoll.help() help on collection methods sh.help() sharding helpers rs.help() replica set helpers help admin administrative help help connect connecting to a db help . . . . . .
Para empezar a trabajar con MongoDB desde Java, primero tendremos que hacernos con el Driver. Los drivers son librerías JAR que se deben añadir a nuestro proyecto. Se pueden descargar desde la sección de drivers Java para MongoDB. Para conectar con MongoDB necesitamos lo siguiente:
mongo-driver.jar
: Driver de Java para conectar con MongoDB. Tiene dos dependencias:bson.jar
: Librerías de documentos BSON que usa MongoDBmongo-driver-core.jar
: Driver de MongoDB para operaciones de bajo nivelEn la sección de descargas también se incluye una librería llamada Uber MongoDB Java Driver que incluye las librerías descritas anteriormente:
mongo-java-driver.jar
: Driver de Java, que contiene sus dependencias.Creamos un objeto MongoClient, que representa un pool de conexiones con el servidor de MongoDB. Con el crearemos una conexión a una base de datos mediante el objeto MongoDatabase:
MongoClient mongoClient = new MongoClient(); //O si quiero abrir conexiones con un servidor remoto MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); //Establecer conexión con una base de datos MongoDatabase db = mongoClient.getDatabase("baseDatos"); //Y si queremos trabajar directamente con una coleccion concreta MongoCollection coleccion = db.getCollection("coleccion");
Si la base de datos o la coleccion no existen, se crearán de forma automática.
Debemos asegurarnos de cerrar los recursos abiertos con el servidor
mongoClient.close()
Hay que tener en cuenta que para poder conectarnos con MongoDB primero tendremos que arrancar el servidor de la forma que se indica un poco más arriba en la sección Puesta en marcha.
MongoDB proporciona varias vías para ejecutar cada una de las operaciones CRUD 1) (Create, Read, Update, Delete) que podemos realizar en todo SGBD.
En java los documentos que utilizamos en estas operaciones pueden estar representados por objetos de la clase org.bson.Document
.
Ejemplo desde línea de comandos
db.libros.insertOne( // colección { // documento titulo: "Secuestrado", descripcion: "Las aventuras de David Balfour", autor: "Robert Louis Stevenson", fecha: "2/5/2002", disponible: "true" } )
Ejemplo desde Java
Document documento = new Document() .append("titulo", libro.getTitulo()) .append("descripcion", libro.getDescripcion()) .append("autor", libro.getAutor()) .append("fecha", libro.getFecha()) .append("disponible", libro.getDisponible())); db.getCollection("libros").insertOne(documento); // Podemos insertar también varios documentos almacenados en una lista List<Document> listaLibros = new ArrayList<Document>(); ... db.getCollection("libros").insertMany(listaLibros); //Vemos cuántos documentos hay en la colección System.out.println(db.getCollection("libros").count());
Ejemplo desde consola
db.usuarios.updateOne( // colección { titulo: { $eq: "Secuestrado"}}, // criterio { $set: {autor: "Robert Louis Stevenson"} // modificación )
Ejemplos desde Java
// Modifica un campo específico de un documento db.getCollection("libros").updateOne(new Document("titulo", "Secuestrado"), new Document("$set", new Document("autor", "Robert Louis Stevenson")); // Reemplaza un documento completo db.getCollection("libros").replaceOne(new Document("_id", libro.getId()), new Document() .append("titulo", libro.getTitulo()) .append("descripcion", libro.getDescripcion()) .append("autor", libro.getAutor()) .append("fecha", libro.getFecha()) .append("disponible", libro.getDisponible()));
Ejemplo desde consola
db.usuarios.deleteOne( // colección { poblacion: "Zaragoza"} // criterio )
Ejemplo desde Java:
//Para borrar un solo documento debemos utilizar un valor para un campo único (_id) db.getCollection("libros").deleteOne(new Document("_id", "345367")); db.getCollection("libros").deleteMany(new Document("autor", "Reverte"));
Ejemplo desde consola
db.usuarios.find( // colección {autor: {$eq: "Robert Louis Stevenson"}}, // criterio {titulo: 1, descripcion: 1}) // proyección
Ejemplo desde Java
El método find()
devuelve una colección FindIterable
, que se puede recorrer con un Iterator
.
//Buscar el primer documento Document libro = db.getCollection("libros").find().first(); //Buscar todos los documentos FindIterable findIterable = db.getCollection("libros").find(); //Buscar un libro concreto: titulo = "Secuestrado" Document documento = new Document("titulo", "Secuestrado"); Document libro = db.getCollection("libros").find(documento).first(); //O también Document libro = db.getCollection("libros").find({titulo: "Secuestrado"}).first(); //Buscar todos los libros de un autor concreto Document documento = new Document("autor", "Robert Louis Stevenson"); FindIterable findIterable = db.getCollection("libros").find(documento); //Recorrer el conjunto de resultados Iterator<Document> iter = findIterable.iterator(); List<Libro> libros = new ArrayList<Libro>(); Libro libro = null; while (iter.hasNext()) { Document documento = iter.next(); libro = new Libro(); libro.setId(documento.getObjectId("_id")); libro.setTitulo(documento.getString("titulo")); libro.setDescripcion(documento.getString("descripcion")); libro.setAutor(documento.getString("autor")); libro.setFecha(documento.getDate("fecha")); libro.setDisponible(documento.getBoolean("disponible", false)); libros.add(libro); }
Podemos establecer distintos criterios de busqueda
En la documentación de mondoDB tenemos un tutorial con más ejemplos de operaciones
Las relaciones en MongoDB se gestionan de forma diferente a los sistemas de bases de datos relaciones. En MongoDB tenemos más flexibilidad ya que, como hemos visto, no hay que definir una estructura fija para los campos de un documento.
En MongoDB existen dos planteamientos a la hora de realizar las relaciones, y se aplicará uno u otro dependiendo de qué relación guarden los distintos documentos:
Para ver los siguientes ejemplos vamos a plantear dos tipos de documentos: empleados, que almacena información sobre los empleados, y departamentos que almacena datos sobre la dirección de los departamentos.
Este patrón se usa cuando necesitamos acceder a los empleados y ver también sus departamentos relacionados. Favorece la consulta de los documentos de empleados, pero no permite acceder directamente a los documentos de sus departamentos relacionados.
En el documento de un empleado, integramos el documento de su departamento:
{ _id: ObjectID("AAAA"), nombre: "Joe", apellidos: "Book Reader" departamento: { calle: "123 Fake Street", ciudad: "Faketon", provincia: "MA", cp: "12345" } }
Cuando cada empleado se relaciona con unos pocos departamentos, podemos usar un array que integre los departamentos relacionados.
{ _id: ObjectID("AAAA"), nombre: "Joe", apellidos: "Book Reader" departamentos: [ { calle: "123 Fake Street", ciudad: "Faketon", provincia: "MA", cp: "12345" }, { calle: "1 Other Street", ciudad: "Boston", provincia: "CA", cp: "56789" } ] }
Consisten en almacenar en un documento un campo con el valor del _id de otro o varios documentos. Se utiliza cuando queremos acceder de forma directa a los empleados, pero tambien directamente a los departamentos con los que se relaciona.
//Documento empleado, guarda las referencias a varios departamentos { _id: ObjectID("AAAA"), nombre: "Joe", apellidos: "Book Reader" departamentos: [ ObjectID("ABCD"), ObjectID("EFGH"), ObjectID("JKLM")] } //Documentos de Departamentos { _id: ObjectId("ABCD") calle: "123 Fake Street", ciudad: "Faketon", provincia: "MA", cp: "12345" } { _id: ObjectId("EFGH") calle: "1 Other Street", ciudad: "Boston", provincia: "CA", cp: "56789" } ...
La ventaja de este planteamiento es que ademas permite una relación N:M, ya que la referencia de un departamento puede estár en el array de diferentes empleados.
Se emplean cuando un empleado se puede relacionar con un volumen muy grande de documentos de departamentos. La capacidad del array (16mb) limita la cantidad de referencias posibles a departamentos.
//Documento empleado { _id: ObjectID("AAAA"), nombre: "Joe", apellidos: "Book Reader" } //Documentos de departamentos, guardan la referencia al empleado { _id: ObjectId("ABCD") calle: "123 Fake Street", ciudad: "Faketon", provincia: "MA", cp: "12345" empleado: ObjectId("AAAA") //Guarda la referencia al empleado } { _id: ObjectId("EFGH") calle: "1 Other Street", ciudad: "Boston", provincia: "CA", cp: "56789" empleado: ObjectId("AAAA") //Guarda la referencia al empleado }
© 2025 Santiago Faci y Fernando Valdeón