martes, 25 de mayo de 2010

Proyectos ágiles distribuidos

Interesante presentación sobre cómo funcionan los proyectos distribuídos (en diferentes lugares geográficos, normalmente en países distantes), por qué suelen fracasar, y cómo las metodologías ágiles pueden mejorar la situación.

Disponible MongoDB v1.4.3 estable

Acaba de ser liberada la versión estable 1.4.3. de MongoDB, que corrige algunos bugs de la versión 1.4.2:
- $set con compensación de array no debería actualizar el índice
- corregido multi-actualización
- los valores syncdelay que son demasiado grandes podrían provocar overflow y causar fsyncs
constantemente
- reparado registro mongod.exe con espacios en el path, si se ejecuta en Windows como un servicio

Fuente: http://groups.google.com/group/mongodb-user/browse_thread/thread/82062d0f09483b03

Enlace de descarga: http://www.mongodb.org/display/DOCSES/Descarga

lunes, 24 de mayo de 2010

Primeros pasos en Java y MongoDB - Parte 2

En la entrada anterior abordamos cómo conectar a la base de datos MongoDB y cómo realizar consultas. En el presente post abordaremos cómo modificar datos en una colección.


Inserciones
La operación más sencilla es la inserción, gracias a la cual añadimos un nuevo documento a una colección. Tomemos el siguiente ejemplo extraído del tutorial de Java de MongoDB. Tenemos el siguiente documento:


{
  "name" : "MongoDB",
  "type" : "database",
  "count" : 1,
  "info" : {
    x : 203,
    y : 102
  }
}


El campo info es un documento embebido dentro del documento principal. La forma de añadir este documento a MongoDB mediante código Java, sería la siguiente:


// Conexion por defecto a localhost por el puerto 27017
Mongo con = new Mongo();
DB bbdd = con.getDB("nombreBaseDatos");
DBCollection col = bbdd.getCollection("nombreColeccion");

BasicDBObject doc = new BasicDBObject();

doc.put("name", "MongoDB");
doc.put("type", "database");
doc.put("count", 1);

BasicDBObject info = new BasicDBObject();

info.put("x", 203);
info.put("y", 102);

doc.put("info", info);

col.insert(doc);


En el ejemplo anterior hemos almacenado un único documento. Si lo que se desea es almacenar una lista de documentos de una sola vez, es posible crear un array o una lista de tipo DBOject, y pasar éste como parámetro. El método insert añadirá todos los documentos a la colección.


abstract void insert(DBObject arr[])

abstract foid insert(List list)


Nota: En el caso anterior, el documento contenía pares campo/valor de tipo nativo (cadenas de texto, números) o de tipo documento (embebido). Si el dato es un array, definir un tipo Vector, y asignarlo como valor a un campo.


Actualizaciones
La actualización permite modificar un documento ya existente.

Existe varias maneras de hacerlo. La primera es mediante el método save, cuya sintaxis es la siguiente:


public final void save(DBOject doc)


El funcionamiento de este método es muy simple: "guardar el documento 'doc', sustituyendo si ya existe, o añadiendo si no existe". En el caso de la sustitución, el documento debe tener el campo "_id" y el valor correspondiente del documento a sustituir.

Otra forma de actualizar documentos es mediante el método update, el cual posee varias posibilidades. La más sencilla sería por sustitución de documento:


BasicDBObject oquery = new BasicDBObject();
oquery.put("name", "MongoDB");
oquery.put("type", "database");

BasicDBObject doc = new BasicDBObject();

doc.put("name", "MongoDB");
doc.put("type", "database");
doc.put("count", 3);

BasicDBObject info = new BasicDBObject();

info.put("x", 255);
info.put("y", 64);

doc.put("info", info);

col.update(oquery, doc);


El método update admite varias sintaxis. En la utilizada en el ejemplo anterior, recoge dos parámetros. El primero de ellos (oquery), contiene un documento de filtro, en el que se especifican los campos y valores que deben cumplirse para los documentos a modificar. En este caso, las condiciones eran "cuyo 'name' tenga el valor 'MongoDB' Y cuyo 'type' tenga el valor 'database'". Si hubiese más de un documento que se correspondiera con el resultado del filtro, por defecto, se asumiría el primero.

El segundo parámetro sería un documento completo que sustituirá por completo al documento encontrado.

Otra forma modificar documentos sería a través de operaciones atómicas. Esto significa que se modifica directamente un elemento del documento, en lugar de sustituir el documento completo. El siguiente ejemplo cambiaría el valor del campo count:


BasicDBObject oquery = new BasicDBObject();
oquery.put("name", "MongoDB");
oquery.put("type", "database");

BasicDBObject doc = new BasicDBObject();
BasicDBObject op = new BasicDBObject();
op.put("count", 4);
doc.put("$set", op);

col.update(oquery, doc);


Esto sería similar a la sentencia SQL:

UPDATE col SET count=4 WHERE name='MongoDB' AND type='database'

Existe una lista rica de operaciones atómicas, muy útiles según el caso. Para más información, consulta la siguiente URL:

http://www.mongodb.org/display/DOCSES/Actualizar

El método update permite las siguientes sintaxis:


public void update(
  DBObject query,
  DBOject doc)

public abstract void update(
  DBObject query,
  DBObject doc,
  boolean upsert,
  boolean multi)


La primera de ellas, es la vista anteriormente. La segunda de ellas, posee cuatro parámetros. Los dos primeros ya los conocemos. Los dos restantes:

- upsert: Si se especifica el valor true, si el filtro se cumple, actualiza los documentos encontrados. Si no se cumple, añade el documento doc a la colección (como un insert). Si se especifica el valor false (por defecto), sólo permite actualizar, no insertar.
- multi: Si se especifica el valor true, si el filtro retorna varios documentos, las actualizaciones se realizarán sobre todos ellos. Si se especifica el valor false (por defecto), las actualizaciones sólo se realizarán sobre el primer documento retornado.

El driver Java de MongoDB ofrece también el método updateMulti, cuya sintaxis es la siguiente:


public void updateMulti(
  DBObject query,
  DBOject doc)


La sintaxis es exactamente igual que la primera del método update. Sin embargo, update solamente actualiza el primer documento encontrado por el filtro. Con updateMulti las actualizaciones se aplicarían a todos los documentos encontrados.


Eliminaciones
Para eliminar documentos, se utiliza el método remove, cuya sintaxis es la siguiente:

public abstract void remove(DBObject query)

El parámetro query es un filtro que determina qué documentos han de coincidir para la eliminación. Dicha eliminación se aplica a todos los documentos que coincidan con el filtro.

jueves, 20 de mayo de 2010

iPad: Cuidado con lo que dices delante de tu enemigo

En 2007, Steve Jobs y Bill Gates fueron entrevistados en un programa de TV. Bill Gates habló su visión del tablet con todo lujo de detalles. Jobs tomó buena nota y se dio prisa. La paradoja es que Microsoft tenía un tablet en camino, con un concepto muy bueno, pero han tenido que enterrarlo antes de ver la luz, por culpa del iPad.

miércoles, 12 de mayo de 2010

El canon de la SGAE es ilegal

Leo en Barrapunto:

"La abogada general del Tribunal de Justicia de la Unión Europea (TUE), Verica Trstenjak, dictaminó hoy que el canon digital que se aplica en España es ilegal porque se impone indiscriminadamente a todos los equipos y materiales de reproducción y no únicamente a los que presumiblemente se vayan a destinar a la realización de copias privadas. "Un sistema nacional que prevé la aplicación de un canon por copia privada a todos los equipos, aparatos y materiales de reproducción digital de forma indiscriminada (como ocurre en España) no es compatible" con la normativa comunitaria, afirma el dictamen."

Yo añadiría: También es ilegal porque se aplica indiscriminadamente a todos los ciudadanos, a los que el canon acusa, implícita y presumiblemente, de atentar contra los derechos de autor y de delinquir, aun cuando se utilice para uso personal (fotos, documentos, programas, etc.), o para copias de uso privado (cosa permitida por la ley), o para grabar documentos Creative Commons, software libre, o cualquier otro tipo de medio libre de derechos de autor privativos.

Seguro que si me presento a la SGAE con todos mis CD's, DVD's, discos duros, cámaras de fotos, o cualquier dispositivo por el que he pagado el canon, para uso personal y LEGAL, a reclamar la devolución del mismo, se van a reír en mi cara.

Y digo yo: ¿quién comete delito, el que ha estafado a todos los españoles con un impuesto revolucionario absurdo y lucrativo, o los millones de españoles que usan la tecnología para su propio uso y disfrute?. ¿Por qué el gobierno está coaccionado por una entidad privada y sectaria, y no impone un organismo estatal que vele por los intereses de los autores y los derechos de los ciudadanos? ¿Cuándo se darán cuenta de que Internet y la tecnología es la mejor oportunidad para todos, y que la industria tiene la herramienta de mayor promoción, difusión y marketing que se haya inventado nunca? ¿Cuándo se darán cuenta que la propia Internet es también cultura, y que estamos viviendo una era sin parangón donde la cultura se expande y se enriquece de forma ilimitada?

martes, 11 de mayo de 2010

Primeros pasos en Java y MongoDB - Parte 1

MongoDB es una base de datos que cuenta con una amplia comunidad, y fruto de ello, son los proyectos que en torno ella se generan, especialmente los drivers, los cuales permiten acceder a la base de datos desde cualquier lenguaje de programación. En este post se realizará una introducción al uso del Driver de Java para Mongo.

Nota:
Se asume que el lector tiene conocimientos sobre programación de Java. En este artículo se omite cualquier estructura de código Java, enfocándose únicamente en las declaraciones y usos concretos del driver de Java para MongoDB.


Descarga del driver de Java

El Driver de Java para Mongo se encuentra en la siguiente URL:

http://www.mongodb.org/display/DOCSES/Centro+de+lenguaje+Java


Documentación sobre el driver

El Driver de Java cuenta con una documentación muy completa, la cual es accesible desde la siguiente URL:

http://www.mongodb.org/display/DOCSES/Centro+de+lenguaje+Java


Conexión al servidor

El primer paso a realizar es importar las clases del driver. Para ello, utilizar la sentencia import de la siguiente manera:

import com.mongodb.*;

Una vez importadas las clases, lo primero es crear una conexión al servidor. Existen varias maneras de hacer ésto:

// Conexion por defecto a localhost por el puerto 27017
Mongo con = new Mongo();
// Conexion al servidor "mongosrv" por el puerto 27017
Mongo con = new Mongo("mongosrv");
// Conexion al servidor "mongosrv" por el puerto 30000
Mongo con = new Mongo("mongosrv", 30000);



Uso de una base de datos

Un servidor de base de datos MongoDB puede tener múltiples bases de datos. Para indicar qué base de datos se desea utilizar, introducir la siguiente sentencia:

DB bbdd = con.getDB("nombreBaseDatos");


Utilizar una colección

Una vez en uso la base de datos, hay que especificar qué colección de entre las existentes en dicha base de datos, queremos utilizar. Para ello, se obtiene la colección a través de la siguiente sentencia:

DBCollection col = bbdd.getCollection("nombreColeccion");


Consultas simples

La consulta más sencilla posible sería la siguiente:

DBObject doc = col.findOne();
System.out.println(doc);


Retornaría el primer documento de la colección, mostrándolo por la consola.

Para obtener más documentos, hay que recuperar un cursor:

DBCursor cur = col.find();
while (cur.hasNext())
  System.out.println(cur.next());


El código anterior recuperaría todos los documentos de la colección y los mostraría por la consola.


Consultas de filtro

Las consultas de filtro permiten seleccionar solamente aquellos documentos que cumplen algún criterio. Por ejemplo, imaginemos que tenemos una colección Agenda, y queremos consultar todos los contactos de Madrid. La consulta sería la siguiente:

...
DBCollection col = bbdd.getCollection("Agenda");

// Se crea el documento de filtro
BasicDBObject filtro = new BasicDBObject();
filtro.put("provincia", "Madrid");
DBCursor cur = col.find(filtro);
while (cur.hasNext())
  System.out.println(cur.next());


Esta consulta sería similar a si lo hiciéramos desde la consola mongo:

db.Agenda.find({"provincia":"Madrid"})

Para ser más concretos y precisos en el filtro, se pueden añadir más condiciones, con las cuales se realizaría una selección AND/Y. Por ejemplo, para extraer los documentos de aquellas personas que se llamen Pedro, Y que vivan en Madrid, Y que tengan vehículo, el filtro quedaría de la siguiente manera:

filtro.put("nombre", "Pedro");
filtro.put("provincia", "Madrid");
filtro.put("vehiculo", true);


Esto equivaldría a:

db.Agenda.find({"nombre":"Madrid", "provincia":"Madrid", "vehiculo":true})

También es posible especificar operadores lógicos para limitar el rango de la consulta. El siguiente ejemplo extaería de la agenda a las personas mayores de edad que pueden trabajar:

filtro.put("edad", new BasicDBObject("$gte", 18));
filtro.put("edad", new BasicDBObject("$lte", 65));


Esto equivaldría a:

db.Agenda.find({"edad":{"$gte":18}, "edad":{"$lte":18}})

Nota: Para más información sobre consultas avanzadas mediante el uso de operadores lógicos, consultar: Consultas Avanzadas o Complejas


Acceso a los valores

Las aplicaciones que acceden a los datos, normalmente lo harán a sus valores, con el fin de realizar operaciones concretas con los mismos: formato, cálculo, comparación, etc.

El siguiente ejemplo valida un usuario y una contraseña, recogiendo el nombre completo, el idioma y la edad:

...
DBCollection col = bbdd.getCollection("Usuarios");

String sUsuario = "usuario";
String sPassword = "password";
String sNombre;
String sIdioma;
Integer iEdad;

BasicDBObject filtro = new BasicDBObject();
filtro.put("usuario", sUsuario);
filtro.put("password", sPassword);
DBObject result = col.findOne(filtro);

if (result==null)
  System.out.println("No se encuentra el usuario");
else {
  sNombre = (String)result.get("nombre");
  sIdioma = (String)result.get("idioma");
  sEdad = (Integer)result.get("edad");
}


Imaginemos ahora que deseamos recoger todas las áreas donde un determinado usuario puede acceder. La estructura de su documento podría ser el siguiente:

{"usuario":"usuario", "areas":["Area 1", "Area 2", "Area 3"]}

En este caso, la clave areas es un array. Para poder leer este array y almacenarlo en un vector interno, se utilizaría el siguiente código:

...
DBCollection col = bbdd.getCollection("Usuarios");

Vector v;

BasicDBObject filtro = new BasicDBObject();
filtro.put("usuario", "usuario");
DBObject result = col.findOne(filtro);

if (result==null)
  System.out.println("No se encuentra el usuario");
else {
  v = new Vector();
  BasicDBList dbl = (BasicDBList)obj.get("areas");
  for (int i=0; i<dbl.size(); i++)
    v.add((String)dbl.get(i));
}


Imaginemos ahora documentos en un array embebido en otro documento:

{"usuario":"usuario", prestado:[{"tipo":"libro", "titulo":"Don Quijote"}, {"tipo":"pelicula", "titulo":"Casablanca"}]}

El acceso a este esquema sería el siguiente:

...
DBCollection col = bbdd.getCollection("Usuarios");

BasicDBObject filtro = new BasicDBObject();
filtro.put("usuario", "usuario");
DBObject result = col.findOne(filtro);

if (result==null)
  System.out.println("No se encuentra el usuario");
else {
  BasicDBList dbl = (BasicDBList)obj.get("prestado");
  for (int i=0; i<dbl.size(); i++) {
    DBObject doc = dbl.get(i);
    System.out.println("Tipo: "+ (String)doc.get("tipo") + " / Titulo: " + (String)doc.get("titulo"));
  }
}

martes, 4 de mayo de 2010