Compartir a través de


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.

Diagrama que muestra la relación de varios a varios entre autores, books_authors y libros.

Como se ve, hay dos relaciones bidireccionales:

  • Relación uno a varios/varios a uno entre authors y books_authors
  • Relación uno a varios/varios a uno entre books y books_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:

Diagrama que muestra otra relación de varios a varios entre autores, books_authors y libros.

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.