Relaciones de entidad
Las consultas de GraphQL pueden atravesar objetos relacionados y sus campos, para que con una sola consulta pueda escribir algo parecido a:
{
books
{
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
Para recuperar libros y sus autores.
Para permitir que esta capacidad funcione, Data API Builder debe saber cómo se relacionan los dos objetos entre sí. La relationships
sección del archivo de configuración proporciona los metadatos necesarios para que esta capacidad funcione correctamente y de forma eficaz.
Configuración de una relación
Independientemente de la base de datos que use con data API Builder, debe indicar explícitamente a Data API Builder que un objeto está relacionado con otro. Hay tres tipos de relaciones que se pueden establecer entre dos entidades:
Relación uno a varios
Una relación uno a varios permite que un objeto tenga acceso a una lista de objetos relacionados. Por ejemplo, una serie de libros puede permitir el acceso a todos los libros de esa serie:
{
series {
items {
name
books {
items {
title
}
}
}
}
}
Si hay claves externas que admiten la relación entre los dos objetos de base de datos subyacentes, solo es necesario indicar al generador de Data API que desea exponer dicha relación. Con la CLI de DAB:
dab update Series --relationship books --target.entity Book --cardinality many
Que actualiza la series
entidad , que se usa en el ejemplo:
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"target.entity": "Book",
"cardinality": "many"
}
}
...
}
Se agrega una nueva clave en el relationships
elemento : books
. El elemento define el nombre que se usa para el campo GraphQL para navegar desde el series
objeto al objeto definido en target.entity
, Book
en este caso. Esto significa que debe haber una entidad denominada Book
en el archivo de configuración.
La cardinality
propiedad indica al generador de Data API que puede haber muchos libros en cada serie, por lo que el campo GraphQL creado devuelve una lista de elementos.
Esa propiedad es todo lo que necesita. Al iniciarse, El generador de API de datos detecta automáticamente los campos de base de datos que se deben usar para mantener la relación definida.
Si no tiene una restricción de clave externa que mantenga la relación de base de datos, Data API Builder no puede averiguar automáticamente qué campos se usan. Para indicar a Data API Builder qué campos relacionan las dos entidades, debe especificarlas manualmente. Puede especificarlos con la CLI mediante dab update
:
dab update Series --relationship books --target.entity Book --cardinality many --relationship.fields "id:series_id"
La opción relationship.fields
permite definir qué campos se usan desde la entidad que se actualiza (Series
) y qué campos se usan desde la entidad de destino (Book
), para conectar los datos de una entidad a la otra.
En el ejemplo anterior, el id
campo de base de datos de la Series
entidad coincide con el campo series_id
de base de datos de la Book
entidad.
La configuración también contiene esta información:
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"cardinality": "many",
"target.entity": "Book",
"source.fields": ["id"],
"target.fields": ["series_id"]
}
}
...
}
Relación de varios a uno
Una relación de varios a uno es similar a la relación uno a varios con dos diferencias principales:
- se
cardinality
establece en .one
- el campo GraphQL creado devuelve un valor escalar que no es una lista.
Siguiendo los ejemplos de la Serie de libros usados antes, un libro puede estar en una sola serie, por lo que la relación se crea mediante el siguiente comando de la CLI de DAB:
dab update Book --relationship series --target.entity Series --cardinality one
Que genera esta configuración:
"Book": {
"source": "dbo.books",
...
"relationships": {
"series": {
"target.entity": "Series",
"cardinality": "one"
}
}
}
A su vez, permite una consulta graphQL como en este ejemplo:
{
books {
items {
id
title
series {
name
}
}
}
}
Donde cada libro devuelve también la serie a la que pertenece.
Relación de varios a varios
Muchas a muchas relaciones se pueden ver como un par de relaciones uno a varios y de varios a uno que funcionan conjuntamente. Un autor puede escribir más de un libro (una relación uno a varios), pero también es cierto que más de un autor puede trabajar en el mismo libro (una relación de varios a uno).
Data API Builder admite este tipo de relación de forma nativa:
- Usar un par de relaciones uno a varios/varios a uno.
- Uso de un objeto de vinculación.
Usar un par de relaciones uno a varios/varios a uno
Un requisito empresarial que es probable que exista para realizar un seguimiento de cómo se dividen las regalías entre los autores de un libro. Para implementar este requisito se necesita una entidad dedicada que vincule un autor, un libro y las regalías asignadas. Por lo tanto, se necesitan tres entidades:
authors
, para representar los detalles biográficos de los autores.books
, para representar datos de libros como título y número de libro estándar internacional (ISBN).books_authors
para representar datos relacionados tanto con un libro como con su autor, por ejemplo, el porcentaje de regalías que obtiene un autor para un libro específico.
Las tres entidades se pueden visualizar mediante el diagrama siguiente.
Como se ve, hay dos relaciones bidireccionales:
- Relación uno a varios/varios a uno entre
authors
ybooks_authors
- Relación uno a varios/varios a uno entre
books
ybooks_authors
Para controlar este escenario correctamente con DAB, todo lo que se necesita es crear las entidades y asignaciones relacionadas en el archivo de configuración. Suponiendo que la Book
entidad y Author
ya están en el archivo de configuración:
dab add BookAuthor --source dbo.books_authors --permissions "anonymous:*"
Para agregar la nueva entidad, ejecute dab update
:
dab update Book --relationship authors --target.entity BookAuthor --cardinality many --relationship.fields "id:book_id"
dab update Author --relationship books --target.entity BookAuthor --cardinality many --relationship.fields "id:author_id"
Para agregar las relaciones a la entidad recién creada BookAuthor
, vuelva a ejecutar dab update
:
dab update BookAuthor --relationship book --target.entity Book --cardinality one --relationship.fields "book_id:id"
dab update BookAuthor --relationship author --target.entity Author --cardinality one --relationship.fields "author_id:id"
Para agregar las relaciones de BookAuthor
a Book
y Author
entidades. Con el DAB de configuración proporcionado puede controlar consultas anidadas como en este ejemplo:
{
authors {
items {
first_name
last_name
books {
items {
book {
id
title
}
royalties_percentage
}
}
}
}
}
Donde está pidiendo que devuelva todos los autores, el libro que escribieron junto con las regalías relacionadas.
Uso de un objeto de vinculación
El proceso descrito en la sección anterior funciona perfectamente si es necesario acceder a todas las entidades implicadas en las relaciones de varios a varios a través de GraphQL. Este escenario no siempre es el caso. Por ejemplo, si no necesita realizar un seguimiento de regalías, la BookAuthor
entidad no aporta ningún valor al usuario final. La entidad solo se usó para asociar libros a sus autores. En las bases de datos relacionales se crean relaciones de varios a varios mediante esta tercera tabla que vincula las tablas que participan en la relación de varios a varios:
En el diagrama, puede ver que hay una tabla denominada books_authors
que vincula autores con sus libros y libros con sus autores. Esta tabla de vinculación no es necesario exponerla al usuario final. La tabla de vinculación es solo un artefacto para permitir que exista la relación de varios a varios, pero el generador de Data API debe conocer su existencia para poder usarlo correctamente.
La CLI de DAB se puede usar para crear la relación De varios a varios y configurar también el objeto de vinculación (asegúrese de quitar todas las relaciones creadas en la sección anterior y empezar solo con la Book
entidad y Author
sin ninguna relación configurada entre ellos):
dab update Book --relationship authors --target.entity Author --cardinality many --relationship.fields "id:id" --linking.object "dbo.books_authors" --linking.source.fields "book_id" --linking.target.fields "author_id"
Que actualiza el archivo de configuración JSON para que sea similar a este ejemplo:
"Book": {
"source": "dbo.books",
...
"relationships": {
"authors": {
"cardinality": "many",
"target.entity": "author",
"source.fields": [ "id" ],
"target.fields": [ "id" ],
"linking.object": "dbo.books_authors",
"linking.source.fields": [ "book_id" ],
"linking.target.fields": [ "author_id" ]
}
}
}
La configuración indica a DAB que desea agregar un authors
campo en la Book
entidad que permita el acceso a los autores del libro. authors
puede ser many
, por lo que se devuelve una lista de autores cuando la consulta graphQL accede al authors
campo. Esta relación define cómo navegar desde libros a autores: los campos de base de datos usados para navegar desde libros a sus autores se definen en para source.fields
el libro y en para target.fields
los autores, de forma similar a la relación uno a varios o varios a uno descrita anteriormente en este artículo.
Esta relación es una relación de varios a varios, por lo que no hay ninguna conexión directa entre las dos entidades, por lo que linking.object
es necesario usar . En el ejemplo, la tabla dbo.books_authors
de base de datos se usa como objeto de vinculación. La forma en que el objeto de vinculación puede conectar libros a sus autores se define en las linking.source.fields
propiedades y linking.target.fields
. La primera indica a DAB cómo se conecta la entidad de origen ( ) Book
al objeto que le gusta, y la segunda cómo está conectado el objeto de vinculación a la entidad de destino, Author
en el ejemplo.
Para comprender cómo se usa la información proporcionada, puede usar esta consulta equivalente de ejemplo:
select *
from dbo.books as b
inner join dbo.books_authors as ba on b.id = ba.book_id
inner join dbo.authors a on ba.author_id = a.id
Con el DAB de configuración proporcionado puede comprender GraphQL como en este ejemplo:
{
books {
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
Dónde quieres obtener libros y sus autores.
Para permitir la navegación desde Author
a Book
, se pueden aplicar los mismos principios, actualizando la configuración mediante el siguiente comando:
dab update Author --relationship books --target.entity Book --cardinality many --relationship.fields "id:id" --linking.object "dbo.books_authors" --linking.source.fields "author_id" --linking.target.fields "book_id"
Que define una relación de varios a varios entre la Author
entidad y la Book
entidad, mediante el objeto dbo.books_authors
de vinculación en segundo plano.