Advertisement
  1. Code
  2. Coding Fundamentals
  3. Databases & SQL

Asignación de bases de datos relacionales y SQL a MongoDB

Scroll to top
Read Time: 12 min

() translation by (you can also view the original English article)

Las bases de datos NoSQL han surgido enormemente en los últimos años debido a su estructura menos restringida, diseño de esquemas escalables y acceso más rápido en comparación con las bases de datos relacionales tradicionales (RDBMS/SQL). MongoDB es una base de datos NoSQL orientada a documentos de código abierto que almacena datos en forma de objetos similares a JSON. Se ha convertido en una de las bases de datos líderes debido a su esquema dinámico, alta escalabilidad, rendimiento óptimo de consultas, indexación más rápida y una comunidad de usuarios activa.

Si vienes de un entorno RDBMS/SQL, comprender los conceptos de NoSQL y MongoDB puede ser un poco difícil al comenzar porque ambas tecnologías tienen formas muy diferentes de representación de datos. Este artículo te llevará a comprender cómo el dominio RDBMS/SQL, sus funcionalidades, términos y lenguaje de consulta se asignan a la base de datos MongoDB. Por mapeo, quiero decir que si tenemos un concepto en RDBMS/SQL, veremos cuál es su concepto equivalente en MongoDB.

Comenzaremos con la asignación de los conceptos relacionales básicos como tabla, fila, columna, entre otros; y avanzaremos para discutir la indexación y las combinaciones. Luego revisaremos las consultas SQL y discutiremos sus correspondientes consultas de base de datos MongoDB. El artículo asume que conoces los conceptos básicos de las bases de datos relacionales y SQL, porque a lo largo del artículo se hará más énfasis en comprender cómo se asignan estos conceptos en MongoDB. Comencemos.


Asignación de tablas, filas y columnas

Cada base de datos en MongoDB consta de colecciones que son equivalentes a una base de datos RDBMS que consta de tablas SQL. Cada colección almacena datos en forma de documentos que equivalen a tablas que almacenan datos en filas. Mientras que una fila almacena datos en su conjunto de columnas, un documento tiene una estructura similar a JSON (conocida como BSON en MongoDB). Por último, de la forma en que tenemos filas en una fila SQL, tenemos campos en MongoDB. A continuación te muestro un ejemplo de un documento (fila de lectura) que tiene algunos campos (columnas de lectura) que almacenan los datos del usuario:

1
{
2
"_id": ObjectId("5146bb52d8524270060001f3"),
3
"age": 25,
4
"city": "Los Angeles",
5
"email": "mark@abc.com",
6
"user_name": "Mark Hanks"
7
}

Este documento es equivalente a una sola fila en RDBMS. Una colección consta de muchos de estos documentos, al igual que una tabla consta de muchas filas. Ten en cuenta que cada documento de una colección tiene un campo _id único, que es un campo de 12 bytes que sirve como clave principal para los documentos. El campo se genera automáticamente en la creación del documento y se utiliza para identificar de forma única cada documento.

Para comprender mejor las asignaciones, tomemos un ejemplo de los users de una tabla SQL y su estructura correspondiente en MongoDB. Como se muestra en la Fig 1, cada fila de la tabla SQL se transforma en un documento y cada columna en un campo de MongoDB.

Figure 1 Mapping Table to Collection (1)Figure 1 Mapping Table to Collection (1)Figure 1 Mapping Table to Collection (1)
Figura 1

Esquema dinámico

Algo interesante en el que enfocarse aquí es que diferentes documentos dentro de una colección pueden tener diferentes esquemas. Entonces, es posible en MongoDB que un documento tenga cinco campos y el otro documento tenga siete campos. Los campos se pueden agregar, eliminar y modificar fácilmente en cualquier momento. Además, no hay restricciones sobre los tipos de datos de los campos. Por lo tanto, en una instancia, un campo puede contener datos de tipo int y en la siguiente instancia puede contener un array.

Estos conceptos les deben parecer muy diferentes a los lectores provenientes del entorno RDBMS donde las estructuras de las tablas, sus columnas, tipos de datos y relaciones están predefinidas. Esta funcionalidad para usar esquema dinámico nos permite generar documentos dinámicos en tiempo de ejecución.

Por ejemplo, ten en cuenta los siguientes dos documentos dentro de la misma colección pero con esquemas diferentes (Fig 2):

Figure 2 Documents in a Collection having different structureFigure 2 Documents in a Collection having different structureFigure 2 Documents in a Collection having different structure
Figura 2

El primer documento contiene los campos address y dob que no están presentes en el segundo documento, mientras que el segundo documento contiene los campos gender y occupation que no están presentes en el primero. Imagínate si hubiéramos diseñado esto en SQL, hubiéramos mantenido cuatro columnas adicionales para address, dob, gender y occupation, algunas de las cuales almacenarían valores vacíos (o nulos) y, por lo tanto, ocuparían un espacio innecesario.

Este modelo de esquema dinámico es la razón por la que las bases de datos NosSQL son altamente escalables en términos de diseño. Se pueden diseñar de manera eficiente varios esquemas complejos (jerárquicos, estructurados en árbol, entre otros) que requerirían un número de tablas RDBMS utilizando dichos documentos. Un ejemplo típico sería almacenar publicaciones de usuarios, sus me gusta, comentarios y otra información asociada en forma de documentos. Una implementación de SQL para el mismo idealmente tendría tablas separadas para almacenar publicaciones, comentarios y me gusta, mientras que un documento de MongoDB puede almacenar toda esta información en un solo documento.


Mapeo de uniones y relaciones

Las relaciones en RDBMS se logran mediante relaciones de clave principal y externa y consultando a las que usan combinaciones. No existe un mapeo tan sencillo en MongoDB, pero aquí las relaciones están diseñadas utilizando documentos incrustados y vinculados.

Considera un ejemplo en el que necesitamos almacenar la información del usuario y la información de contacto correspondiente. Un diseño SQL ideal tendría dos tablas, por ejemplo, user_information y contact_information, con las claves principales id y contact_id como se muestra en la Fig 3. La tabla contact_information también contendría una columna user_id que sería la clave externa que enlazaría al campo id de la tabla user_information.

Figure 3Figure 3Figure 3
Figura 3

Ahora veremos cómo diseñaríamos tales relaciones en MongoDB usando enfoques de vinculación de documentos y documentos incrustados. Ten en cuenta que en el esquema SQL, generalmente agregamos una columna (como id y contact_id en nuestro caso) que actúa como una columna principal para esa tabla. Sin embargo, en MongoDB, generalmente usamos el campo de _id generado automáticamente como clave principal para identificar de forma única los documentos.

Vinculación de documentos

Este enfoque utilizará dos colecciones, user_information y contact_information, ambas con sus campos _id únicos. Tendremos un campo user_id en el documento contact_information que se refiere al campo _id del documento user_information que muestra a qué usuario corresponde el contacto. (Consulta la Fig 4) Ten en cuenta que en MongoDB, las relaciones y sus operaciones correspondientes deben cuidarse manualmente (por ejemplo, a través del código) ya que no se aplican restricciones ni reglas de clave externa.

Figure 4 Linking Documents in MongoDBFigure 4 Linking Documents in MongoDBFigure 4 Linking Documents in MongoDB
Figura 4

El campo user_id en nuestro documento es simplemente un campo que contiene algunos datos y toda la lógica asociada con él tiene que ser implementada por nosotros. Por ejemplo, incluso si vas a insertar algunos user_id en el documento contact_information que no existen en la colección user_information, MongoDB no va a producir ningún error que diga que el user_id correspondiente no se encontró en la colección user_information (a diferencia de SQL donde se trataría de una restricción de clave externa no válida).

Incrustación de documentos

El segundo enfoque es incrustar el documento contact_information dentro del documento user_information de esta manera (Fig 5):

Figure 5 Embedding Documents in MongoDBFigure 5 Embedding Documents in MongoDBFigure 5 Embedding Documents in MongoDB
Figura 5

En el ejemplo anterior, incrustamos un pequeño documento de información de contacto dentro de la información del usuario. De manera similar, los documentos grandes y complejos y los datos jerárquicos se pueden incrustar de esta manera para relacionar entidades.

Además, el enfoque que se va a usar entre el enfoque de vinculación e incrustación depende del escenario específico. Si se espera que los datos que se van a incrustar aumenten de tamaño, es mejor utilizar el enfoque de vinculación en lugar del enfoque incrustado para evitar que el documento se vuelva demasiado grande. El enfoque integrado se utiliza generalmente en casos en los que se debe incorporar una cantidad limitada de información (como la dirección en nuestro ejemplo).


Gráfico de mapeo

Para resumir, el siguiente cuadro (Fig 6) representa las correlaciones comunes que discutimos:

Figure 6 Mapping ChartFigure 6 Mapping ChartFigure 6 Mapping Chart
Figura 6

Asignación de SQL a consultas de MongoDB

Ya que nos sentimos cómodos con las asignaciones básicas entre RDBMS y MongoDB, discutiremos cómo difiere el lenguaje de consulta utilizado para interactuar con la base de datos entre ellos.

Para las consultas de MongoDB, supongamos una colección users con estructura de documento de la siguiente manera:

1
{
2
"_id": ObjectId("5146bb52d8524270060001f3"),
3
"post_text":"This is a sample post" ,
4
"user_name": "mark",
5
"post_privacy": "public",
6
"post_likes_count": 0
7
}

Para consultas SQL, asumimos que la tabla users tiene cinco columnas con la siguiente estructura:

Figure 7 Sample SQL TableFigure 7 Sample SQL TableFigure 7 Sample SQL Table
Figura 7

Discutiremos consultas relacionadas con la creación y modificación de colecciones (o tablas), inserción, lectura, actualización y eliminación de documentos (o filas). Hay dos consultas para cada punto, una para SQL y otra para MongoDB. Explicaré las consultas de MongoDB solo porque estamos bastante familiarizados con las consultas SQL. Las consultas de MongoDB que se presentan aquí están escritas en el shell de JavaScript de Mongo, mientras que las consultas SQL están escritas en MySQL.

Crear

En MongoDB, no es necesario crear explícitamente la estructura de colección (como lo hacemos para las tablas que utilizan una consulta CREATE TABLE). La estructura del documento se crea automáticamente cuando se produce la primera inserción en la colección. Sin embargo, puedes crear una colección vacía mediante el comando createCollection.

1
SQL: CREATE TABLE `posts` (`id` int(11) NOT NULL AUTO_INCREMENT,`post_text` varchar(500) NOT NULL,`user_name` varchar(20) NOT NULL,`post_privacy` varchar(10) NOT NULL,`post_likes_count` int(11) NOT NULL,PRIMARY KEY (`id`))
2
3
MongoDB: db.createCollection("posts")

Insertar

Para insertar un documento en MongoDB, usamos el método insert que toma un objeto con pares de valores clave como su entrada. El documento insertado contendrá el campo _id generado automáticamente. Sin embargo, también puedes proporcionar explícitamente un valor de 12 bytes como _id junto con los otros campos.

1
SQL: INSERT INTO `posts` (`id` ,`post_text` ,`user_name` ,`post_privacy` ,`post_likes_count`)VALUES (NULL ,  'This is a sample post',  'mark',  'public',  '0');
2
3
MongoDB:  db.posts.insert({user_name:"mark", post_text:"This is a sample post", post_privacy:"public", post_likes_count:0})

No hay una función Alter Table en MongoDB para cambiar la estructura del documento. Como los documentos son dinámicos en el esquema, el esquema cambia a medida que ocurre alguna actualización en el documento.

Lectura

MongoDB utiliza el método find que es equivalente al comando SELECT en SQL. Las siguientes declaraciones simplemente leen todos los documentos de la colección posts.

1
SQL: SELECT * FROM  `posts`
2
3
MongoDB: db.posts.find()

La siguiente consulta realiza una búsqueda condicional de documentos que tienen el campo user_name como  mark. Todos los criterios para obtener los documentos deben colocarse entre las primeras llaves {} separadas por comas.

1
SQL: SELECT * FROM `posts` WHERE `user_name` =  'mark'
2
3
MongoDB: db.posts.find({user_name:"mark"})

La siguiente consulta obtiene columnas específicas, post_text y post_likes_count como se especifica en el segundo conjunto de llaves {}.

1
SQL: SELECT  `post_text` ,  `post_likes_count` FROM  `posts`
2
3
MongoDB: db.posts.find({},{post_text:1,post_likes_count:1})

Ten en cuenta que MongoDB de forma predeterminada devuelve el campo _id con cada instrucción find. Si no queremos que este campo esté en nuestro conjunto de resultados, tenemos que especificar la clave _id con un valor 0 en la lista de columnas que se van a recuperar. El valor 0 de la clave indica que queremos excluir este campo del conjunto de resultados.

1
MongoDB: db.posts.find({},{post_text:1,post_likes_count:1,_id:0})

La siguiente consulta recupera campos específicos en función de los criterios que user_name es mark.

1
SQL: SELECT  `post_text` , `post_likes_count` FROM `posts` WHERE `user_name` =  'mark'
2
3
MongoDB: db.posts.find({user_name:"mark"},{post_text:1,post_likes_count:1})

Ahora agregaremos un criterio más para obtener las publicaciones con el tipo de privacidad como público. Los campos de criterios especificados mediante comas representan la condición lógica AND. Por lo tanto, esta declaración buscará documentos que tengan tanto user_name como mark y post_privacy como public.

1
SQL: SELECT  `post_text` ,  `post_likes_count` FROM  `posts` WHERE  `user_name` =  'mark' AND  `post_privacy` =  'public'
2
3
MongoDB: db.posts.find({user_name:"mark",post_privacy:"public"},{post_text:1,post_likes_count:1})

Para utilizar OR lógico entre los criterios del método find, usamos el operador $or.

1
SQL: SELECT  `post_text` ,  `post_likes_count` FROM  `posts` WHERE  `user_name` =  'mark' OR  `post_privacy` =  'public'
2
3
MongoDB: db.posts.find({$or:[{user_name:"mark"},{post_privacy:"public"}]},{post_text:1,post_likes_count:1})

Después, usaremos el método sort que ordena el resultado en orden ascendente de post_likes_count (indicado por 1).

1
SQL: SELECT *  FROM `posts` WHERE `user_name` = 'mark' order by post_likes_count ASC
2
3
MongoDB: db.posts.find({user_name:"mark"}).sort({post_likes_count:1})

Para ordenar los resultados en orden descendente, especificamos -1 como el valor del campo.

1
SQL: SELECT *  FROM `posts` WHERE `user_name` = 'mark' order by post_likes_count DESC
2
3
MongoDB: db.posts.find({user_name:"mark"}).sort({post_likes_count:-1})

Para limitar el número de documentos que se devolverán, utilizamos el método limit especificando el número de documentos.

1
SQL: SELECT *  FROM `posts` LIMIT 10
2
3
MongoDB: db.posts.find().limit(10)

La forma en que usamos offset en SQL para omitir algunos registros, usamos la función skip en MongoDB. Por ejemplo, la siguiente instrucción obtendría diez publicaciones omitiendo las cinco primeras.

1
SQL: SELECT *  FROM `posts` LIMIT 10 OFFSET  5
2
3
MongoDB: db.posts.find().limit(10).skip(5)

Actualizar

El primer parámetro del método update especifica los criterios para seleccionar los documentos. El segundo parámetro especifica la operación de actualización real que se realizará. Por ejemplo, la siguiente consulta selecciona todos los documentos con user_name como mark y configura sus post_privacy como private.

Una diferencia aquí es que, de forma predeterminada, la consulta update de MongoDB actualiza solo un documento (y el primer documento coincidente). Para actualizar todos los documentos coincidentes, debemos proporcionar un tercer parámetro que especifique multi como true, lo que indica que queremos actualizar varios documentos.

1
SQL: UPDATE posts SET post_privacy = "private" WHERE user_name='mark'
2
3
MongoDB: db.posts.update({user_name:"mark"},{$set:{post_privacy:"private"}},{multi:true})

Eliminar

La eliminación de documentos es bastante simple y similar a SQL.

1
SQL: DELETE FROM posts WHERE user_name='mark'
2
 
3
MongoDB:  db.posts.remove({user_name:"mark"})

Indexación

MongoDB tiene un índice predeterminado creado en el campo _id de cada colección. Para crear nuevos índices en los campos, usamos el método secureIndex que especifica los campos y el orden de clasificación asociado indicado por 1 o -1 (ascendente o descendente).

1
SQL: CREATE INDEX index_posts ON posts(user_name,post_likes_count DESC)
2
3
MongoDB: db.posts.ensureIndex({user_name:1,post_likes_count:-1})

Para ver todos los índices presentes en cualquier colección, usamos el método getIndexes en las mismas líneas de la consulta SHOW INDEX de SQL.

1
SQL: SHOW INDEX FROM posts
2
3
MongoDB: db.posts.getIndexes()

Conclusión

En este artículo, entendimos cómo se relacionan los conceptos y términos elementales de RDBMS/SQL en MongoDB. Analizamos el diseño de relaciones en MongoDB y aprendimos cómo se asigna la funcionalidad de las consultas SQL básicas en MongoDB.

Después de comenzar con este artículo, puedes continuar probando consultas complejas que incluyen agregación, reducción de mapas y consultas que involucran múltiples colecciones. También puedes utilizar algunas herramientas en línea para convertir consultas SQL en consultas MongoDB al principio. Puedes jugar a diseñar un esquema de base de datos MongoDB de muestra por tu cuenta. Uno de los mejores ejemplos para hacerlo sería una base de datos para almacenar publicaciones de usuarios, sus me gusta, comentarios y me gusta de comentarios. Esto te brindaría una vista práctica del diseño de esquema flexible que ofrece MongoDB.

No dudes en comentar cualquier sugerencia, pregunta o idea que te gustaría ver más.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.