Bases de datos NoSQL y GraphQL

Bases de datos NoSQL y GraphQL: la falta de coincidencia de tipos. Es un problema importante que se debe abordar para que GraphQL alcance todo su potencial. Los sistemas sin tipo, como las bases de datos NoSQL, JSON, JavaScript y Python, han ganado popularidad y son muy útiles en la práctica porque los datos del mundo no se ajustan bien a una estructura rígida y consistente.

Bases de datos GraphQL y NoSQL

Incluso si lo hiciera, es casi imposible capturar todas las facetas de los datos y predecir el uso futuro de estos datos. Sin embargo, los datos tampoco son completamente sin esquema, y cualquier aplicación que use los datos aplicará un esquema bien definido.

Los opositores de NoSQL se quejan de que esta popularidad con NoSQL revierte el desarrollo de aplicaciones a los días de la base de datos jerárquica de los años 60, ignorando la realidad de que los datos en estos sistemas sin tipos, de hecho, tienen una estructura consistente y que su esquema está bien diseñado y evoluciona con los procesos de desarrollo de aplicaciones.

Con la llegada de GraphQL, podemos introducir un sistema de tipos sobre estos sistemas sin quitarle la flexibilidad que introdujeron, devolviendo el orden a lo que parece ser un desorden.

Bases de datos NoSQL y GraphQL: la falta de coincidencia de tipos

Analicemos esto utilizando una de las más populares bases de datos NoSQL: MongoDB.

Supongamos que tenemos un esquema GraphQL para datos que representan a un cliente:

type Customer {
   id: ID!
   name: String!
   email: String
   age: Int
   joined: Date!
}

Este esquema dice que un cliente tiene cinco atributos y cada uno debe ser del tipo que se muestra. La presencia de «!» en GraphQL indica que el campo no admite valores NULL, similar a NOT NULL en SQL.

Ahora suponga que su colección MongoDB contiene los siguientes tres documentos de estilo JSON:

 [
    {
       “id”: “12345”,
       “name”: “John Doe”,
       “email”: “[email protected]”,
       “age”: 20,
       “joined”: “2021-01-10”,
       “children”: [“John”, “Mary”]
    },
    {
       “id”: “23456”,
       “name”: “Jane Doe”,
       “email”: “[email protected]”,
       “age”: 30,
       “joined”: “2020-01-10”,
       “hobbies”: [“surfing”, “reading”]
    },
    {
       “id”: “34567”,
       “name”: “John Smith”,
       “email”: “[email protected]”,
       “age”: 40.1
       “offices”: [“StepZen”]
    }
]

Como puede ver, los datos tienen una estructura bastante consistente con algunas excepciones. Las obvias son que cada documento tiene características diferenciadoras:

  • John Doe tiene hijos
  • Jane Doe tiene pasatiempos
  • John Smith tiene oficinas
  • La propiedad «joined» parece ser común, pero en una inspección más cercana, vemos que a uno de los documentos le falta este campo.
  • Si solo consideráramos al Sr. y la Sra. Doe, podríamos pensar que la edad podría representarse como un número entero, pero la edad del Sr. Smith claramente no es un número entero.

¿Cómo encajarían estos datos en nuestro modelo GraphQL? Hay problemas obvios:

  1. El campo «joined» no se puede configurar para que sea ! ya que en el último documento, falta. Fácil arreglo, ¿verdad? Conviértalo en «Date» en lugar de «Date!». Pero, ¿y si, de los millones de documentos, este es el único registro que no parece tener ningún valor para unir? Con esta perspectiva aumentada, eliminando el ! ahora parece una mala idea ya que esta anomalía podría representar datos incorrectos.
  2. Los documentos parecen tener diferentes campos adicionales. Este es un patrón bastante común, incluso cuando los datos se encuentran en sistemas estrictamente tipificados, como los sistemas de administración de bases de datos relacionales, razón por la cual se introdujeron BLOBS (Objetos binarios grandes), XML y JSON. Con GraphQL, podríamos hacer algo como:
    type Customer {
    ...
       children: [String!]
       hobbies: [String!]
       office: [String!]
    }

    asegurándose de que los tres registros se puedan mapear. ¡Tenga en cuenta que los campos niños, pasatiempos y oficina no tienen ! después de ellos, indicando que son opcionales. (El descriptor String! de la lista significa que un elemento de la lista no puede ser nulo). Sin embargo, esto también parece subóptimo; después de todo, podemos obtener cientos de estos campos en millones de registros y eso conduce a una lógica de aplicación excesiva. Le mostraremos una mejor manera a continuación.

  3. Nuestro esquema GraphQL asume el tipo INT para la edad, que funciona para el Sr. y la Sra. Doe pero no es compatible con la edad del Sr. Smith, que se manejaría mejor con el tipo FLOAT, a menos que se encasille a un INT.

Estos son solo algunos ejemplos simples que ilustran estos problemas de matrimonio entre tipos fuertes (GraphQL) y tipos débiles (en este caso, JSON).

Sin embargo, se pueden encontrar algunas soluciones excelentes utilizando GraphQL para estos y otros problemas.

  1. Un tipo de GraphQL puede ser JSON. Eso significa que si bien los datos dentro de ese JSON son opacos para GraphQL, cualquier dato que tenga la forma de JSON se puede asignar a ese campo, preservando la flexibilidad de tipo del sistema sin tipo subyacente. Por ejemplo, si hubiera un campo:
    type Customer {
    ...
       extras: JSON
    }

    entonces todos los registros podrían pasar a través de la capa GraphQL.

  2. Un tipo GraphQL puede ser un tipo UNION. Entonces podríamos declarar:
    union Extra =Hobbies | Children | Offices
    type Customer {
    ...
       extras: [Extra!]
    }

    y esto mantiene la representación compacta. Además, los registros siguen fuertemente tipados, excepto los extras de campo, que pueden ser uno o más de los tres tipos. También podemos usar un fragmento con una condición de tipo para capturar el diseño específico del tipo Extra:

    {
       customers (id: “12345”) {
          name
          extras: {
             __typeName
             … on hobbies {
                level
             }
             … on children {
                name
             }
             … on offices {
                location
             }
          }
       }
    }

     

En lo anterior, la consulta de GraphQL dice explícitamente: «Si un elemento de extras es del tipo pasatiempos, devuelve el nivel, etc.» Esto permite que la API de GraphQL haga lo correcto para devolver los datos en la forma correcta, eliminando la carga de la aplicación.

En todo lo anterior, el desarrollador de la API de GraphQL está tomando algunas decisiones explícitas sobre qué tipos quiere que coincidan aproximadamente con los tipos de los backends. ¿Y si tuviéramos el problema inverso? ¿Qué pasaría si inspeccionáramos el backend y derivamos automáticamente los tipos GraphQL de los datos subyacentes?

Para tal sistema:

  1. Muestra suficientes registros para ver la diversidad. MongoDB tiene un hallazgo donde puede recuperar múltiples registros. Las API REST pueden tener modelos de paginación. Los sistemas SQL tienen límites y compensaciones. De cualquier manera, una docena de registros es una buena muestra.
  2. Tome algunas decisiones sensatas. Como se mencionó anteriormente, los datos en estos sistemas no son completamente sin esquema; contienen algún esquema claro. Encuentre las subestructuras comunes más grandes y declare las poco comunes como UNION o JSON.
  3. Elija los tipos correctos y, en caso de duda, elimine el !

Conclusión

El problema de las discrepancias de tipos es un problema importante que se debe abordar para que GraphQL finalmente alcance su potencial.

Sin embargo, como lenguaje, tiene muchas características que hacen que el problema de la falta de coincidencia sea menos grave. Y herramientas como JSON2SDL hacen que el trabajo sea cada vez más automático.

El desajuste de paradigma entre una base de datos NoSQL como MongoDB y GraphQL se puede solventar con relativa facilidad tal y como hemos visto y eso, también, es cierto para otras tecnologías como REST y SQL. Todos los signos apuntan a que GraphQL se está convirtiendo en la capa de API fuertemente tipada predeterminada para acceder a todo tipo de backends.


Espero que el artículo «Bases de datos NoSQL y GraphQL» te haya sido de ayuda ❤️

Compartir:

Deja un comentario