{"id":7351,"date":"2019-08-06T06:57:07","date_gmt":"2019-08-06T13:57:07","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=7351"},"modified":"2023-07-26T12:09:43","modified_gmt":"2023-07-26T19:09:43","slug":"postgres-jsonb-and-nosql","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/postgres-jsonb-and-nosql\/","title":{"rendered":"Comparaci\u00f3n de Postgres JSONB con NoSQL"},"content":{"rendered":"<p><span style=\"font-weight: 400\">La realidad es que las bases de datos est\u00e1n convergiendo y, en los \u00faltimos a\u00f1os, se est\u00e1 haciendo a\u00fan m\u00e1s dif\u00edcil se\u00f1alar cu\u00e1les son los mejores escenarios para cada almac\u00e9n de datos sin un conocimiento profundo de c\u00f3mo funcionan las cosas bajo el cap\u00f3.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Postgres ha sido mi RDBMS favorito durante a\u00f1os, y estoy encantado con la creciente popularidad de su soporte JSONB. En mi opini\u00f3n personal, ayudar\u00e1 a que los desarrolladores est\u00e9n m\u00e1s familiarizados con todas las ventajas de almacenar datos como JSON en lugar de como simples tablas.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Sin embargo, he visto a mucha gente presentando inadvertidamente Postgres 11 como \"El Nuevo NoSQL\" o que no necesitan ning\u00fan <a href=\"https:\/\/www.couchbase.com\/blog\/es\/resources\/why-nosql\/\">Base de datos NoSQL<\/a> puesto que ya utilizan Postgres. En este art\u00edculo, me gustar\u00eda abordar las principales diferencias y casos de uso.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Si no tiene tiempo de leer todo el art\u00edculo, resumir\u00e9 los resultados m\u00e1s importantes en la conclusi\u00f3n.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><b>Modelizaci\u00f3n de datos: RDBMS y bases de datos de documentos<\/b><\/h2>\n<p><span style=\"font-weight: 400\">Todos estamos familiarizados con el coste de una operaci\u00f3n JOIN en un RDBMS a escala: Si tienes 1 Mill\u00f3n de usuarios con 10 preferencias cada uno, entonces para traer a este usuario a la memoria, suponiendo que est\u00e1s usando un framework ORM (<\/span><span style=\"font-weight: 400\">Mapeo Objeto-Relacional<\/span><span style=\"font-weight: 400\">) tendr\u00e1 que hacer un join con una tabla de USER_PREFERENCES con 10 millones de filas.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">En el mundo real, los usuarios tambi\u00e9n suelen estar asociados a muchas otras entidades, lo que empeorar\u00e1 a\u00fan m\u00e1s la situaci\u00f3n y obligar\u00e1 a los desarrolladores a decidir qu\u00e9 relaciones deben ser perezosas o ansiosas. Hoy en d\u00eda, todos los RDBMS disponen de muchas optimizaciones para el escenario anterior, pero modelar los datos de la forma en que lo hemos venido haciendo durante los \u00faltimos 30 a\u00f1os es definitivamente sub\u00f3ptima.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Una de las razones por las que RDBMS se hizo tan bueno en el manejo de transacciones es exactamente por la limitaci\u00f3n de su modelo de datos: \u00bfTiene sentido almacenar un pedido si no hay art\u00edculos en \u00e9l? A\u00fan as\u00ed, me veo obligado a crear una transacci\u00f3n para guardar esta \"unidad \u00fanica\" repartida entre al menos dos tablas: <\/span><b>PEDIR<\/b><span style=\"font-weight: 400\"> y <\/span><b>\u00cdTEM_ORDEN<\/b><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Veamos un escenario a\u00fan m\u00e1s com\u00fan: c\u00f3mo se puede almacenar un usuario en una base de datos de documentos frente a un RDBMS:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-7381\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p1-1-1024x523.png\" alt=\"\" width=\"900\" height=\"460\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1-1024x523.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1-300x153.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1-768x392.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1-20x10.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1.png 1300w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p><span style=\"font-weight: 400\">En una base de datos de documentos, las entidades con fuertes relaciones suelen almacenarse en una \u00fanica estructura. En este enfoque, casi no hay coste adicional para cargar cosas como preferencias y permisos, mientras que en un modelo relacional requerir\u00eda al menos 2 uniones.<\/span><\/p>\n<p><span style=\"font-weight: 400\">\u00a0Ahora, ampliemos este ejemplo a un caso sencillo de comercio electr\u00f3nico:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-7353\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p2-1024x658.png\" alt=\"\" width=\"739\" height=\"475\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2-1024x658.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2-300x193.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2-768x493.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2-20x13.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2.png 1177w\" sizes=\"auto, (max-width: 739px) 100vw, 739px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">En el ejemplo anterior, una base de datos de documentos no necesitar\u00eda ning\u00fan JOIN para listar usuarios y productos. Para los pedidos, sin embargo, podr\u00eda necesitar una o dos, lo que es totalmente aceptable. El mismo modelo en un RDBMS requerir\u00eda al menos ~12 tablas:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-7354\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p3-1024x910.png\" alt=\"\" width=\"598\" height=\"531\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3-1024x910.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3-300x267.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3-768x683.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3-20x18.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3.png 1052w\" sizes=\"auto, (max-width: 598px) 100vw, 598px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Utilizando nuestro ejemplo anterior, puede observar que los JOIN son esenciales para un RDBMS, mientras que en una base de datos de documentos se utilizan con menos frecuencia. Lo mismo ocurre con las transacciones o las operaciones en cascada, ya que la mayor\u00eda de las entidades relacionadas se almacenan en un \u00fanico documento.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Algunas de las bases de datos NoSQL m\u00e1s famosas todav\u00eda no soportan JOINs correctamente. Afortunadamente, este no es el caso aqu\u00ed. Couchbase incluso soporta <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/es\/ansi-join-support-n1ql\/\"><span style=\"font-weight: 400\">UNIONES ANSI<\/span><\/a><span style=\"font-weight: 400\">:\u00a0<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">SELECT DISTINCT route.destinationairportFROM `travel-sample` airport JOIN `travel-sample` route\u00a0 \r\n     ON airport.faa = route.sourceairport\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n       AND route.type = \"route\"\r\nWHERE airport.type = \"airport\"\u00a0\u00a0\r\n     AND airport.city = \"San Francisco\"\u00a0\u00a0\r\n     AND airport.country = \"United States\";<\/pre>\n<p><span style=\"font-weight: 400\">S\u00e9 que es posible que haya visto esta explicaci\u00f3n sobre el modelado de datos para RDBMS vs modelado de datos para NoSQL antes, pero tengo que hacer hincapi\u00e9 en que a medida que cada base de datos est\u00e1 optimizado para un modelo de datos espec\u00edfico, y que jugar\u00e1 un papel importante durante las pruebas de rendimiento.\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><b>El mito del silo<\/b><\/h2>\n<p><span style=\"font-weight: 400\">Como el usuario y el nombre del producto raramente cambiar\u00e1n, podr\u00eda simplemente almacenarlos ambos en la entidad Pedidos para evitar unos cuantos JOINS, esta es una estrategia com\u00fan en <a href=\"https:\/\/www.couchbase.com\/blog\/es\/products\/capella\/\">Bases de datos NoSQL<\/a>pero no se aplica estrictamente:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-7355\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p4-1024x476.png\" alt=\"\" width=\"512\" height=\"238\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4-1024x476.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4-300x139.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4-768x357.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4-20x9.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4.png 1143w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/p>\n<p><span style=\"font-weight: 400\">El almacenamiento en cach\u00e9 de datos en otras entidades puede mejorar significativamente el rendimiento de tus consultas a escala, pero hay algunas contrapartidas: Si tienes que almacenar en cach\u00e9 estos datos en m\u00faltiples partes de tu sistema, cada vez que estos datos cambien tendr\u00e1s que ejecutar unas cuantas actualizaciones para \"mantener los datos sincronizados\".\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">He visto a muchos desarrolladores experimentados utilizar esto como un inconveniente de las bases de datos de documentos, y siempre tengo que recordarles que se podr\u00eda tener exactamente el mismo problema en un RDBMS.\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><b>Postgres JSONB Tipo de columna<\/b><\/h2>\n<p><span style=\"font-weight: 400\">En Postgres, JSONB es un tipo especial de columna que puede almacenar JSON en un formato optimizado para lecturas:<\/span><\/p>\n<pre class=\"lang:pgsql decode:true\">CREATE TABLE my_table (\u00a0\u00a0id integer NOT NULL,\u00a0\u00a0data jsonb);<\/pre>\n<p><span style=\"font-weight: 400\">Como se indica en este <\/span><a href=\"https:\/\/www.youtube.com\/watch?v=tMT16q9pqp\"><span style=\"font-weight: 400\">v\u00eddeo<\/span><\/a><span style=\"font-weight: 400\">Si bien es cierto que el almacenamiento de datos en una columna JSONB tiene algunas penalizaciones de rendimiento, la base de datos tiene que analizar el JSON para almacenarlo en un formato optimizado para la lectura, lo que parece una compensaci\u00f3n justa.<\/span><\/p>\n<p><b>NOTA:<\/b><span style=\"font-weight: 400\"> Ignoremos la columna JSON de Postgres por ahora, ya que incluso la documentaci\u00f3n de Postgres indica que, en general, deber\u00edas elegir JSONB en lugar del tipo de columna JSON.<\/span><\/p>\n<p><span style=\"font-weight: 400\">En teor\u00eda, incluso se puede emular una base de datos de documentos en Postgres utilizando una columna JSONB para todas las entidades anidadas:<\/span><\/p>\n<pre class=\"lang:pgsql decode:true\">CREATE TABLE users (\u00a0\u00a0\r\n     id integer NOT NULL,\u00a0\u00a0\r\n     name varchar,\u00a0\u00a0username varchar,\u00a0\u00a0\r\n     address jsonb,\u00a0\u00a0\r\n     preferences jsonb,\u00a0\u00a0\r\n     permissions jsonb\r\n);<\/pre>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">Manipulaci\u00f3n de datos<\/span><\/h2>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">Aqu\u00ed es donde las cosas empiezan a ponerse realmente interesantes: En primer lugar, Postgres no sigue exactamente la <\/span><a href=\"https:\/\/standards.iso.org\/ittf\/PubliclyAvailableStandards\/c067367_ISO_IEC_TR_19075-6_2017.zip\"><span style=\"font-weight: 400\">Normas SQL:2016<\/span><\/a><span style=\"font-weight: 400\"> (<\/span><a href=\"https:\/\/en.wikipedia.org\/wiki\/ISO_9075\"><b>ISO\/IEC 9075:2016<\/b><\/a><span style=\"font-weight: 400\">). Esto no es necesariamente algo malo, ya que las consultas en esta especificaci\u00f3n pueden ser f\u00e1cilmente bastante grandes, pero sigue siendo algo a tener en cuenta.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Siempre me gusta destacar los est\u00e1ndares porque las bases de datos NoSQL ya han recorrido este camino antes, y hoy en d\u00eda tenemos docenas de lenguajes diferentes y una importante inversi\u00f3n en refactorizaci\u00f3n si quieres migrar de una NoSQL a otra.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Ojal\u00e1, <\/span><a href=\"https:\/\/forward.ucsd.edu\/sqlpp.html\"><span style=\"font-weight: 400\">SQL<\/span><\/a><span style=\"font-weight: 400\"> vino al rescate, el padre del propio SQL, Don Chamberlin, <\/span><a href=\"https:\/\/www.amazon.com\/SQL-Users-Tutorial-Don-Chamberlin\/dp\/0692184503\"><span style=\"font-weight: 400\">escribi\u00f3 un libro sobre ello<\/span><\/a><span style=\"font-weight: 400\"> el a\u00f1o pasado. En esta sesi\u00f3n, comparar\u00e9 las funciones y operadores JSON de Postgress con una implementaci\u00f3n de SQL++ llamada N1QL, que es el lenguaje de consulta que utilizamos en Couchbase.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Insertos<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Las inserciones son lo que cabr\u00eda esperar, la principal diferencia entre la sintaxis de Postgres y N1QL es que en la primera, s\u00f3lo unas pocas columnas de una fila contendr\u00e1n una cadena codificada en JSON, mientras que en la segunda, todo el documento es un JSON:<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">INSERT INTO users VALUES (1, 'First User', 'user1',\u00a0\u00a0 \r\n'{\"streetName\": \"Wayside Lane\", \"houseNumber\": 3104, \"zipcode\": \"94538\", \"city\": \"Fremont\", \"state\": \"CA\", \"country\": \"US\", \"entrances\": [{\"name\" : \"main\"}] }',\u00a0\u00a0\r\n'[{\"name\": \"lang\", \"value\": \"en\"},{\"name\": \"notification\", \"value\":\"emailOnly\"},\u00a0{{\"name\":\"timezone\",\"value\": \"GMT+2\"}]',\u00a0\r\n'{\"groups\":[\"MARKETING\"], \"roles\": [\"ADMIN\", \"PREMIUM_USER\"]}');<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">INSERT INTO `test` ( KEY, VALUE ) VALUES ( \"1\", {\r\n  \"type\": \"users\",\r\n  \"name\": \"First User\",\r\n  \"username\": \"user1\",\r\n  \"address\": {\r\n    \"streetName\": \"Wayside Lane\", \r\n      \"houseNumber\": 3104, \r\n        \"zipcode\": 94538, \r\n        \"city\": \"Fremont\", \r\n        \"state\": \"CA\", \r\n        \"country\": \"US\", \r\n        \"entrances\": [{\"name\" : \"main\"}] },\r\n  \"preferences\": [\r\n    {\"name\": \"lang\", \"value\": \"en\"},\r\n    {\"name\": \"notification\", \"value\":\"emailOnly\"},\r\n    {\"name\":\"timezone\",\"value\": \"GMT+2\"}],\r\n  \"permissions\": {\r\n    \"groups\":[\"MARKETING\"], \r\n    \"roles\": [\"ADMIN\", \"PREMIUM_USER\"]}\r\n});\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">Actualizaciones<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Empecemos con una actualizaci\u00f3n muy sencilla<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">update users set address = jsonb_set(address, '{state}', '\"California\"') WHERE address-&gt;'state' = '\"CA\"';<\/pre>\n<p><span style=\"font-weight: 400\">En la sintaxis de Postgres, las cadenas deben especificarse entre comillas dobles y simples ('\"CA\"'), mientras que los literales deben ir entre comillas simples ('false' o '123').\u00a0<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">update `test` set address.state = 'California' where address.state = 'CA' and type = 'users'<\/pre>\n<p><span style=\"font-weight: 400\">En Couchbase no existe un concepto similar al de tabla, por lo que diferenciamos los documentos seg\u00fan un \"<\/span><b>tipo<\/b><span style=\"font-weight: 400\">\", que en este caso debe ser igual a \"<\/span><b>usuarios<\/b><span style=\"font-weight: 400\">\". El resto de la consulta es similar al SQL est\u00e1ndar, o si vienes del mundo Java, es casi la misma sintaxis que JPA JPQL.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Intentemos un ejemplo m\u00e1s complejo en el que a\u00f1adimos una nueva entrada a la casa, actualizamos el c\u00f3digo postal y eliminamos el rol ADMIN del usuario de destino:<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">UPDATE users\r\n   SET address = jsonb_set( jsonb_set(\r\n\t\t\t\t\taddress::jsonb,\r\n\t\t\t\t\tarray['entrances'],\r\n\t\t\t\t\t(address-&gt;'entrances')::jsonb || '{\"name\": \"backyard\"}'::jsonb), \r\n\t\t\t\t '{zipcode}', '94537'),\r\n\t\tpermissions = jsonb_set(permissions, '{roles}', (permissions-&gt;'roles') - 'ADMIN')<\/pre>\n<p><span style=\"font-weight: 400\">Las consultas Postgres pueden volverse f\u00e1cilmente demasiado complejas si necesitas manipular el JSON. En algunos casos, incluso <\/span><a href=\"https:\/\/stackoverflow.com\/questions\/45035597\/how-to-update-deeply-nested-json-object-based-on-filter-criteria-in-postgres\"><span style=\"font-weight: 400\">tienen que crear funciones<\/span><\/a><span style=\"font-weight: 400\"> s\u00f3lo para ejecutar algunas actualizaciones b\u00e1sicas. Para m\u00ed, esto es se\u00f1al de que a\u00fan necesitamos algunas mejoras en el lenguaje de consulta.\u00a0<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">update `test` set address.zipcode = 94537, \r\n                  address.entrances = ARRAY_APPEND(address.entrances,  {\"name\": \"backyard\"}),\r\n                  permissions.roles = ARRAY_REMOVE(permissions.roles, \"ADMIN\") \r\n<\/pre>\n<p><span style=\"font-weight: 400\">Incluso si usted no est\u00e1 familiarizado con N1QL puede entender claramente lo que est\u00e1 pasando en la consulta anterior, N1QL tiene <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/arrayfun.html\"><span style=\"font-weight: 400\">docenas de funciones s\u00f3lo para tratar matrices<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">SELECCIONE<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Como la selecci\u00f3n de datos es un tema extenso, vamos a dividirlo en sesiones m\u00e1s peque\u00f1as:<\/span><\/p>\n<h4><\/h4>\n<h4><span style=\"font-weight: 400\">Consulta de datos sencillos<\/span><\/h4>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">select address-&gt;'city' from users where address @&gt; '{\"zipcode\": \"94537\"}'\r\nselect * from users where address @&gt; '{\"entrances\":[{\"name\": \"backyard\"}]}'\r\n<\/pre>\n<p><span style=\"font-weight: 400\">La magia <\/span><strong>@&gt;<\/strong><span style=\"font-weight: 400\"> te permite emparejar f\u00e1cilmente un par clave-valor o un objeto dentro de tu JSON. De hecho, hace que sea m\u00e1s f\u00e1cil hacer coincidir cosas en JSON, aunque hay algunas cosas que debes tener en cuenta:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">\u00a0El operador <\/span><b>@&gt; <\/b><span style=\"font-weight: 400\">s\u00f3lo admite comparaciones de igualdad<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">En la segunda consulta, hacemos coincidir <\/span><b>patio trasero<\/b><span style=\"font-weight: 400\"> en la matriz de entradas, pero la matriz real es en realidad la siguiente:<\/span><\/li>\n<\/ul>\n<pre class=\"lang:js decode:true\">{\r\n...\r\n    \"entrances\": [\r\n        {\r\n            \"name\": \"main\"\r\n        },\r\n        {\r\n            \"name\": \"backyard\"\r\n        }\r\n    ],\r\n...\r\n}\r\n<\/pre>\n<p><span style=\"font-weight: 400\">As\u00ed, cuando buscamos un atributo (\"c\u00f3digo postal\", en este primer caso), el atributo <\/span><b>@&gt; <\/b><span style=\"font-weight: 400\">se comport\u00f3 como <\/span><b>es igual a<\/b><span style=\"font-weight: 400\">pero si utilizamos el mismo operador para buscar en un array, se comporta como \"<\/span><b>contiene<\/b><span style=\"font-weight: 400\">\".<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">Select address.city from `test` where\u00a0 address.zipcode = \u201894537\u2019;\r\nselect * from `test`\u00a0 where ANY entrance IN address.entrances SATISFIES entrance.name = \"main\" END;\r\nselect * from `test` as t where \"main\" within t; \/\/search for the occurence of \u201cmain\u201d inside the JSON<\/pre>\n<p><span style=\"font-weight: 400\">No existe una correlaci\u00f3n directa entre los valores de\u00a0 <\/span><b>@&gt;<\/b><span style=\"font-weight: 400\"> y una palabra clave en N1QL. En las consultas anteriores utilizamos diferentes estrategias para lograr las mismas cosas. La sintaxis de Postgres es m\u00e1s corta para consultas muy simples, pero si filtramos por dos o tres atributos las consultas en N1QL tendr\u00e1n aproximadamente el mismo tama\u00f1o. En este caso tambi\u00e9n se puede utilizar cualquier tipo de operadores de comparaci\u00f3n.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Una cosa que me parece un plus es que las consultas que utilizan la sintaxis SQL++ \"<\/span><b>parecerse m\u00e1s a SQL\".<\/b><span style=\"font-weight: 400\"> que el SQL del propio Postgres.\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">Navegar por los objetos<\/span><\/h3>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">select * from users where (address-&gt;&gt;'houseNumber')::int &gt; 5<\/pre>\n<p><span style=\"font-weight: 400\">Postgres utiliza la funci\u00f3n <\/span><b>-&gt;&gt;<\/b><span style=\"font-weight: 400\"> para navegar por las entidades y el operador <\/span><b>-&gt;<\/b><span style=\"font-weight: 400\"> para convertir un atributo en texto. Pero si tu atributo es un entero tienes que convertir id de nuevo a int.<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">Select * from `test` where address.houseNumber &gt; 5<\/pre>\n<p><span style=\"font-weight: 400\">En el caso anterior puede simplemente navegar a trav\u00e9s de las entidades utilizando el bot\u00f3n \"<\/span><b>.<\/b><span style=\"font-weight: 400\">\" y se deduce autom\u00e1ticamente el tipo adecuado.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">Tratamiento de atributos ausentes\/existentes<\/span><\/h4>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">select * from users where (preferences-&gt;'randomAttributeName\u2019') is\u00a0 null<\/pre>\n<p><span style=\"font-weight: 400\">Postgres considera los valores perdidos como NULL, lo que es sem\u00e1nticamente incorrecto:<\/span><\/p>\n<ul>\n<li><span style=\"font-weight: 400\">JSON con null \"<\/span><b>randomAttributeName''<\/b><span style=\"font-weight: 400\"> :<\/span><\/li>\n<\/ul>\n<pre class=\"lang:js decode:true\">[\r\n    {\r\n        \"name\": \"lang\",\r\n        \"value\": \"en\",\r\n        \"timezone\": \"GMT+2\",\r\n        \"notification\": \"emailOnly\",\r\n       \u201crandomAttributeName\u2019': null\r\n    }\r\n]\r\n<\/pre>\n<p>&nbsp;<\/p>\n<ul>\n<li><span style=\"font-weight: 400\">JSON al que le falta \"<\/span><b>randomAttributeName''<\/b><span style=\"font-weight: 400\"> :<\/span><\/li>\n<\/ul>\n<pre class=\"lang:js decode:true\">[\r\n    {\r\n        \"name\": \"lang\",\r\n        \"value\": \"en\",\r\n        \"timezone\": \"GMT+2\",\r\n        \"notification\": \"emailOnly\"\r\n    }\r\n]\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">Puede que no sea un gran problema para ti ahora mismo, pero esta diferenciaci\u00f3n ayuda a solucionar posibles problemas en tu esquema o cuando necesitas actualizar las estructuras del propio JSON.<\/span><\/p>\n<p><span style=\"font-weight: 400\">En<\/span><b> ?<\/b><span style=\"font-weight: 400\"> puede comprobar si un atributo existe, pero s\u00f3lo puede utilizarse con claves de nivel superior seg\u00fan la directiva <\/span><a href=\"https:\/\/www.postgresql.org\/docs\/9.5\/functions-json.html\"><span style=\"font-weight: 400\">docs<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<p><span style=\"font-weight: 400\">En N1QL ya existe una sintaxis adecuada para este escenario:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">Select * from\u00a0 `test` where randomAttributeName is missing<\/pre>\n<p><span style=\"font-weight: 400\">Adem\u00e1s, tambi\u00e9n hay una sintaxis-az\u00facar para comprobar si el atributo existe (igual que \"is not missing\"):<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">Select * from\u00a0 `test` where randomAttributeName exists<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">\u00cdndices\u00a0<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Las bases de datos que permiten almacenar datos como JSON no suelen imponer ning\u00fan tipo de esquema, pero existe un problema inherente cuando se a\u00f1ade soporte flexible de esquemas: Por defecto, no sabes de antemano qu\u00e9 documentos tienen los atributos que est\u00e1s consultando.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Este problema se puede solucionar r\u00e1pidamente con la creaci\u00f3n de \u00edndices adecuados, ya que se puede reducir significativamente el n\u00famero de documentos escaneados y ordenarlos de alguna manera para que sea m\u00e1s f\u00e1cil encontrar el valor de destino. Sin embargo, al tratarse de JSON, los \u00edndices tambi\u00e9n tienen que lidiar con entidades anidadas y matrices, lo que a\u00f1ade un importante nivel extra de complejidad.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Naturalmente, crear el \u00edndice adecuado para una consulta tambi\u00e9n es una tarea que requiere cierta reflexi\u00f3n. De hecho, ~15% de las preguntas en los foros de Couchbase son exactamente sobre esto. Couchbase 6.5 vendr\u00e1 incluso con un Recomendador de Indexadores que sugerir\u00e1 un \u00edndice de acuerdo a una consulta dada:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-7356\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p5-1024x559.png\" alt=\"\" width=\"900\" height=\"491\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5-1024x559.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5-300x164.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5-768x419.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5-20x11.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5.png 1300w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Los \u00edndices para datos JSONB son una de las nuevas caracter\u00edsticas de Postgres, los desarrolladores est\u00e1n realmente entusiasmados con ella ya que el rendimiento de las consultas aumentar\u00e1 significativamente en comparaci\u00f3n con las versiones anteriores.  Seg\u00fan la documentaci\u00f3n principal, Postgres soporta dos tipos de \u00edndices: el \u00edndice por defecto y el \u00edndice por defecto. <\/span><b>jsonb_path_ops<\/b><span style=\"font-weight: 400\">:<\/span><\/p>\n<p><b>Por defecto<\/b><\/p>\n<pre class=\"lang:pgsql decode:true\">CREATE INDEX idxusersall ON users USING GIN (address);<\/pre>\n<p><span style=\"font-weight: 400\">Este \u00edndice permite utilizar consultas con los operadores de nivel superior de existencia de clave ?, ?&amp; y ?| y el operador de existencia de ruta\/valor @&gt; . <\/span><span style=\"font-weight: 400\">Adem\u00e1s, tambi\u00e9n puede indexar un campo espec\u00edfico:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">CREATE INDEX idxusers ON users USING GIN ((address -&gt; 'entrances'));<\/pre>\n<p><span style=\"font-weight: 400\">Para el \u00edndice GIN, s\u00f3lo puede especificar un \u00fanico campo.<\/span><\/p>\n<p><b>jsonb_path_ops<\/b><\/p>\n<pre class=\"lang:pgsql decode:true\">CREATE INDEX idxginp ON api USING GIN (jdoc jsonb_path_ops);<\/pre>\n<p><span style=\"font-weight: 400\">La clase de operador GIN no predeterminada jsonb_path_ops s\u00f3lo admite la indexaci\u00f3n del operador @&gt;. Normalmente resultar\u00e1 en un \u00edndice m\u00e1s r\u00e1pido y m\u00e1s peque\u00f1o. Puede <\/span><a href=\"https:\/\/www.postgresql.org\/docs\/current\/datatype-json.html#JSON-INDEXING\"><span style=\"font-weight: 400\">m\u00e1s informaci\u00f3n aqu\u00ed<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<h4><strong>Actualizaci\u00f3n del art\u00edculo:\u00a0<\/strong><\/h4>\n<p>Mark (que coment\u00f3 aqu\u00ed en este art\u00edculo) y @postgresmen en twitter destacaron que se pueden crear \u00edndices con m\u00faltiples campos utilizando BTrees o GIST:<\/p>\n<pre class=\"lang:pgsql decode:true\">\/\/ for a JSONB collumn called \"data\" with the following content:\r\n\/\/ {\"a\": %s, \"b\":2, \"c\":1, \"d\":3}\r\ncreate index t1_l2 on users using btree((address-&gt;&gt;'a'), (address-&gt;&gt;'b'), (address-&gt;&gt;'c'));<\/pre>\n<p>A continuaci\u00f3n, puede utilizar el \u00edndice anterior con la siguiente consulta:<\/p>\n<pre class=\"lang:pgsql decode:true\">select from t1 where address-&gt;&gt;'a' = 1::text<\/pre>\n<p>Tambi\u00e9n puede utilizar \u00edndices parciales con la sintaxis anterior:<\/p>\n<pre class=\"lang:pgsql decode:true\">create index t1_l3 on users using btree((address-&gt;&gt;'a'), (address-&gt;&gt;'b'), (address-&gt;&gt;'c')) \r\nwhere address-&gt;'state' = '\"CA\"';<\/pre>\n<p><span style=\"font-weight: 400\">En <\/span><a href=\"https:\/\/www.postgresql.org\/files\/documentation\/pdf\/11\/postgresql-11-US.pdf\"><span style=\"font-weight: 400\">la documentaci\u00f3n oficial s\u00f3lo tiene 2 p\u00e1ginas sobre c\u00f3mo indexar campos JSONB,<\/span><\/a><span style=\"font-weight: 400\"> S\u00f3lo despu\u00e9s de que Mark\/@postgresmen me informara pude averiguar c\u00f3mo crear ciertos tipos de \u00edndices. Indexaci\u00f3n JSONB <\/span><span style=\"font-weight: 400\">debe recibir <a href=\"https:\/\/www.youtube.com\/watch?v=VyjrEhr6RsU\">actualizaciones interesantes en las pr\u00f3ximas versiones de Postgres<\/a>.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Los \u00edndices son en realidad el n\u00facleo de Couchbase, actualmente soportamos 7 tipos diferentes:<\/span><\/p>\n<ul>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/createprimaryindex.html\"><b>Principal<\/b><\/a><b> &#8211;<\/b><span style=\"font-weight: 400\"> Indexa todo el bucket en la clave del documento<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/6.0\/learn\/services-and-indexes\/indexes\/global-secondary-indexes.html\"><b>Secundaria<\/b><\/a><b> &#8211; <\/b><span style=\"font-weight: 400\">Indexa un escalar, objeto o matriz utilizando una clave-valor<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/covering-indexes.html\"><b>Compuesto\/Cubierto<\/b><\/a><b> &#8211; <\/b><span style=\"font-weight: 400\">M\u00faltiples campos almacenados en un \u00edndice<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/services-and-indexes\/indexes\/indexing-and-query-perf.html#functional-index\"><b>Funcional<\/b><\/a><b> &#8211; <\/b><span style=\"font-weight: 400\">\u00cdndice secundario que permite expresiones funcionales en lugar de una simple clave-valor<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/services-and-indexes\/indexes\/indexing-and-query-perf.html#array-index\"><b>Matriz<\/b><\/a><b> &#8211; <\/b><span style=\"font-weight: 400\">Un \u00edndice de elementos de matriz que van desde valores escalares simples hasta matrices complejas u objetos JSON anidados a mayor profundidad en la matriz.<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/adaptive-indexing.html\"><b>Adaptativo<\/b><\/a><b> &#8211;<\/b><span style=\"font-weight: 400\"> \u00cdndice de matriz secundario para todos o algunos campos de un documento sin tener que definirlos de antemano.<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/services-and-indexes\/indexes\/indexing-and-query-perf.html#partial-index\"><b>\u00cdndice parcial -<\/b><\/a> <span style=\"font-weight: 400\">Permite indexar s\u00f3lo un subconjunto de datos<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">Como puedes ver, los \u00edndices son algo bastante maduro en Couchbase y mucho m\u00e1s flexibles que los soportados por Postgres JSONB. No voy a profundizar en ello porque este art\u00edculo ya es bastante largo, s\u00f3lo me gustar\u00eda destacar dos cosas que personalmente creo que son realmente geniales: \u00cdndices Parciales Cubiertos y Pushdowns Agregados.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h5><b>\u00cdndices parciales cubiertos\u00a0<\/b><\/h5>\n<p><span style=\"font-weight: 400\">Con una combinaci\u00f3n de Covered y Partial puedes crear \u00edndices s\u00f3lo para el subconjunto de datos que te interesa.\u00a0<\/span><\/p>\n<p><b>EX:<\/b><span style=\"font-weight: 400\"> Digamos que tienes un juego online y necesitas mostrar una tabla de clasificaci\u00f3n por pa\u00eds, tambi\u00e9n ignoras a los usuarios inactivos o con menos de 10 puntos. El rendimiento de tu tabla de clasificaci\u00f3n est\u00e1 bien para todos los pa\u00edses excepto para China, que tiene 10 veces m\u00e1s jugadores. En este caso, podr\u00edas crear un \u00edndice espec\u00edfico para mejorar la velocidad de tu consulta:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">CREATE INDEX `china_leader_board` ON\r\n`user_profiles`(\r\n   username,\r\n   points DESC)\r\nWHERE active = true\r\n   and countryCode = \"CN\" and points &gt; 10<\/pre>\n<p><span style=\"font-weight: 400\">Tenga en cuenta que ya mantenemos los puntos ordenados, por lo que una consulta como la siguiente deber\u00eda ser rapid\u00edsima:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">Select username, points from user_profiles where active = true\u00a0\u00a0\u00a0and countryCode = \"CN\" order by points DESC limit 20<\/pre>\n<p>&nbsp;<\/p>\n<h5><b>Flexiones agregadas<\/b><\/h5>\n<p><span style=\"font-weight: 400\">La agregaci\u00f3n es siempre una tarea dif\u00edcil para almacenamientos no columnares, en Couchbase te permitimos crear \u00edndices para hacer tu agregaci\u00f3n m\u00e1s r\u00e1pida. Pongamos el siguiente ejemplo:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">SELECT pa\u00eds, estado, ciudad, COUNT(1) AS total\r\nFROM `viajes-muestra\r\nWHERE type = 'hotel' and country is not null\r\nGROUP BY pa\u00eds, estado, ciudad\r\nORDER BY COUNT(1) DESC;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">Esta consulta tard\u00f3 ~90ms en ejecutarse, aqu\u00ed est\u00e1 el plan de consulta:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-7357\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p6-1024x159.png\" alt=\"\" width=\"900\" height=\"140\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6-1024x159.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6-300x47.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6-768x119.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6-20x3.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6.png 1300w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">Ahora, vamos a crear el siguiente \u00edndice:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">CREATE INDEX ix_hotelregions ON `travel-sample` (country, state, city) WHERE type='hotel';<\/pre>\n<p><span style=\"font-weight: 400\">Si volvemos a ejecutar la misma consulta, deber\u00eda ejecutarse en ~7ms, n\u00f3tese que en el nuevo plan de consulta no hay ning\u00fan paso de \"grupo\":<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-7358\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p7-1024x152.png\" alt=\"\" width=\"900\" height=\"134\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7-1024x152.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7-300x45.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7-768x114.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7-20x3.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7.png 1300w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Puede<\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/groupby-aggregate-performance.html\"><span style=\"font-weight: 400\"> m\u00e1s informaci\u00f3n sobre los \u00edndices de Couchbase\u00a0<\/span><\/a><\/p>\n<p><b>Nota<\/b><span style=\"font-weight: 400\">travel-sample es una de las bases de datos de demostraci\u00f3n que puede cargar al instalar Couchbase<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><b>Rendimiento<\/b><\/h2>\n<p><span style=\"font-weight: 400\">Aunque ambas bases de datos se consideran CP (Consistent\/Partition Tolerant), Postgres es un RDBMS Maestro\/Esclavo tradicional, mientras que Couchbase est\u00e1 optimizado para lecturas\/escrituras r\u00e1pidas a escala y soporte adicional para <\/span><a href=\"https:\/\/jepsen.io\/consistency\/models\/monotonic-atomic-view\"><span style=\"font-weight: 400\">Vistas at\u00f3micas mon\u00f3tonas<\/span><\/a><\/p>\n<p><span style=\"font-weight: 400\">Desafortunadamente, s\u00f3lo hay unos pocos benchmarks de JSONB publicados en l\u00ednea, y en los m\u00e1s recientes Postgres ha sido<\/span><a href=\"https:\/\/www.youtube.com\/watch?v=4c-Q_rEZ9K8&amp;feature=youtu.be\"><span style=\"font-weight: 400\"> m\u00e1s r\u00e1pido que Mongo para una instancia de nodo \u00fanico<\/span><\/a><span style=\"font-weight: 400\"> (<\/span><a href=\"https:\/\/www.postgresql.eu\/events\/fosdem2018\/sessions\/session\/1691\/slides\/63\/High-Performance%20JSON_%20PostgreSQL%20Vs.%20MongoDB.pdf\"><span style=\"font-weight: 400\">aqu\u00ed tambi\u00e9n<\/span><\/a><span style=\"font-weight: 400\">). Los resultados son bastante impresionantes, pero vale la pena destacar que la mayor\u00eda de esas comparaciones se hicieron contra s\u00f3lo uno o dos nodos, que es un escenario que favorece a RDBMS en general.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">No quiero hacer hincapi\u00e9 en la arquitectura de Couchbase aqu\u00ed, pero como una base de datos de memoria primero, su aplicaci\u00f3n recibe el acuse de recibo de una escritura exitosa tan pronto como la base de datos recibe la solicitud, y luego su documento se replica de forma as\u00edncrona y se escribe en el disco (s\u00ed, tambi\u00e9n puede cambiar cuando desea recibir el acuse de recibo).\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Si adem\u00e1s a\u00f1adimos que Couchbase tiene una arquitectura sin maestros (tu aplicaci\u00f3n env\u00eda las escrituras\/lecturas directamente al servidor adecuado), un soporte de indexaci\u00f3n mucho mejor, y la alta escalabilidad (hay clientes que ejecutan clusters CB individuales en producci\u00f3n con +100 nodos), para m\u00ed est\u00e1 claro cu\u00e1l tendr\u00e1 un mejor rendimiento a escala, la cuesti\u00f3n es s\u00f3lo \"cu\u00e1nto\".<\/span><\/p>\n<p><span style=\"font-weight: 400\">Todav\u00eda no hay un benchmark Postgres vs Couchbase, si quieres ver uno, env\u00edame un tweet a <\/span><a href=\"https:\/\/twitter.com\/deniswsrosa\"><span style=\"font-weight: 400\">@deniswsrosa<\/span><\/a><span style=\"font-weight: 400\">. Mientras tanto, puede comparar indirectamente el rendimiento de ambos utilizando este m\u00e9todo <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/es\/benchmarks\/\"><span style=\"font-weight: 400\">Punto de referencia de Couchbase\/Mongo\/Cassandra<\/span><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">Conclusi\u00f3n<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Estoy realmente entusiasmado con el creciente soporte de JSON en Postgres, definitivamente har\u00e1 que los desarrolladores se familiaricen m\u00e1s con los beneficios de almacenar datos como JSON y, en consecuencia, har\u00e1 que las Bases de Datos de Documentos tambi\u00e9n sean m\u00e1s populares.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Muchas herramientas y marcos de trabajo del mercado ya ofrecen compatibilidad con datos JSON y, a medida que aumente la adopci\u00f3n de Postgres JSONB, deber\u00eda convertirse en una caracter\u00edstica est\u00e1ndar, lo que, una vez m\u00e1s, es positivo para todos los usuarios. <a href=\"https:\/\/www.couchbase.com\/blog\/es\/resources\/why-nosql\/\">Base de datos NoSQL<\/a>.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Sin embargo, hay que tener en cuenta algunas cosas antes de lanzarse al JSONB de Postgres:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><b>Lenguaje de consulta complejo: <\/b><span style=\"font-weight: 400\">el lenguaje de consulta actual para JSONB no es intuitivo, incluso despu\u00e9s de leer los documentos sigue siendo un poco complejo entender lo que est\u00e1 pasando en la consulta. PG 12 podr\u00eda resolver algunos de esos problemas con el <\/span><b>Lenguaje JSON Path<\/b><span style=\"font-weight: 400\">pero seguir\u00e1 pareciendo una mezcla de otro lenguaje con SQL. Preferir\u00eda que Postgres a\u00f1adiera soporte para SQL++.<\/span><\/li>\n<li style=\"font-weight: 400\"><b>Lenguaje de consulta limitado:<\/b><span style=\"font-weight: 400\"> Adem\u00e1s de ser complejo, el lenguaje de consulta a\u00fan no est\u00e1 disponible. Faltan funciones para manipular datos JSON, por ejemplo, tienes que utilizar algunas soluciones para hacer algunas manipulaciones b\u00e1sicas de matrices. Si tienes un JSON muy din\u00e1mico y necesitas consultarlo de m\u00faltiples maneras, las cosas pueden ponerse realmente dif\u00edciles. <\/span>Parece que el enfoque principal hasta ahora era construir el puente entre el JSON y los datos relacionales.<\/li>\n<li style=\"font-weight: 400\"><b>Indexaci\u00f3n:<\/b><span style=\"font-weight: 400\"> Con el nuevo tipo de \u00edndice, las consultas se ejecutar\u00e1n mucho m\u00e1s r\u00e1pido que antes. Adem\u00e1s, puede utilizar BTree y Gist para cubrir casos no admitidos por GIN.<\/span><\/li>\n<li><b>Documentaci\u00f3n superficial: <span style=\"font-weight: 400\">S\u00f3lo hay ~6 p\u00e1ginas de documentaci\u00f3n que hablan de JSONB. La mayor\u00eda de las cosas que aprend\u00ed mientras escrib\u00eda este art\u00edculo se basaron en prueba y error, preguntas de StackOverflow, entradas de blog y presentaciones de youtube y\u00a0<\/span><\/b><\/li>\n<li style=\"font-weight: 400\"><b>Herramientas<\/b><span style=\"font-weight: 400\">: No he mencionado esto durante el art\u00edculo, pero como es una caracter\u00edstica bastante nueva, naturalmente algunos frameworks\/SDKs no han a\u00f1adido soporte completo para todav\u00eda. Tomemos SpringData como un ejemplo, hay algunos <\/span><a href=\"https:\/\/stackoverflow.com\/questions\/51276703\/how-to-store-postgresql-jsonb-using-springboot-jpa\"><span style=\"font-weight: 400\">esfuerzos comunitarios<\/span><\/a><span style=\"font-weight: 400\"> pero no es una experiencia totalmente fluida. Cabe esperar algunos contratiempos por el camino.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">Algunos de los problemas anteriores son conocidos, incluso se mencionan en algunas charlas\/art\u00edculos enlazados en este art\u00edculo. Los m\u00e1s cr\u00edticos ya est\u00e1n en la hoja de ruta de las pr\u00f3ximas versiones de Postgres.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Contrariamente a la mayor\u00eda de las presentaciones populares que he visto, no creo que sea una buena opci\u00f3n para modelos muy din\u00e1micos, sobre todo porque la consulta y manipulaci\u00f3n de datos no es tan f\u00e1cil como podr\u00eda ser.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">\u00bfD\u00f3nde encaja Postgres JSONB?<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Aunque he se\u00f1alado algunos problemas desde mi punto de vista, creo que es una funci\u00f3n valiosa y que deber\u00edas plantearte utilizarla. He aqu\u00ed algunos escenarios en los que creo que es una buena opci\u00f3n:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">CQRS\/<a href=\"https:\/\/www.couchbase.com\/blog\/es\/event-sourcing-event-logging-an-essential-microservice-pattern\/\">Contrataci\u00f3n de eventos<\/a> sistemas que deben ser altamente transaccionales<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Metadatos<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Evitar uniones innecesarias almacenando algunas entidades relacionadas como JSONBs en su lugar.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Siempre que tengas que almacenar cadenas codificadas en JSON pero no necesites manipular o consultar los datos con demasiada frecuencia.<\/span><\/li>\n<\/ul>\n<p>En los casos anteriores, Postgres deber\u00eda funcionar bien, incluso para grandes despliegues. Los \u00edndices pueden ser un poco grandes con GIN, pero a\u00fan manejables.<\/p>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">\u00bfD\u00f3nde encaja bien Couchbase?<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Llevo m\u00e1s de 4 a\u00f1os trabajando con \u00e9xito con bases de datos documentales y, a estas alturas, puede que sea un poco parcial, pero creo que los escenarios en los que se puede utilizar como sustituto de un RDBMS son mucho m\u00e1s amplios de lo que cabr\u00eda esperar. Algunos de los casos de uso m\u00e1s conocidos son:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Almacenes de perfiles de usuario;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Cat\u00e1logos de productos\/Carros de la compra;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Historial m\u00e9dico (para HealthCare);<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Contratos, p\u00f3lizas de seguros;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Medios de comunicaci\u00f3n social;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Juegos de azar;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Cach\u00e9;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">&#8230;<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">De hecho, la mayor\u00eda de los sistemas que no requieren <\/span><a href=\"https:\/\/jepsen.io\/consistency\/models\/serializable\"><span style=\"font-weight: 400\">transacciones serializables fuertes<\/span><\/a><span style=\"font-weight: 400\"> entre m\u00faltiples documentos deber\u00eda ser un buen ajuste, eso no significa que las transacciones no est\u00e9n soportadas en absoluto, es s\u00f3lo una versi\u00f3n m\u00e1s relajada que no comprometer\u00e1 la escalabilidad de la base de datos, \u00a1especialmente con Couchbase 6.5!<\/span><\/p>\n<p><span style=\"font-weight: 400\">Couchbase CE y EE realmente brillan cuando necesitas rendimiento a escala. Puedes crear f\u00e1cilmente clusters con 3,5,10,50,100 nodos y a\u00fan as\u00ed mantener un buen rendimiento y una fuerte consistencia, por eso es actualmente una de las principales opciones para aplicaciones de misi\u00f3n cr\u00edtica. Si tienes tiempo echa un vistazo a algunas de las <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/es\/customers\/\"><span style=\"font-weight: 400\">casos de uso p\u00fablico<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Todos esos casos de uso cr\u00edticos a lo largo de los a\u00f1os hicieron que N1QL y la indexaci\u00f3n fueran muy s\u00f3lidos, r\u00e1pidos y flexibles. Es por eso que incluso lo considero una comparaci\u00f3n injusta dado el estado actual de Postgres JSONB, aunque es v\u00e1lido para mostrar a los desarrolladores las brechas entre una implementaci\u00f3n temprana frente al mejor soporte de JSON hasta el momento.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Si tiene alguna pregunta, comentario o est\u00e1 totalmente en desacuerdo conmigo, no dude en tuitearme en <a href=\"https:\/\/twitter.com\/deniswsrosa\">@deniswsrosa<\/a><\/span><\/p>","protected":false},"excerpt":{"rendered":"<p>The reality is that databases are converging, and in the last few years, it is becoming even more difficult to point what are the best scenarios for each datastore without a deep understanding of how things work under the hood.\u00a0 [&hellip;]<\/p>","protected":false},"author":8754,"featured_media":10650,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1812],"tags":[],"ppma_author":[9059],"class_list":["post-7351","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-n1ql-query"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Comparing Postgres JSONB With NoSQL Databases | Learn More<\/title>\n<meta name=\"description\" content=\"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/postgres-jsonb-and-nosql\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Comparing Postgres JSONB With NoSQL\" \/>\n<meta property=\"og:description\" content=\"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/postgres-jsonb-and-nosql\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-08-06T13:57:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-07-26T19:09:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/Couchbase-postgres_RESIZED.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2200\" \/>\n\t<meta property=\"og:image:height\" content=\"635\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Denis Rosa, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@deniswsrosa\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Denis Rosa, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\"},\"author\":{\"name\":\"Denis Rosa, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/fe3c5273e805e72a5294611a48f62257\"},\"headline\":\"Comparing Postgres JSONB With NoSQL\",\"datePublished\":\"2019-08-06T13:57:07+00:00\",\"dateModified\":\"2023-07-26T19:09:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\"},\"wordCount\":3371,\"commentCount\":5,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png\",\"articleSection\":[\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\",\"name\":\"Comparing Postgres JSONB With NoSQL Databases | Learn More\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png\",\"datePublished\":\"2019-08-06T13:57:07+00:00\",\"dateModified\":\"2023-07-26T19:09:43+00:00\",\"description\":\"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png\",\"width\":2200,\"height\":635,\"caption\":\"Learn how to compare Postgres JSONB with a NoSQL database.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Comparing Postgres JSONB With NoSQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/fe3c5273e805e72a5294611a48f62257\",\"name\":\"Denis Rosa, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/be0716f6199cfb09417c92cf7a8fa8d6\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g\",\"caption\":\"Denis Rosa, Developer Advocate, Couchbase\"},\"description\":\"Denis Rosa is a Developer Advocate for Couchbase and lives in Munich - Germany. He has a solid experience as a software engineer and speaks fluently Java, Python, Scala and Javascript. Denis likes to write about search, Big Data, AI, Microservices and everything else that would help developers to make a beautiful, faster, stable and scalable app.\",\"sameAs\":[\"https:\/\/x.com\/deniswsrosa\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/denis-rosa\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Comparing Postgres JSONB With NoSQL Databases | Learn More","description":"Aprende los diferentes casos de uso para cuando usar Postgres 11 con JSONB y cuando usar una base de datos NoSQL como Couchbase. Empieza a aprender con Couchbase hoy mismo.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/postgres-jsonb-and-nosql\/","og_locale":"es_MX","og_type":"article","og_title":"Comparing Postgres JSONB With NoSQL","og_description":"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.","og_url":"https:\/\/www.couchbase.com\/blog\/es\/postgres-jsonb-and-nosql\/","og_site_name":"The Couchbase Blog","article_published_time":"2019-08-06T13:57:07+00:00","article_modified_time":"2023-07-26T19:09:43+00:00","og_image":[{"width":2200,"height":635,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/Couchbase-postgres_RESIZED.png","type":"image\/png"}],"author":"Denis Rosa, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@deniswsrosa","twitter_misc":{"Written by":"Denis Rosa, Developer Advocate, Couchbase","Est. reading time":"16 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/"},"author":{"name":"Denis Rosa, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/fe3c5273e805e72a5294611a48f62257"},"headline":"Comparing Postgres JSONB With NoSQL","datePublished":"2019-08-06T13:57:07+00:00","dateModified":"2023-07-26T19:09:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/"},"wordCount":3371,"commentCount":5,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png","articleSection":["SQL++ \/ N1QL Query"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/","url":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/","name":"Comparing Postgres JSONB With NoSQL Databases | Learn More","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png","datePublished":"2019-08-06T13:57:07+00:00","dateModified":"2023-07-26T19:09:43+00:00","description":"Aprende los diferentes casos de uso para cuando usar Postgres 11 con JSONB y cuando usar una base de datos NoSQL como Couchbase. Empieza a aprender con Couchbase hoy mismo.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png","width":2200,"height":635,"caption":"Learn how to compare Postgres JSONB with a NoSQL database."},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Comparing Postgres JSONB With NoSQL"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/fe3c5273e805e72a5294611a48f62257","name":"Denis Rosa, Defensor del Desarrollador, Couchbase","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/be0716f6199cfb09417c92cf7a8fa8d6","url":"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g","caption":"Denis Rosa, Developer Advocate, Couchbase"},"description":"Denis Rosa es un Developer Advocate para Couchbase y vive en Munich - Alemania. Tiene una s\u00f3lida experiencia como ingeniero de software y habla con fluidez Java, Python, Scala y Javascript. A Denis le gusta escribir sobre b\u00fasqueda, Big Data, AI, Microservicios y todo lo que pueda ayudar a los desarrolladores a hacer una aplicaci\u00f3n hermosa, m\u00e1s r\u00e1pida, estable y escalable.","sameAs":["https:\/\/x.com\/deniswsrosa"],"url":"https:\/\/www.couchbase.com\/blog\/es\/author\/denis-rosa\/"}]}},"authors":[{"term_id":9059,"user_id":8754,"is_guest":0,"slug":"denis-rosa","display_name":"Denis Rosa, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g","author_category":"","last_name":"Rosa, Developer Advocate, Couchbase","first_name":"Denis","job_title":"","user_url":"","description":"Denis Rosa es un Developer Advocate para Couchbase y vive en Munich - Alemania. Tiene una s\u00f3lida experiencia como ingeniero de software y habla con fluidez Java, Python, Scala y Javascript. A Denis le gusta escribir sobre b\u00fasqueda, Big Data, AI, Microservicios y todo lo que pueda ayudar a los desarrolladores a hacer una aplicaci\u00f3n hermosa, m\u00e1s r\u00e1pida, estable y escalable."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/7351","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/8754"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=7351"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/7351\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/10650"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=7351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=7351"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=7351"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=7351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}