Delen via


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 op one
  • 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.

Diagram met veel-op-veel-relatie tussen auteurs, books_authors en boeken.

Zoals zichtbaar zijn er twee bidirectionele relaties:

  • Een-op-veel-/veel-op-een-relatie tussen authors en de books_authors
  • Een-op-veel-/veel-op-een-relatie tussen books en de books_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 updateuit:

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:

Diagram met een andere veel-op-veel-relatie tussen auteurs, books_authors en boeken.

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 Booktoestaan, 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.