Bases de Datos NoSQL y Orientadas a Objetos: eXist-db, MongoDB y Neodatis con Ejemplos Prácticos en Java
eXist-db
Es un sistema de base de datos orientado a NoSQL y una base de datos XML nativa, que permite trabajar con XQuery y XSLT. Admite interfaces REST para interactuar con formularios web de tipo AJAX.
La interfaz WebDAV de eXist permite a los usuarios arrastrar y soltar archivos XML directamente en la base de datos eXist.
Instalación
Paso 1: Descargar eXist-db desde la página oficial.
Paso 2: Al hacer doble clic, nos aparecerá la ventana principal de eXist-db para realizar la instalación, que se llevará a cabo en 9 pasos:
Paso 3: Iniciar el servicio con el comando java -jar start.jar. Para detenerlo, desde C:\eXist-db\bin usaremos la siguiente línea de comandos:
$~Shutdown.bat -p admin (contraseña de admin).
Paso 4: Por último, navegamos a la ruta localhost:8080 para empezar a utilizar eXist-DB; nos aparecerá la ventana principal (DashBoard).
Consultar datos
Las consultas se realizan mediante expresiones FLWOR:
FOR: asocia una o más variables a expresiones, creando un conjunto de tuplas en el cual cada tupla vincula una variable dada a uno de los ítems a los cuales está asociada la expresión evaluada.
LET: vincula las variables al resultado de una expresión, agregando estos vínculos a las tuplas generadas por la cláusula FOR.
WHERE: filtra tuplas, quedando solo aquellas que cumplen con la condición.
ORDER BY: ordena las tuplas en el conjunto de tuplas.
RETURN: construye el resultado de la expresión FLWOR para una tupla dada.
Práctica
<persona>
<nombre>Ramón</nombre>
<apellido>López</apellido>
<telefono>600700800</telefono>
<dni>12345678A</dni>
<edad>20</edad>
</persona>Ejemplos
-Nos saca todo el contenido entre etiquetas personalizadas con el nombre:
xquery version "3.1";
for $x in doc("agenda.xml")/agenda/persona
return ($x)-Nos saca los teléfonos de personas con edad menor de 22 años:
for $x in doc("agenda.xml")/agenda/persona
where $x/edad < 22
order by $x/edad
return $x/telefono-Nos saca los nombres de personas entre etiquetas personalizadas, pero todos de una sola vez:
let $x := doc("agenda.xml")/agenda/persona/nombre
return ($x)-Saca todos los teléfonos de todas las personas:
for $x in doc("agenda.xml")/agenda/persona/telefono
order by $x
return data($x)Ejemplo: crear base de datos desde XML (Java)
// Ejemplo crear base de datos desde XML
private static String URI = "xmldb:exist://localhost:8080/exist/xmlrpc";
public static void main(String args[]) throws Exception {
final String driver = "org.exist.xmldb.DatabaseImpl";
Class cl = Class.forName(driver);
Database database = (Database) cl.newInstance();
database.setProperty("create-database", "true");
DatabaseManager.registerDatabase(database);
Collection col = null;
XMLResource res = null;
try {
// Obtenemos la colección
col = DatabaseManager.getCollection(URI + "/db/jose"); // /db/jose = args[0]
col.setProperty(OutputKeys.INDENT, "no");
res = (XMLResource) col.getResource("agenda.xml"); // agenda.xml = args[1]
if (res == null) {
System.out.println("Documento no encontrado");
} else {
System.out.println(res.getContent());
}
} finally {
// Agregamos lo del finally
}
}Consultas con XPath (Java)
// Consultas con XPATH
private static String URI = "xmldb:exist://localhost:8080/exist/xmlrpc";
public static void main(String args[]) throws Exception {
final String driver = "org.exist.xmldb.DatabaseImpl";
Class cl = Class.forName(driver);
Database database = (Database) cl.newInstance();
database.setProperty("create-database", "true");
DatabaseManager.registerDatabase(database);
Collection col = null;
try {
col = DatabaseManager.getCollection(URI + "/db/jose");
XPathQueryService xpqs = (XPathQueryService) col.getService("XPathQueryService", "1.0");
xpqs.setProperty("indent", "yes");
ResourceSet result = xpqs.query("/agenda/persona/dni[text()]"); // DNI de todas las personas
ResourceIterator i = result.getIterator();
Resource res = null;
while (i.hasMoreResources()) {
try {
res = i.nextResource();
System.out.println(res.getContent());
} finally {
// Agregamos finally
}
}
} finally {
// Agregamos finally
}
}MongoDB
Es un gestor de bases de datos NoSQL, orientado a documentos y pensado para manejar enormes cantidades de datos. Es utilizado por grandes empresas como Google.
Características
Bases de datos distribuidas: diferentes equipos pueden trabajar simultáneamente con la misma base de datos, y pueden realizarse consultas Ad Hoc.
Replicación de datos y uso de la memoria para almacenar volúmenes de datos, lo que permite realizar consultas más rápidas. Los datos se almacenan internamente en formato BSON, aunque se trabaja con ficheros JSON.
¿Qué es JSON?
Es un formato de texto ligero para el intercambio de datos que se utiliza como alternativa a XML. Los datos se almacenan en formato clave-valor.
Los valores pueden ser objetos, arrays o valores primitivos (string, boolean, etc.).
Java: listar bases de datos y colecciones
// Listar bases de datos
private static void listarBBDD() {
MongoCursor dbsCursor = mongoClient.listDatabaseNames().iterator();
while (dbsCursor.hasNext()) {
System.out.println(dbsCursor.next());
}
}
// Listar colecciones
private static void listarColecciones() {
MongoCursor collections = mongoDatabase.listCollectionNames().iterator();
while (collections.hasNext()) {
System.out.println(collections.next().toString());
}
}Método para obtener los diferentes tipos de documentos existentes
private static void listarCampos(String coleccion) {
MongoCursor documents = database.getCollection(coleccion).find().iterator();
Set key = new HashSet();
while (documents.hasNext()) {
Document doc = documents.next();
key.add(doc.keySet().toString());
}
System.out.println(key);
}Crear documentos
// Crear documentos
private static Document crearDocumento() {
boolean anadiendo = true;
Document docNuevo = new Document();
while (anadiendo) {
System.out.println("Inserte campo a insertar");
String campoNuevo = scan.nextLine();
System.out.println("Inserte valor a insertar");
String valorNuevo = scan.nextLine();
docNuevo.append(campoNuevo, valorNuevo);
System.out.println("¿Quiere añadir otro campo?: y/N");
String opcion = scan.nextLine();
if (opcion.equals("Y") || opcion.equals("y")) {
System.out.println("Entonces se añade un nuevo campo");
} else {
anadiendo = false;
System.out.println("El documento nuevo es el siguiente: \n" + docNuevo.toJson());
}
}
return docNuevo;
}Insertar documentos
// Insertar documentos
private static void insertarDocumento() {
System.out.println("Creando documento nuevo:");
Document docNuevo = crearDocumento();
collection.insertOne(docNuevo);
}Buscar documentos
// Buscar documentos
private static void filtrarPorRango(String campo1, String valor1, String campo2, String valor2, String coleccion) {
MongoCursor documentos = collection.find(and(gt(campo1, valor1), lte(campo2, valor2))).iterator();
}Actualizar documentos
// Actualizar documentos
private static void actualizarMuchosDocumentos() {
boolean anadiendo = true;
String campoBuscar = "";
String valorBuscar = "";
Document docNuevo;
System.out.println("Creando documento nuevo a reemplazar:");
docNuevo = crearDocumento();
collection.updateMany(eq(campoBuscar, valorBuscar), new Document("$set", docNuevo));
}Borrado de documentos
// Borrado de documentos
private static void borrarMuchosDocumentos() {
String campoBuscar = "";
String valorBuscar = "";
collection.deleteMany(eq(campoBuscar, valorBuscar));
System.out.println("Documentos borrados");
}Neodatis
Es un gestor de bases de datos orientado a objetos. Es software libre con licencia GNU.
Características
Es fácil de implantar en un programa y no consume muchos recursos. Como desventajas, no ofrece mucha seguridad en los datos y está pensado para almacenamiento individual.
Instalación
Para instalarlo, debemos descargarlo desde su página oficial. Al revisar el contenido, solo necesitamos el fichero .jar para agregarlo a la librería del proyecto.
Ejemplo: creamos la clase Coche
public class Coche {
private float largo;
private float ancho;
private int caballos;
private int asientos;
public Coche(float largo, float ancho, int caballos, int asientos) {
this.largo = largo;
this.ancho = ancho;
this.caballos = caballos;
this.asientos = asientos;
}
// getters y setters
}Conexión e inserción de objetos
// Conexión e inserción de objetos
ODB odbFile = ODBFactory.open("C:\\Users\\Admin\\Desktop\\NeoDatis\\prueba2.db", "usuario", "a");
Coche c1 = new Coche(400.0F, 60.5F, 120, 5);
Coche c2 = new Coche(300.0F, 80.5F, 100, 3);
Coche c3 = new Coche(500.0F, 60.5F, 110, 4);
odbFile.store(c1);
odbFile.store(c2);
odbFile.store(c3);
// Recogemos todos los objetos que contiene la BBDD
Objects coches = odbFile.getObjects(Coche.class);
System.out.println("Número de coches: " + coches.size());
int i = 1;
while (coches.hasNext()) {
Coche c = coches.next();
System.out.println("Coche número: " + i + " Ancho: " + c.getAncho()
+ " Largo: " + c.getLargo() + " Caballos: " + c.getCaballos()
+ " Asientos: " + c.getAsientos());
}
// Filtramos la BBDD
ICriterion criterio = new And().add(Where.equal("largo", 300.0F));
CriteriaQuery query = new CriteriaQuery(Coche.class, criterio);
Coche c = (Coche) odbFile.getObjects(query).getFirst();
System.out.println(" Ancho: " + c.getAncho()
+ " Largo: " + c.getLargo() + " Caballos: " + c.getCaballos()
+ " Asientos: " + c.getAsientos());
// Eliminamos el objeto que hemos recogido
odbFile.delete(c);
// Filtramos la BBDD
ICriterion criterio2 = new And().add(Where.equal("largo", 400.0F));
CriteriaQuery query2 = new CriteriaQuery(Coche.class, criterio2);
Coche cc = (Coche) odbFile.getObjects(query2).getFirst();
System.out.println(" Ancho: " + cc.getAncho()
+ " Largo: " + cc.getLargo() + " Caballos: " + cc.getCaballos()
+ " Asientos: " + cc.getAsientos());
// Modificamos el objeto que hemos recogido
cc.setAncho(80.0F);
odbFile.store(cc);
System.out.println(" Ancho: " + cc.getAncho()
+ " Largo: " + cc.getLargo() + " Caballos: " + cc.getCaballos()
+ " Asientos: " + cc.getAsientos());
// Cerrar la BBDD
odbFile.close();