MEAN: Node.js y Express

Siguiendo con la serie de artículos dedicados al stack MEAN, me dispongo a explicar brevemente las características de Node.js y Express, una infraestructura perfecta para empezar. En esta ocasión no entraré en demasiados detalles, y me limitaré a describir las tecnologías poniendo ejemplos simples que en artículos posteriores desarrollaré con ejemplos, una vez haya presentado todas las tecnologías del stack.

Node.js

JavaScript nació en el lado servidor casi al mismo tiempo que en el navegador. La propia empresa que creó el lenguaje, Netscape, lo incluyó también en su servidor web llamado Netscape Enterprise Server, aunque con poco éxito. Poco después Microsoft lo incorporó a su ASP clásico, donde todavía funciona.

No es sin embargo hasta hace relativamente poco, en 2009, cuando un proyecto empezó a poner en el mapa realmente a JavaScript en el lado servidor. Se trata de Node.js, un entorno de ejecución de aplicaciones multiplataforma y de código abierto (Open Source).

Node.js utiliza el motor de JavaScript de Google, denominado V8, y provee una arquitectura orientada a eventos (como la de los navegadores) así como una serie de APIs no-bloqueantes (asíncronas) que le proporcionan un rendimiento y una escalabilidad muy elevadas. Se puede utilizar para crear cualquier tipo de lógica de aplicación, pero dado que incorpora un módulo para poder actuar como un servidor web, es especialmente popular para crear aplicaciones web. Actualmente lo emplean para sus aplicaciones multitud de empresas de todos los ámbitos pero especialmente de Internet: PayPal, SAP, Groupon e incluso la mismísima Microsoft.

Gracias a Node.js se pueden crear gratuitamente aplicaciones web de alto rendimiento, en cualquier sistema operativo y utilizando como único lenguaje de programación JavaScript.

npm

Node.js cuenta con un repositorio de paquetes que incluye diferentes recursos para utilizar en la creación de aplicaciones. Para acceder a ese repositorio se utiliza el administrador de paquetes denominado npm, el cual nos permite instalar y actualizar innumerables recursos creados por diferentes desarrolladores. Además, permite crear nuestros propios paquetes y recursos de código para poder reutilizarlos y compartirlos con la comunidad.

Cada vez que instalamos un paquete en nuestra aplicación, se añadirá información relacionada en un fichero denominado package.json. Este fichero incluye toda la información importante de una aplicación Node.js en formato JSON, como el nombre y descripción de la misma, la versión actual, el tipo de licencia del mismo, y lo que es más importante, las dependencias necesarias de otros paquetes. Esto nos permite crear paquetes que podremos reutilizar en otras aplicaciones añadiendo éstos como dependencia en el fichero package.json de la nueva aplicación, así como modificar las versiones de las dependencias y demás propiedades importantes.

En el Fragmento de Código 1 podemos ver el fichero package.json de una aplicación web básica. Como podemos observar, existen algunos parámetros que son relativos a la aplicación en sí, como el nombre, la versión o la visibilidad del paquete. Otros más avanzados como scripts, que nos permite introducir comandos habituales en nuestra aplicación, lo cual nos facilitará algunas tareas comunes. Finalmente, la propiedad dependencies, como podemos deducir, incluye los nombres de los paquetes necesarios así como la versión de los mismos.

Las versiones de los paquetes incluyen algunos modificadores que nos permitirán actualizar los paquetes conforme vayan saliendo nuevas versiones, o mantener las versiones específicas de forma estricta. Los modificadores de versión más habituales son los siguientes:

  • >=: Versiones mayores o iguales a una versión concreta. Por ejemplo >=1.3 instalará todas las versiones superiores a la 1.3 sin distinción.
  • ~: Actualizaciones de la rama de la versión especificada. Por ejemplo ~1.3 indicará que se permiten actualizaciones de versiones del tipo 1.3.2, pero en caso de que el paquete se actualizara a la versión 1.4, ésta actualización sería ignorada.

Todos los paquetes que instalemos a través de npm se instalarán en la carpeta node_modules. De esta forma, en caso de que quisiéramos compartir nuestro paquete en un repositorio, o simplemente distribuirlo de forma manual, podríamos ignorar esa carpeta, ya que ejecutando el comando “npm install” se crearía automáticamente la carpeta node_modules y se descargarían del repositorio todas las dependencias indicadas en el fichero package.json. Del mismo modo, en caso de que quisiéramos actualizar las dependencias a versiones más actuales, el comando a utilizar sería “npm update”.

Una forma de utilizar estos paquetes en una aplicación es utilizando la función require, que recibe como parámetro una cadena de texto con el nombre del paquete instalado a utilizar, devolviendo un objeto que contendrá los métodos y valores correspondientes que podremos utilizar.

Servidor HTTP

Una vez instalemos Node.js en el sistema, podremos crear un servidor web completamente funcional definiéndolo en un fichero de texto utilizando los componentes connect y serve-static como podemos ver en el Fragmento de Código 2. El componente connect nos permitirá crear una instancia de servidor HTTP que se encargará de manejar las peticiones en un puerto determinado, mientras que serve-static permitirá a este servidor mostrar ficheros estáticos HTML situados en la misma carpeta del fichero app.js de definición de la aplicación (_dirname) o en cualquier otra carpeta que se le pase por parámetro a este componente en su definición.

Para iniciar el servidor tan solo hay que ejecutar el fichero con node como podemos ver en el Fragmento de Código 3. De esta forma podríamos acceder a los ficheros HTML de la carpeta mediante un navegador en la URL http://localhost:1337/fichero.html.

Existen múltiples formas de crear un servidor en Node.js, así como numerosas extensiones a las que podremos acceder con el ya mencionado administrador de paquetes para crear diferentes tipos de aplicación.

Node.js y MongoDB

Como vimos en la descripción de MongoDB, existe una pequeña diferencia a la hora de utilizar este sistema gestor de base de datos entre un sistema u otro, y es la forma de obtener un objeto de base de datos desde el que realizar las peticiones.

En Node.js podemos utilizar el paquete oficial mongodb para obtener una conexión a la base de datos y realizar peticiones similares a las vistas anteriormente utilizando un esquema de conexión parecido al del Fragmento de Código 4.

Sin embargo, existen otras extensiones más elegantes como mongoose, que nos permite definir esquemas en JavaScript para facilitar la tarea de manejo de colecciones y mantener un código fuente más modular.

Express

Para ayudar a la creación de servidores y aplicaciones web se crearon diferentes infraestructuras que facilitaban esta tarea. Entre éstas destaca Express, que forma parte del conjunto de aplicaciones MEAN, que explicaremos a continuación.

Como hemos explicado anteriormente, Node.js es el entorno ideal para crear la lógica de un gran número de tipos de aplicaciones, y puesto que posee un módulo para controlar el protocolo HTTP, es posible crear aplicaciones web de forma sencilla. Sin embargo, para aplicaciones web medianamente complejas resulta muy laborioso y complejo desarrollar toda la lógica inicial de una aplicación web haciendo uso de Node.js sin ninguna metodología o infraestructura.

Haciendo uso de npm, Express se puede instalar de forma sencilla con el siguiente comando:

Express es una infraestructura de aplicaciones web escrita en JavaScript para Node.js que nace con el propósito específico de crear aplicaciones web en este entorno. Ofrece soporte para las principales necesidades en este tipo de aplicaciones: gestión de peticiones y respuestas, cabeceras, rutas, vistas, etc. Además, cuenta con diferentes plantillas de aplicación que nos permite inicializar diferentes proyectos dependiendo de las necesidades específicas requeridas en cada caso.

Como puede verse en el Fragmento de Código 5 se pueden controlar diferentes tipos de petición HTTP estableciendo el patrón de la URL en el primer parámetro de la función, y la función de control en el segundo, que recibe como parámetros la propia petición, así como un objeto que nos permite establecer una respuesta. En el ejemplo del Fragmento de Código 5 podremos obtener las respuestas oportunas realizando las diferentes peticiones en las URL: http://localhost:3000/, http://localhost:3000/usuario y http://localhost:3000/cliente respectivamente.

Sin embargo, Express cuenta con un generador de aplicaciones que nos permite crear una estructura de aplicación completa ejecutando un simple comando, evitándonos la tarea inicial de gestionar las diferentes peticiones más habituales. Esto facilita notablemente la tarea de crear aplicaciones siguiendo una estructura lógica de carpetas, separando conceptos en diferentes ficheros para hacer más modular el código. Mediante el siguiente comando se creará una estructura de carpetas como la que podemos ver en la Captura 1.

Estructura de carpetas de una aplicación generada con Node.js y Express
Captura 1: Estructura de carpetas de una aplicación generada con Express

Como podemos observar, entre los ficheros que se generan se encuentra el fichero package.json, el cual se corresponde con el que pudimos ver anteriormente en el Fragmento de Código 1, por tanto, para terminar de inicializar la aplicación debemos instalar las dependencias que indica este fichero mediante el ya mencionado comando “npm install”. Una vez instaladas las dependencias podremos iniciar la aplicación mediante el comando del Fragmento de Código 7 que ejecutará el script de inicialización contenido en el fichero package.json que ejecuta el fichero ./bin/www con la definición del servidor HTTP.

La definición de la aplicación la encontramos en el fichero app.js, en el que se incluyen, entre otras cosas, la definición dónde encontrar las rutas disponibles en la aplicación, así como gestión de errores y manejo de vistas. Cabe destacar que, por defecto, Express utiliza un motor de plantillas denominado Jade, el cual permite generar código HTML de forma dinámica mediante un lenguaje propio que permite reutilizar código de forma sencilla. Sin embargo, este lenguaje y su uso se escapa del contexto de nuestro propósito, por lo que no nos detendremos a detallar su funcionamiento. Encontraremos las definiciones de vistas en este lenguaje en los ficheros contenidos en la carpeta views.

Por otro lado, las rutas se encuentran estructuradas de forma modular en diferentes ficheros en la carpeta routes, donde podremos ver código similar al que pudimos ver en el Fragmento de Código 6.

En los próximos artículos partiremos de una aplicación web generada con Express con la estructura anteriormente vista, sin embargo, para procurar que nuestro servidor HTTP esté funcionando de forma constante en la máquina, y de esa manera pueda interactuar con otro tipo de servidores y aplicaciones instalados, haremos uso de la aplicación pm2, contenida en el repositorio de aplicaciones npm, que se encargará de mantener nuestra aplicación web ejecutándose de forma continua.

1

MEAN: MongoDB

Continuando con la serie de artículos relacionados con el stack MEAN (MongoDB, ExpressJS, AngularJS y NodeJS), y tras haber explicado lo que es JSON, paso a explicar los por menores del sistema gestor de bases de datos MongoDB, no sin antes introducir el concepto de NoSQL.

NoSQL

En el lado del almacenamiento se han utilizado tradicionalmente bases de datos relacionales. Sin embargo, actualmente, los tipos de información que suelen requerir las aplicaciones web demandan mayor flexibilidad, menos coherencia y sobre todo mayor capacidad de escalar. Para dar respuesta a todo esto surge la tendencia tecnológica en almacenes de datos que se denomina NoSQL. Aunque el nombre pueda llevar a confusiones, su significado real es “no solo SQL” (Not Only SQL), pues su característica principal es que no utilizan SQL como lenguaje principal para las consultas.

En una base de datos NoSQL los datos almacenados no requieren de estructuras fijas, por lo general tampoco soportan operaciones JOIN y no cumplen completamente las formas normales que garantizan atomicidad, consistencia, aislamiento y durabilidad.

Esta ruptura con las formas tradicionales nace de las nuevas necesidades en el tratamiento de datos. Con el crecimiento de la red y con ello el crecimiento exponencial de la cantidad de datos, se hacía necesario una nueva forma de procesar grandes volúmenes de datos con un mayor rendimiento y que permitiera un procesamiento en tiempo real más eficiente. Estos requerimientos se hicieron mucho más importantes que la coherencia de datos, que eran la principal característica de los sistemas de base de datos clásicos. De esta forma, los sistemas NoSQL basan su optimización en las operaciones de agregar y recuperar datos más allá de la de mantener la consistencia de la información almacenada.

A pesar de que los sistemas NoSQL ofrecen grandes ventajas para algunas estructuras de datos no hay que tomar esta nueva tecnología como un estándar para todos los sistemas que se vayan a desarrollar en el futuro. Los sistemas de base de datos relacionales siguen cumpliendo su papel, y lo seguirán haciendo en la mayoría de los sistemas en los que se utiliza. Es por ello que antes de tomar la decisión de si utilizar un sistema tradicional o un NoSQL habrá que realizar una tarea de análisis para determinar cuál es el mejor gestor de base de datos a utilizar dependiendo de las características del sistema que vayamos a desarrollar.

Almacenamiento de datos NoSQL

Los almacenes de datos NoSQL pueden ser de diversos tipos. Dependiendo de cómo almacenen la información y manejen los datos se clasificarán dentro de uno de los siguientes grupos:

  • Documentales
  • De Grafo
  • Clave-Valor
  • Multivalor
  • Orientados a Objetos
  • Tabulares

MongoDB

De entre todos los almacenes de datos no-relacionales hay uno que destaca especialmente: MongoDB, que es la «M» del stack MEAN.

En la clasificación de bases de datos NoSQL podríamos clasificar a MongoDB entre las bases de datos documentales y de clave valor, ya que en el tratamiento de los datos realiza una mezcla de ambos sistemas. Puesto que está orientado a documentos, lo que se almacena en una base de datos de tipo MongoDB es, valga la redundancia, documentos en BSON, que no es más que una implementación binaria del formato JSON, por lo que todos los datos almacenados en la base de datos se podrían tratar de una forma similar a como se hacen en JavaScript, que será el lenguaje que utilizará estos datos.

Los documentos se almacenan en colecciones, que es lo más parecido a las tablas de los sistemas de bases de datos tradicionales. Sin embargo, a diferencia de las tablas, los elementos de una colección no tienen porqué tener los mismos campos. En el Fragmento de Código 1 podemos ver un ejemplo de colección válida almacenada en BSON con mongoDB. Hay que tener en cuenta que mongoDB añade un campo adicional a todos los documentos de una colección. Este campo se denomina “_id” y es un valor numérico autoincremental de carácter único que sirve de identificador.

Cómo puede verse, no existe un esquema definido, por lo que habrá que plantear la forma de almacenar los datos de una manera diferente a cómo se hace con las bases de datos relacionales, pues, como puede deducirse, no solo carecemos de esquemas definidos, sino también de relaciones.

Almacenamiento de Datos

Si quisiéramos almacenar los datos de una tienda online en la que existen clientes y pedidos podríamos diseñarlo de las siguientes formas, cada una con sus ventajas y desventajas:

Una única colección

Podemos almacenar en una misma colección los datos de los clientes, e incluirles un campo pedidos en el que almacenaríamos una lista con todos los pedidos del cliente. En el Fragmento de Código 2 podemos ver cómo quedaría en la base de datos.

Almacenando los datos de esta forma conseguiremos optimizar las consultas de pedidos de cada cliente, sin embargo, habrá que tener en cuenta, que cuantos más pedidos haga un cliente, mayor crecerá el tamaño de éste, y cada vez que hagamos una consulta de un cliente todos esos datos serán manejados. A largo plazo no parece una buena solución dependiendo del sistema que se vaya a desarrollar.

Dos colecciones

Podemos optar por un diseño de base de datos similar al que utilizaríamos en una base de datos relacional, esto es, utilizando una colección para clientes, y otra para pedidos. En el Fragmento de Código 3 se muestra un ejemplo de cómo se almacenarían los datos en este caso.

Aunque el uso de esta estructura nos pueda parecer más familiar y coherente, debemos tener en cuenta que al no tratarse de un sistema de base de datos relacional, para obtener el conjunto de pedidos de un cliente, anteriormente hemos de obtener el cliente para poder conocer el campo de identificación que lo relaciona con cada pedido, por lo que deberíamos realizar dos peticiones en lugar de una.

Dos colecciones con datos duplicados

Dependiendo del sistema podríamos optar por un diseño híbrido de las dos alternativas anteriores. Supongamos que necesitáramos consultar de forma recurrente el último pedido de un cliente. En este caso sería conveniente almacenar ese pedido en el mismo documento del cliente, además de en la tabla general de pedidos. De esa forma ahorraríamos un gran número de peticiones habiendo tenido en cuenta esa consulta recurrente, sacrificando por otro lado el inconveniente de duplicar la información. En el Fragmento de Código 4 podemos ver un ejemplo de cómo se almacenarían los datos en este caso.

En definitiva, como podemos observar el sistema es muy flexible, y nos permite diseñar siempre la opción más óptima dependiendo del sistema, haciendo en este caso que el sistema de base de datos se adapte a las necesidades del mismo, en lugar de ser el sistema el que se tenga que adaptar a las características de un sistema gestor de base de datos concreto.

Es importante destacar, que escojamos la opción de diseño que escojamos, podremos cambiarla en cualquier momento sin que esto afecte a los datos ya almacenados, lo que supone una gran ventaja a la hora de escoger este sistema.

Operaciones de Consulta

Mientras que en los sistemas tradicionales podíamos utilizar SQL como lenguaje de consulta, en MongoDB no tenemos ese privilegio. En este sistema todas las consultas se realizan mediante JavaScript. Por tanto, en MongoDB no existen cadenas de consulta, si no que existen funciones que aceptan parámetros específicos para realizar las consultas. Las funciones de consulta más utilizadas son find, findOne y findAndModify. En los siguientes apartados veremos un ejemplo de uso de las mismas. Para poder entenderlos debemos definir algunos objetos JavaScript que se utilizarán:

  • db: Objeto de conexión de base de datos. Dependiendo del sistema a utilizar (Express, C#, etc.) se creará de una forma u otra. Todas las peticiones parten de este objeto. Dependiendo del sistema accederemos a las colecciones de una forma u otra, pero en la mayoría de los casos el esquema es muy similar al que veremos a continuación.
  • Colección usuarios: Definimos una colección a la que llamaremos “usuarios” con la estructura del Fragmento de Código 5.

find

Este método es el que nos permite buscar elementos en una colección. Si no le pasamos ningún parámetro nos devolverá todos los elementos de la misma.

Sin embargo, hay que tener en cuenta que este método no nos devolverá de forma automática todos los elementos de una colección, si no que nos devolverá una especie de puntero a los datos solicitados que podremos recorrer de forma sencilla. A este objeto se le denomina cursor.

Cursor

En mongoDB un cursor es una conexión directa con la base de datos que permanece abierta mientras la necesitamos, permitiéndonos iterar sobre los resultados de una consulta concreta. Como ejemplo, para recorrer todos los objetos de una colección podríamos hacer algo parecido a lo que nos encontramos en el Fragmento de Código 6.

Los cursores cuentan con diferentes métodos adicionales que nos pueden servir para diferentes finalidades. Entre ellos destaca la función limit, que acepta como parámetro un número y nos permite limitar el número de resultados, y sort, que nos permite ordenar los resultados conforme a parámetros específicos. La función sort recibe como parámetro un objeto JSON con los campos por los que se deberá ordenar, cada uno con dos posibles valores: 1 en caso de que queramos que se ordene de forma ascendente por ese campo, o -1 en caso contrario. En el Fragmento de Código 7 podemos ver un ejemplo completo de los métodos limit y sort.

El resultado serán los dos primeros objetos de la colección ordenados de forma ascendente por el campo age, y de forma descendente por el campo name.

Filtros

Para poder filtrar los resultados de una consulta debemos pasar como parámetro al método find un documento JSON con las características que deben cumplir los objetos a encontrar. Este procedimiento sería similar a la cláusula WHERE de las sentencias SQL. En el Fragmento de Código 8 podemos ver un ejemplo de uso de un filtro simple que nos devolvería un cursor con el usuario con edad 32 y nombre Catalina Sánchez Román.

Existen diferentes operadores que nos permiten modificar estos filtros para optimizar las búsquedas de forma sencilla.

Proyecciones

Hasta ahora la función find está devolviendo documentos completos de una colección. En SQL sería el equivalente a realizar consultas comenzando con SELECT *. Sin embargo, al igual que con SQL, podemos filtrar los resultados para obtener solo los campos que necesitemos. Para ello haremos uso de las proyecciones, que se pasarán en el segundo parámetro de la función find. Una proyección es un objeto JSON que contiene como pares clave/valor los nombres de los campos a obtener con valores 0 o 1. Utilizaremos el valor 1 en caso de que queramos que ese valor se obtenga, o un 0 en caso contrario. Por defecto, en caso de que pasemos una proyección como parámetro, todos los valores que no definamos de forma explícita tendrán el valor 0, excepto el campo _id, el cual, si no queremos que se encuentre entre los campos devueltos habrá que especificar claramente que debe ser así, como podemos observar en el Fragmento de Código 9, el cual, nos devolverá tan solo los campos name de la colección.

findOne

Este método es parecido al método find, pero en lugar de obtener un cursor, obtendremos un único documento en forma de objeto JavaScript. Si la consulta de búsqueda contiene más de un objeto que cumpla con las condiciones que hayamos establecido, la función findOne nos devolverá el primero. En el Fragmento de Código 10 tenemos un ejemplo de uso con filtros y proyecciones.

findAndModify

En ocasiones se hace necesario modificar un documento y obtener el resultado de la modificación de inmediato. De esta forma certificamos que la modificación se ha hecho correctamente y podemos seguir operando con el objeto en cuestión manteniendo de esa forma cierta consistencia. En este caso, los parámetros se pasarán como un objeto JSON con los siguientes campos:

  • query: Un objeto JSON con los criterios de búsqueda, similar a los filtros de los métodos find y findOne.
  • sort: Un objeto JSON con los criterios de ordenación similar a los parámetros del método sort de los cursores.
  • remove: Campo booleano. Si el valor es true, se borrará el documento encontrado. No es necesario incluirlo si se incluye el campo update.
  • update: Un objeto JSON con los campos a modificar y sus valores. Este campo no es necesario en caso de utilizar el campo remove.
  • new: Campo booleano. Si es true, el método findAndModify devuelve el objeto modificado, en caso contrario devuelve el original antes de ser modificado.
  • fields: Un objeto JSON con la proyección de los datos que queremos obtener.
  • upsert: Campo booleano. Si es true y la consulta no devuelve ningún documento creará uno nuevo con los campos del parámetro update. Si es false no ser hará nada.

En el Fragmento de Código 11 podemos ver una forma de modificar el primer documento con el campo age igual a 32 ordenado de forma descendente por el name cambiándole el name y obteniendo el objeto ya modificado. Como puede deducirse, findAndModify es el método que nos sirve tanto para actualizar datos, como para eliminarlos.

Operaciones de Actualización de Datos

Todas las bases de datos son capaces de realizar operaciones CRUD (Create, Read, Update y Delete). En el apartado anterior hemos visto diferentes formas de realizar opciones de lectura, por lo que nos quedaría ver cómo se insertan y modifican datos en MongoDB.

Inserción

La inserción es uno de los comandos más simples de MongoDB, ya que tan solo hay que utilizar el método insert y pasarle como parámetro un objeto JSON. En el Fragmento de Código 12 podemos ver un ejemplo de inserción de un nuevo usuario en la colección usuarios.

Como mencionamos anteriormente, MongoDB añade automáticamente un campo identificador denominado _id a todos los objetos que se insertan. Este campo se puede añadir en un objeto de inserción sin ningún problema, teniendo en cuenta que en caso de introducir un valor que coincida con alguno ya almacenado en la colección, MongoDB nos devolverá una excepción.

Existe otra función que nos permite introducir objetos en una base de datos pero que, en caso de añadir un campo _id que ya exista en la colección, en lugar de devolver una excepción, modificaría el objeto que coincidiera con esa misma _id introducida. Esta función se denomina save y se utiliza de la misma forma que se hace con insert.

Para añadir varios objetos a la vez debemos pasar como parámetro un array JSON con los objetos a añadir, como podemos observar en el Fragmento de Código 13.

Borrado

Para eliminar documentos de una colección utilizaremos el método remove, que recibe como parámetro un objeto JSON con los criterios de selección de los elementos a borrar como podemos ver en el Fragmento de Código 14, dónde se eliminarían todos los objetos de la colección cuyo campo age sea igual a 32 y cuyo campo mail sea “miguel@smendoza.net”. En caso de no pasarle ningún parámetro se borraría la colección completa.

Actualización

En el apartado anterior sobre Operaciones de Consulta, vimos un ejemplo de cómo actualizar un documento haciendo uso de la función findAndModify. Sin embargo, existe otra forma más directa de actualizar un documento, y es haciendo uso de la función update. Esta función recibe como parámetros un objeto con los criterios de selección del elemento o elementos a modificar, y un objeto JSON con el nuevo objeto a sustituir. El Fragmento de Código 15 muestra un ejemplo de cómo sustituir todos los documentos cuyo campo age sea 32 por un objeto diferente, es decir, no se realizaría una actualización de los campos propiamente dichos dentro del objeto que coincida con los criterios, si no que el objeto sería sustituido por completo por el nuevo pasado por parámetro, sea como sea su estructura.

Como puede observarse éste no es el comportamiento habitual de una operación de actualización, ya que estamos acostumbrados a utilizar este tipo de funciones para actualizar campos concretos de un objeto en una base de datos, en lugar de sustituirlos por completo. Para lograr un comportamiento similar al de las sentencias UPDATE en SQL deberemos utilizar un operador de MongoDB denominado $set. Éste nos permitirá actualizar campos concretos de un objeto que coincida con los criterios de búsqueda introducidos en el primer parámetro. En el Fragmento de Código 32 podemos ver como modificar el campo mail del documento con valor del campo _id igual a 1.

Instalación

Para instalar una base de datos mongoDB tan solo deberemos seguir los pasos que podremos encontrar en el siguiente enlace:

https://docs.mongodb.com/manual/installation/

La instalación es un proceso bastante sencillo, por lo que no nos detendremos en este momento a detallar los por menores de la misma, pero resulta de vital importancia entender que una vez instalado en nuestro sistema, podremos acceder a la base de datos mediante línea de comandos y ejecutar todos los comandos que veremos a continuación. En la mayoría de sistemas esto se consigue ejecutando el comando «mongo» en un terminal.

Recomiendo utilizar una interfaz de usuario de administración (Admin UI) para manejar los datos de forma más eficiente. Entre todas las posibilidades yo destacaría Robomongo, ya que su facilidad de uso y posibilidades superan con creces a las demás alternativas. En cuanto a interfaz de usuario basada en web recomiendo utilizar mongo-express. La utilización y posibilidades de estas herramientas escapan al contexto del artículo, por lo que os animo a investigar una vez hayáis entendido bien los conceptos.

Conclusión

Como hemos podido ver, MongoDB es un sistema gestor de base de datos muy flexible y sencillo de utilizar. Todas las sentencias que hemos visto podríamos utilizarlas tanto en el terminal de comandos del propio sistema de Mongo, como a través de cualquier framework compatible.

En los siguientes artículos, veremos como utilizar MongoDB desde NodeJS y como integrarlo en un entorno real.

1

MEAN: JSON

Hace cosa de un año decidí sacarme la titulación del Grado en Ingeniería Informática convalidando gran parte del mismo con mi Ingeniería Técnica en Informática. Realmente solo tuve que hacer dos asignaturas, y presentar un TFG o Trabajo de Fin de Grado. Aproveché el TFG para sumergirme en el mundo del desarrollo de aplicaciones web de tipo SPA (Single Page Application) en Angular 1.x utilizando el stack MEAN (MongoDB, Express, AngularJS y NodeJS), para lo que desarrollé una aplicación web que ahora se utiliza en mi entorno laboral de forma frecuente.

Puesto que no supe hacerlo de otra manera, toda la memoria de mi TFG se convirtió en un gran tutorial que pretendía recoger todos los conocimientos necesarios para que cualquier iniciado pudiera desarrollar su aplicación web. Pasado un tiempo, y después de haberme encontrado de nuevo con el documento en sí, me ha parecido buena idea compartir todos los contenidos de esa memoria de forma estructurada, por lo que iré creando diferentes artículos con los distintos capítulos del mismo.

Intentaré partir de los conocimientos más básicos necesarios para ir comprendiendo las diferentes tecnologías que utilicé, por lo que considero primordial comenzar hablando del formato de datos utilizado en todos los intercambios de información de la arquitectura MEAN. Este estándar es el llamado JavaScript Object Notation, o comúnmente denominado JSON (ECMA-404).

JSON es una alternativa más ligera al XML como formato de intercambio de datos, ya que no necesita de etiquetas que encierren la información, si no que se sirve de una notación simple basada en comillas, llaves y corchetes que hacen que la información no solo sea más liviana, si no más fácilmente entendible.

Estructuras

En JSON existen dos tipos de estructuras básicas:

Objeto

Colección de pares clave/valor encerrados entre llaves. También es denominado diccionario o array asociativo. En la Figura 1 se muestra la definición formal de un objeto JSON.

Esquema de un Objeto JSON
Figura 1: Objeto JSON

Un ejemplo de objeto JSON sería el siguiente:

Array

Colección ordenada de valores encerrados entre llaves. En la Figura 2 podemos ver que la diferencia fundamental con un objeto.

Estructura de un Array JSON
Figura 2: Array JSON

A continuación podemos ver dos ejemplos de arrays en JSON:

Datos

Resulta importante destacar que los valores que se pueden utilizar en una estructura JSON son números y cadenas de texto, los valores booleanos true o false, null como valor nulo, además de los ya mencionados objetos y arrays. En la Figura 3 podemos ver la definición formal de valor en JSON.

Estructura de Valores en JSON
Figura 3: Valores en JSON

La especificación de JSON define además el formato de las cadenas de texto, por lo que habrá que tomar especial atención a la hora de crearlas, ya que no se permiten caracteres especiales como tal, si no que hay que utilizar notación UNICODE. En la Figura 4 podemos ver un ejemplo de cómo se forma una cadena de texto JSON.

Estructura de Cadenas de Texto en JSON
Figura 4: Cadenas de Texto en JSON

Los números en JSON no necesitan introducirse entre comillas, pero si tienen que cumplir ciertas reglas de formato como se puede observar en la Figura 5.

Estructura de Números en JSON
Figura 5: Números en JSON

Para finalizar, en el siguiente ejemplo podemos ver un extraño objeto JSON con diferentes elementos:

1