Relations d’entité
GraphQL requêtes peuvent parcourir des objets connexes et leurs champs, de sorte qu’avec une seule requête, vous pouvez écrire quelque chose comme :
{
books
{
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
Pour récupérer des livres et leurs auteurs.
Pour permettre à cette capacité de fonctionner, le générateur d’API de données doit savoir comment les deux objets sont liés l’un à l’autre. La relationships
section du fichier de configuration fournit les métadonnées nécessaires pour que cette capacité fonctionne correctement et efficacement.
Configuration d’une relation
Quelle que soit la base de données que vous utilisez avec le générateur d’API de données, vous devez indiquer explicitement au générateur d’API de données qu’un objet est lié à un autre. Il existe trois types de relations qui peuvent être établis entre deux entités :
Relation un-à-plusieurs
Une relation un-à-plusieurs permet à un objet d’accéder à une liste d’objets associés. Par exemple, une série de livres peut autoriser l’accès à tous les livres de cette série :
{
series {
items {
name
books {
items {
title
}
}
}
}
}
S’il existe des clés étrangères prenant en charge la relation entre les deux objets de base de données sous-jacents, vous devez simplement indiquer au générateur d’API de données que vous souhaitez exposer cette relation. Avec l’interface CLI DAB :
dab update Series --relationship books --target.entity Book --cardinality many
Qui met à jour l’entité series
- utilisée dans l’exemple :
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"target.entity": "Book",
"cardinality": "many"
}
}
...
}
Une nouvelle clé est ajoutée sous l’élément relationships
: books
. L’élément définit le nom utilisé pour le champ GraphQL pour naviguer de l’objet series
à l’objet défini dans , target.entity
Book
dans ce cas. Cela signifie qu’il doit y avoir une entité appelée Book
dans le fichier de configuration.
La cardinality
propriété indique au générateur d’API de données qu’il peut y avoir de nombreux livres dans chaque série, de sorte que le champ GraphQL créé retourne une liste d’éléments.
Cette propriété est tout ce dont vous avez besoin. Au démarrage, le générateur d’API de données détecte automatiquement les champs de base de données qui doivent être utilisés pour maintenir la relation définie.
Si vous n’avez pas de contrainte de clé étrangère qui soutient la relation de base de données, le générateur d’API de données ne peut pas déterminer automatiquement les champs utilisés. Pour indiquer au Générateur d’API de données quels champs relient les deux entités, vous devez les spécifier manuellement. Vous pouvez les spécifier avec l’interface CLI à l’aide de dab update
:
dab update Series --relationship books --target.entity Book --cardinality many --relationship.fields "id:series_id"
L’option relationship.fields
vous permet de définir les champs utilisés à partir de l’entité en cours de mise à jour (Series
) et les champs utilisés à partir de l’entité cible (Book
), pour connecter les données d’une entité à l’autre.
Dans l’exemple précédent, le id
champ de base de données de l’entité Series
est mis en correspondance avec le champ series_id
de base de données de l’entité Book
.
La configuration contient également les informations suivantes :
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"cardinality": "many",
"target.entity": "Book",
"source.fields": ["id"],
"target.fields": ["series_id"]
}
}
...
}
Relation plusieurs-à-un
Une relation plusieurs-à-un est similaire à la relation un-à-plusieurs avec deux différences majeures :
- est
cardinality
défini surone
- le champ GraphQL créé retourne un scalaire et non une liste
À la suite des exemples de séries de livres utilisés précédemment, un livre peut se trouver dans une seule série. La relation est donc créée à l’aide de la commande CLI DAB suivante :
dab update Book --relationship series --target.entity Series --cardinality one
Qui génère cette configuration :
"Book": {
"source": "dbo.books",
...
"relationships": {
"series": {
"target.entity": "Series",
"cardinality": "one"
}
}
}
Ce qui, à son tour, autorise une requête GraphQL comme dans cet exemple :
{
books {
items {
id
title
series {
name
}
}
}
}
Où chaque livre retourne également la série à laquelle il appartient.
Relation plusieurs-à-plusieurs
Les relations plusieurs à plusieurs peuvent être considérées comme une paire de relations un-à-plusieurs et plusieurs-à-un fonctionnant ensemble. Un auteur peut certainement écrire plusieurs livres (une relation un-à-plusieurs), mais il est également vrai que plusieurs auteurs peuvent travailler sur le même livre (une relation plusieurs-à-un).
Le générateur d’API de données prend en charge ce type de relation en mode natif :
- Utilisation d’une paire de relations un-à-plusieurs/plusieurs-à-un.
- Utilisation d’un objet de liaison.
Utilisation d’une paire de relations un-à-plusieurs/plusieurs-à-un
Une exigence commerciale qui est susceptible d’être là est de suivre la façon dont les redevances sont réparties entre les auteurs d’un livre. Pour implémenter une telle exigence, une entité dédiée qui lie un auteur, un livre et les redevances affectées sont nécessaires. Trois entités sont donc nécessaires :
authors
, pour représenter les détails biographiques des auteurs.books
, pour représenter des données de livre telles que le titre et le numéro isBN (International Standard Book Number).books_authors
pour représenter des données liées à la fois à un livre et à son auteur, par exemple, le pourcentage de redevances qu’un auteur obtient pour un livre spécifique.
Les trois entités peuvent être visualisées via le diagramme suivant.
Comme visible, il existe deux relations bidirectionnelles :
- Relation un-à-plusieurs/plusieurs-à-un entre
authors
etbooks_authors
- Relation un-à-plusieurs/plusieurs-à-un entre
books
etbooks_authors
Pour gérer correctement un tel scénario avec DAB, il suffit de créer les entités et les mappages associés dans le fichier de configuration. En supposant que l’entité Book
et se Author
trouve déjà dans le fichier de configuration :
dab add BookAuthor --source dbo.books_authors --permissions "anonymous:*"
Pour ajouter la nouvelle entité, exécutez 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"
Pour ajouter les relations à l’entité nouvellement créée BookAuthor
, exécutez dab update
à nouveau :
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"
Pour ajouter les relations de BookAuthor
à Book
des entités et Author
. Avec la configuration fournie, DAB est en mesure de gérer les requêtes imbriquées, comme dans cet exemple :
{
authors {
items {
first_name
last_name
books {
items {
book {
id
title
}
royalties_percentage
}
}
}
}
}
Où vous demandez à retourner tous les auteurs, le livre qu’ils ont écrit avec les redevances associées.
Utilisation d’un objet de liaison
Le processus décrit dans la section précédente fonctionne très bien si toutes les entités impliquées dans les relations plusieurs-à-plusieurs doivent être accessibles via GraphQL. Ce scénario n’est pas toujours le cas. Par exemple, si vous n’avez pas besoin de suivre les redevances, l’entité BookAuthor
n’apporte pas vraiment de valeur à l’utilisateur final. L’entité a été utilisée uniquement pour associer des livres à leurs auteurs. Dans les bases de données relationnelles, les relations plusieurs-à-plusieurs sont créées à l’aide de cette troisième table qui lie les tables participant à la relation plusieurs-à-plusieurs :
Dans le diagramme, vous pouvez voir qu’il existe un tableau nommé books_authors
qui lie les auteurs à leurs livres et les livres avec leurs auteurs. Cette table de liaison n’a pas besoin d’être exposée à l’utilisateur final. La table de liaison n’est qu’un artefact permettant à la relation plusieurs-à-plusieurs d’exister, mais le générateur d’API de données doit connaître son existence pour pouvoir l’utiliser correctement.
L’interface CLI DAB peut être utilisée pour créer la relation plusieurs-à-plusieurs et configurer l’objet de liaison (veillez à supprimer toutes les relations créées dans la section précédente et à commencer uniquement par l’entité Book
et Author
sans aucune relation configurée entre elles déjà) :
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"
Qui met à jour le fichier de configuration JSON comme suit :
"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 configuration indique à DAB que vous souhaitez ajouter un authors
champ dans l’entité qui autorise l’accès Book
aux auteurs du livre. authors
peut être many
, de sorte qu’une liste d’auteurs est retournée lorsque la requête GraphQL accède au authors
champ. Cette relation définit comment naviguer de livres à auteurs : les champs de base de données utilisés pour naviguer des livres à leurs auteurs sont définis dans le source.fields
pour le livre, et dans le target.fields
pour les auteurs, de la même façon que la relation un-à-plusieurs ou plusieurs-à-un décrite précédemment dans cet article.
Cette relation étant une relation plusieurs-à-plusieurs, il n’y a pas de connexion directe entre les deux entités et un linking.object
doit donc être utilisé. Dans l’exemple, la table dbo.books_authors
de base de données est utilisée comme objet de liaison. La façon dont l’objet de liaison est en mesure de connecter des livres à leurs auteurs est définie dans les linking.source.fields
propriétés et linking.target.fields
. La première indique à DAB comment l’entité source ( le Book
) est connectée à l’objet d’affection, et la seconde comment l’objet de liaison est connecté à l’entité cible, Author
dans l’exemple.
Pour comprendre comment les informations fournies sont utilisées, vous pouvez utiliser cet exemple de requête équivalente :
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
Avec la configuration fournie, DAB est en mesure de comprendre GraphQL comme dans cet exemple :
{
books {
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
Où vous voulez obtenir des livres et leurs auteurs.
Pour autoriser la navigation de Author
à Book
, les mêmes principes peuvent être appliqués, en mettant à jour la configuration à l’aide de la commande suivante :
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"
Qui définit une relation plusieurs-à-plusieurs entre l’entité Author
et l’entité Book
, en utilisant l’objet dbo.books_authors
de liaison en arrière-plan.