Mongo en Java

Hola mundo en Java

Utilizaremos Maven, así que lo primero que haremos será crear en nuestro IDE un proyecto Maven simple al que añadiremos la dependencia a Mongo:

Seguidamente, creamos una clase con un método main:

Si vemos la consola, comprobamos que nos muestra el documento:

DBObject y BasicDBObject

Las colecciones se representan en java con objetos que implementen la interfaz DBObject, que son colecciones de “cosas”. Tienen básicamente los mismos métodos que un map. La implementación por defecto es BasicDBObject.

Vamos a ver un ejemplo en el que se creará un documento:

Si nos fijamos en el penúltimo put, vemos como se incluye un array y en el último put, tenemos el modo de incluir un sub-documento con la dirección.

Insertción

Aquí tenemos un ejemplo de inserción, cuando se hace el primer insert se crea el id, y dicho id aparece en el propio objeto “doc”. Al hacer el segundo insert se produce una excepción.

Para insertar varios documentos se puede hacer:

findOne(), cursor y count()

El método find one, es muy simple:

En el caso de que queramos recorrer un cursor, lo mejor es encerrarlo en un try y cerrar dicho cursor antes de terminar. En el siguiente ejemplo usamos find(), con lo que recuperaríamos todos los elementos.

Podemos contar los elementos de este modo:

Ejecutar consultas

Existen dos modos de realizar consultas, el primero es con el propio DBObject:

Aquí estaríamos buscando los documentos con “x = 0” y la propiedad “y > 10” y “y < 90”

El segundo modo es usar el objeto QueryBuilder la equivalecia sería:

Seleccionando campos

Lo que hay que hacer, es añadir un segundo parámetro en la consulta con los criterios de selección.

Con “new BasicDBObject(“y”, true)” estamos seleccionando únicamente el campo “y” de cada objeto, si lo pusieramos a false, estaríamos seleccionando todos los campos, menos el “y”.

Usando la notación punto en java

Cuando queremos acceder a subdocumentos, lo hacemos con el punto:

La primera sentencia busca la propiedad “x” del documento que está dentro de la propiedad “coordenadas” y devuelve los que son mayores de 50. En el cursor, únicamente recuperamos el valor y:

sort() skip() and limit()

En el siguiente ejemplo vamos a ordenar por dos criterios simultáneos, por x de manera ascendente y por y de manera descendente, siendo x e y dos propiedades de un subdocumento que contiene la propiedad “coordenadas”. Se salta los dos primeros y devuelve 10 resultados.

update() y remove()

En el siguiente ejemplo vamos a actualizar el documento con id = “64646”, el comportamiento es similar a lo que hemos visto, es decir, eliminará todas las propiedades que tenga y añadirá “valor”:

Si lo que queremos es actualizar un valor, sin eliminar el resto, hay que añadir un BDObjet con un $set:

Hay dos parámetros más en el objeto BasicBDObject, el primero es “upsert” y el segundo es “multi”. Upsert a false, indica que si no encuentra el criterio, en este caso “new BasicDBObject(“_id”, “64646”)”, que no haga nada. Si se pone a true, creará un registro con el id “64646” y el valor que pongamos… Multi, indica, que debe de añadir o modificar todos los registros que cumplan con el criterio o únicamente el primero que encuentre.

Finalmente para eliminar, se realiza algo similar a lo siguiente:

Replica set y el driver de Java

Si estamos trabajando con un “replica set” e intentamos hacer una consulta desde Java, se nos mostrará la siguiente excepción:

Para evitar esto, hay que definir una lista de conexiones a nuestro replica set, de modo que intente encontrar el nodo primario en la lista proporcionada, por ejemplo:

maginemos que en el ejemplo anterior, hemos definido en la lista los tres nodos que aparece, pero en realidad tenemos más nodos, por ejemplo 10. Bien, estos nodos serán auto descubiertos, con que en la lista exista al menos un nodo válido que funcione como primario.

Otro problema que podemos tener, es que estemos realizando una inserción, y en ese momento el nodo primario se caiga. En ese caso se produciría una excepción como la que se ha mostrado al principio de este apartado y el programa terminaría. Para evitar esto, se puede capturar las excepciones y reintentar la inserción transcurridos unos segundos, para dar tiempo a que se asigne un nuevo nodo primario. Por ejemplo:

Preferencias respecto a la escritura de datos

Anteriormente hemos comentado que podemos ajustar el driver de java, para que se comporte de una determinada manera a la hora de asegurar las inserciones de datos, esto es, comprobar si se ha realizado la escritura en el nodo primario, si se han replicado los datos en algún nodo secundario, etc. Esto se hace a través de WriteConcern de este modo:

Esto se puede hacer a nivel de cliente, de la base de datos utilizada, de colección o a nivel de la operación realizada, por ejemplo:

No vamos a entrar en detalle sobre los ámbitos de escritura, pero comentaremos algunas cosas. Las constantes definidas en WriteConcern son objetos que tienen cuatro parámetros:

  • w → Número de servidores en los que se replica la información
  • wtimeout → timeout en las operaciones de escritura
  • fsync → si se deben sincronizar o no
  • j → si las operaciones de escritura deben esperar a que se haga commit en el “journal”

Algunas constantes interesantes:

  • ERRORS_IGNORED → Se ignoran los errores. Se utiliza si queremos conseguir la máxima velocidad
  • JOURNALED → Se lanzan excepciones si hay problemas con la red o con el servidor. La operación de escritura espera a que se registre en el fichero journal en disco
  • REPLICA_ACKNOWLEDGED → Que se replique la información por lo menos 2 servidores
  • MAJORITY → que se escriba en la mayoría de los servidores

Hay muchas más constantes, para conocer los detalles lo mejor es consultar el API. Los valores que garantizan que la escritura persiste en disco son w=1 y j=1

Preferencias respecto a la lectura de datos

Si estamos escribiendo en el nodo primario y leyendo de nodos secundarios, es posible que la lectura no esté sincronizada con las modificaciones que acabamos de realizar. Se puede definir la manera en la que queremos realizar la lectura de este modo:

Veamos algunos tipos:

  • primary() → Únicamente lee del nodo primario
  • primaryPreferred() → Lee del nodo primario si está disponible
  • secondary() → Lee de los nodos secundarios
  • secondaryPreferred() → Lee de los secundarios si están disponibles
  • nearest() → Lee del nodo más cercano en términos de tiempo

Un comentario:

  1. Buenas, leí todos los documentos, mis felicitaciones !!!!!!

Deja un comentario

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