Entiteitsrelaties
GraphQL-query's kunnen gerelateerde objecten en hun velden passeren, zodat u met slechts één query iets kunt schrijven als:
{
books
{
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
Om boeken en hun auteurs op te halen.
Om deze mogelijkheid te laten werken, moet de Data API Builder weten hoe de twee objecten aan elkaar zijn gerelateerd. De relationships
sectie in het configuratiebestand bevat de benodigde metagegevens om deze mogelijkheid correct en efficiënt te laten werken.
Een relatie configureren
Ongeacht welke database u gebruikt met Data API Builder, u moet Data API Builder expliciet vertellen dat een object aan een ander object is gerelateerd. Er zijn drie soorten relaties die tussen twee entiteiten tot stand kunnen worden gebracht:
Een-op-veel-relatie
Met een een-op-veel-relatie kan een object toegang krijgen tot een lijst met gerelateerde objecten. Een boekenreeks kan bijvoorbeeld toegang verlenen tot alle boeken in die reeks:
{
series {
items {
name
books {
items {
title
}
}
}
}
}
Als er refererende sleutels zijn die de relatie tussen de twee onderliggende databaseobjecten ondersteunen, hoeft u data-API builder alleen te laten weten dat u een dergelijke relatie beschikbaar wilt maken. Met DAB CLI:
dab update Series --relationship books --target.entity Book --cardinality many
Hiermee wordt de series
entiteit bijgewerkt, die in het voorbeeld wordt gebruikt:
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"target.entity": "Book",
"cardinality": "many"
}
}
...
}
Er wordt een nieuwe sleutel toegevoegd onder het relationships
-element: books
. Het -element definieert de naam die wordt gebruikt voor het veld GraphQL om van het series
object naar het object te navigeren dat in dit geval is gedefinieerd in de target.entity
. Book
Dit betekent dat er een entiteit moet zijn aangeroepen Book
in het configuratiebestand.
De cardinality
eigenschap vertelt Data API Builder dat elke reeks veel boeken kan bevatten, zodat het gemaakte GraphQL-veld een lijst met items retourneert.
Die eigenschap is alles wat u nodig hebt. Bij het opstarten detecteert Data API Builder automatisch de databasevelden die moeten worden gebruikt om de gedefinieerde relatie te onderhouden.
Als u geen beperking voor een refererende sleutel hebt die de databaserelatie ondersteunt, kan Data API Builder niet automatisch achterhalen welke velden worden gebruikt. Als u Data API Builder wilt laten weten welke velden de twee entiteiten koppelen, moet u deze handmatig opgeven. U kunt deze opgeven met de CLI met behulp van dab update
:
dab update Series --relationship books --target.entity Book --cardinality many --relationship.fields "id:series_id"
Met de optie relationship.fields
kunt u definiëren welke velden worden gebruikt van de entiteit die wordt bijgewerkt (Series
) en welke velden worden gebruikt vanuit de doelentiteit (Book
), om de gegevens van de ene entiteit met de andere te verbinden.
In het vorige voorbeeld wordt het id
databaseveld van de Series
entiteit vergeleken met het databaseveld series_id
van de Book
entiteit.
De configuratie bevat ook deze informatie:
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"cardinality": "many",
"target.entity": "Book",
"source.fields": ["id"],
"target.fields": ["series_id"]
}
}
...
}
Veel-op-een-relatie
Een veel-op-een-relatie is vergelijkbaar met de een-op-veel-relatie met twee belangrijke verschillen:
- is
cardinality
ingesteld opone
- het gemaakte GraphQL-veld retourneert een scalaire niet een lijst
Na de voorbeelden van de Book Series die eerder zijn gebruikt, kan een boek zich in slechts één reeks bevinden, dus de relatie wordt gemaakt met behulp van de volgende DAB CLI-opdracht:
dab update Book --relationship series --target.entity Series --cardinality one
Hiermee wordt deze configuratie gegenereerd:
"Book": {
"source": "dbo.books",
...
"relationships": {
"series": {
"target.entity": "Series",
"cardinality": "one"
}
}
}
Wat op zijn beurt een GraphQL-query zoals in dit voorbeeld toestaat:
{
books {
items {
id
title
series {
name
}
}
}
}
Waar elk boek retourneert ook de reeks waartoe het behoort.
Veel-op-veel-relatie
Veel-op-veel-relaties kunnen worden gezien als een paar een-op-veel- en veel-op-een-relaties die samenwerken. Een auteur kan zeker meer dan één boek schrijven (een een-op-veel-relatie), maar het is ook waar dat meerdere auteurs aan hetzelfde boek kunnen werken (een veel-op-een-relatie).
Data API Builder ondersteunt dit type relatie systeemeigen:
- Een paar een-op-veel-/veel-op-een-relaties gebruiken.
- Een koppelingsobject gebruiken.
Een paar een-op-veel-/veel-op-een-relaties gebruiken
Een zakelijke vereiste die waarschijnlijk aanwezig is, is om bij te houden hoe royalty's worden verdeeld over de auteurs van een boek. Voor het implementeren van een dergelijke vereiste is een toegewezen entiteit nodig die een auteur, een boek en de toegewezen royalty's aan elkaar koppelt. Daarom zijn er drie entiteiten nodig:
authors
, om biografische details van auteurs weer te geven.books
, om boekgegevens weer te geven, zoals titel en International Standard Book Number (ISBN).books_authors
om gegevens weer te geven die zowel betrekking hebben op een boek als op de auteur, bijvoorbeeld het percentage royalty's dat een auteur voor een specifiek boek krijgt.
De drie entiteiten kunnen worden gevisualiseerd via het volgende diagram.
Zoals zichtbaar zijn er twee bidirectionele relaties:
- Een-op-veel-/veel-op-een-relatie tussen
authors
en debooks_authors
- Een-op-veel-/veel-op-een-relatie tussen
books
en debooks_authors
Als u een dergelijk scenario probleemloos wilt afhandelen met DAB, hoeft u alleen de gerelateerde entiteiten en toewijzingen in het configuratiebestand te maken. Ervan uitgaande dat de Book
entiteit en Author
zich al in het configuratiebestand bevinden:
dab add BookAuthor --source dbo.books_authors --permissions "anonymous:*"
Als u de nieuwe entiteit wilt toevoegen, voert u dab update
uit:
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"
Voer dab update
opnieuw uit om de relaties toe te voegen aan de zojuist gemaakte BookAuthor
entiteit:
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"
De relaties van BookAuthor
naar Book
en Author
entiteiten toevoegen. Met de opgegeven configuratie kan DAB geneste query's verwerken, zoals in dit voorbeeld:
{
authors {
items {
first_name
last_name
books {
items {
book {
id
title
}
royalties_percentage
}
}
}
}
}
Waar u vraagt om alle auteurs terug te geven, het boek dat ze samen met de gerelateerde royalty's hebben geschreven.
Een koppelingsobject gebruiken
Het proces dat in de vorige sectie wordt beschreven, werkt uitstekend als alle entiteiten die betrokken zijn bij de veel-op-veel-relaties, moeten worden geopend via GraphQL. Dit scenario is niet altijd het geval. Als u bijvoorbeeld geen royalty's hoeft bij te houden, levert de BookAuthor
entiteit geen waarde op voor de eindgebruiker. De entiteit is alleen gebruikt om boeken aan hun auteurs te koppelen. In relationele databases worden veel-op-veel-relaties gemaakt met behulp van een derde tabel die de tabellen die deelnemen aan de veel-op-veel-relatie aan elkaar koppelt:
In het diagram ziet u dat er een tabel met de naam books_authors
is die auteurs koppelt aan hun boeken en boeken aan hun auteurs. Deze koppelingstabel hoeft niet beschikbaar te zijn voor de eindgebruiker. De koppelingstabel is slechts een artefact waarmee de veel-op-veel-relatie kan bestaan, maar de Opbouwfunctie voor gegevens-API's moet het bestaan ervan kennen om deze op de juiste manier te kunnen gebruiken.
DAB CLI kan worden gebruikt om de veel-op-veel-relatie te maken en ook het koppelingsobject te configureren (verwijder alle relaties die in de vorige sectie zijn gemaakt en begin alleen met de Book
entiteit en Author
zonder geconfigureerde relatie er al tussen):
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"
Hiermee wordt het JSON-configuratiebestand bijgewerkt naar dit voorbeeld:
"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" ]
}
}
}
De configuratie vertelt DAB dat u een authors
veld in de Book
entiteit wilt toevoegen waarmee toegang wordt verleend aan auteurs van het boek. authors
kan zijn many
, zodat er een lijst met auteurs wordt geretourneerd wanneer de GraphQL-query het authors
veld opent. Deze relatie definieert hoe u van boeken naar auteurs navigeert: de databasevelden die worden gebruikt om van boeken naar hun auteurs te navigeren, worden gedefinieerd in de source.fields
voor het boek en in voor target.fields
de auteurs, op dezelfde manier als de een-op-veel- of veel-op-een-relatie die eerder in dit artikel is beschreven.
Deze relatie is een veel-op-veel-relatie, dus er is geen directe verbinding tussen de twee entiteiten en daarom moet een linking.object
worden gebruikt. In het voorbeeld wordt de databasetabel dbo.books_authors
gebruikt als het koppelingsobject. Hoe het koppelingsobject boeken met hun auteurs kan verbinden, wordt gedefinieerd in de linking.source.fields
eigenschappen en linking.target.fields
. De eerste vertelt DAB hoe de bronentiteit , de Book
, is verbonden met het object leuk en de tweede hoe het koppelende object is verbonden met de doelentiteit, Author
in het voorbeeld.
Als u wilt begrijpen hoe de opgegeven informatie wordt gebruikt, kunt u deze voorbeeldquery gebruiken:
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
Met de opgegeven configuratie kan DAB GraphQL begrijpen zoals in dit voorbeeld:
{
books {
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
Waar u boeken en hun auteurs wilt downloaden.
Als u navigatie van Author
naar wilt Book
toestaan, kunnen dezelfde principes worden toegepast, waarbij u de configuratie bijwerkt met behulp van de volgende opdracht:
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"
Hiermee wordt een veel-op-veel-relatie tussen de Author
entiteit en de Book
entiteit gedefinieerd, met behulp van het koppelingsobject dbo.books_authors
achter de schermen.