Entitätsbeziehungen
GraphQL Abfragen können verwandte Objekte und deren Felder durchlaufen, sodass Sie mit nur einer Abfrage folgendes schreiben können:
{
books
{
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
Zum Abrufen von Büchern und deren Autoren.
Damit diese Möglichkeit funktioniert, muss der Daten-API-Generator wissen, wie die beiden Objekte miteinander verbunden sind. Der relationships
Abschnitt in der Konfigurationsdatei enthält die erforderlichen Metadaten, damit diese Funktion ordnungsgemäß und effizient funktioniert.
Konfigurieren einer Beziehung
Unabhängig davon, welche Datenbank Sie mit dem Daten-API-Generator verwenden, müssen Sie den Daten-API-Generator explizit darüber informieren, dass ein Objekt mit einem anderen verknüpft ist. Es gibt drei Arten von Beziehungen, die zwischen zwei Entitäten eingerichtet werden können:
1:n-Beziehung
Eine 1:n-Beziehung ermöglicht einem Objekt den Zugriff auf eine Liste verwandter Objekte. Beispielsweise kann eine Buchreihe den Zugriff auf alle Bücher in dieser Reihe ermöglichen:
{
series {
items {
name
books {
items {
title
}
}
}
}
}
Wenn Fremdschlüssel vorhanden sind, die die Beziehung zwischen den beiden zugrunde liegenden Datenbankobjekten unterstützen, müssen Sie nur den Daten-API-Generator mitteilen, dass Sie eine solche Beziehung verfügbar machen möchten. Mit dab CLI:
dab update Series --relationship books --target.entity Book --cardinality many
Dadurch wird die series
Entität aktualisiert, die im Beispiel verwendet wird:
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"target.entity": "Book",
"cardinality": "many"
}
}
...
}
Unter dem -Element wird ein relationships
neuer Schlüssel hinzugefügt: books
. Das -Element definiert den Namen, der für das feld GraphQL verwendet wird, um in diesem Fall vom series
-Objekt zum in target.entity
Book
definierten Objekt zu navigieren. Dies bedeutet, dass in der Konfigurationsdatei eine Entität namens vorhanden Book
sein muss.
Die cardinality
Eigenschaft teilt dem Data API-Generator mit, dass in jeder Reihe viele Bücher vorhanden sein können, sodass das erstellte GraphQL Feld eine Liste von Elementen zurückgibt.
Diese Eigenschaft ist alles, was Sie benötigen. Beim Start erkennt der Daten-API-Generator automatisch die Datenbankfelder, die verwendet werden müssen, um die definierte Beziehung aufrechtzuerhalten.
Wenn Sie keine Fremdschlüsseleinschränkung haben, die die Datenbankbeziehung aufrechterhalten soll, kann der Daten-API-Generator nicht automatisch ermitteln, welche Felder verwendet werden. Um den Daten-API-Generator zu informieren, welche Felder die beiden Entitäten in Beziehung setzen, müssen Sie sie manuell angeben. Sie können sie mit der CLI angeben, indem dab update
Sie verwenden:
dab update Series --relationship books --target.entity Book --cardinality many --relationship.fields "id:series_id"
Mit der Option relationship.fields
können Sie definieren, welche Felder von der entität verwendet werden, die aktualisiert wird (Series
) und welche Felder von der Zielentität (Book
) verwendet werden, um die Daten von einer Entität mit der anderen zu verbinden.
Im vorherigen Beispiel wird das id
Datenbankfeld der Series
Entität mit dem Datenbankfeld series_id
der Book
Entität abgeglichen.
Die Konfiguration enthält auch diese Informationen:
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"cardinality": "many",
"target.entity": "Book",
"source.fields": ["id"],
"target.fields": ["series_id"]
}
}
...
}
n:1-Beziehung
Eine m:1-Beziehung ähnelt der 1:n-Beziehung mit zwei Hauptunterschieden:
- ist
cardinality
auf festgelegt.one
- Das erstellte GraphQL Feld gibt einen Skalar und keine Liste zurück.
Nach den zuvor verwendeten Book Series-Beispielen kann ein Buch in nur einer Reihe enthalten sein, sodass die Beziehung mit dem folgenden DAB CLI-Befehl erstellt wird:
dab update Book --relationship series --target.entity Series --cardinality one
Dadurch wird diese Konfiguration generiert:
"Book": {
"source": "dbo.books",
...
"relationships": {
"series": {
"target.entity": "Series",
"cardinality": "one"
}
}
}
Dies wiederum ermöglicht eine GraphQL Abfrage wie in diesem Beispiel:
{
books {
items {
id
title
series {
name
}
}
}
}
Wobei jedes Buch auch die Reihe zurückgibt, zu der es gehört.
m:n-Beziehung
Viele zu viele Beziehungen können als ein Paar von 1:n- und n:1-Beziehungen betrachtet werden, die zusammenarbeiten. Ein Autor kann sicherlich mehr als ein Buch schreiben (eine 1:n-Beziehung), aber es stimmt auch, dass mehr als ein Autor an demselben Buch arbeiten kann (eine m:n-Beziehung).
Der Daten-API-Generator unterstützt diese Art von Beziehung nativ:
- Verwenden eines 1:n-/n-1-Beziehungspaars.
- Verwenden eines Verknüpfungsobjekts.
Verwenden eines 1:n-/n-1-Beziehungspaars
Eine geschäftliche Anforderung, die wahrscheinlich vorhanden sein wird, besteht darin, nachzuverfolgen, wie Lizenzgebühren zwischen den Autoren eines Buches aufgeteilt werden. Um eine solche Anforderung zu implementieren, sind eine dedizierte Entität, die einen Autor miteinander verknüpft, ein Buch und die zugewiesenen Lizenzgebühren erforderlich. Daher werden drei Entitäten benötigt:
authors
, um biografische Details von Autoren darzustellen.books
, um Buchdaten wie Titel und International Standard Book Number (ISBN) darzustellen.books_authors
, um Daten darzustellen, die sich sowohl auf ein Buch als auch auf den Autor beziehen, z. B. den Prozentsatz der Lizenzgebühren, die ein Autor für ein bestimmtes Buch erhält.
Die drei Entitäten können mithilfe des folgenden Diagramms visualisiert werden.
Wie sichtbar, gibt es zwei bidirektionale Beziehungen:
- 1:n/n-Beziehung zwischen
authors
undbooks_authors
- 1:n/n-Beziehung zwischen
books
undbooks_authors
Um ein solches Szenario ordnungsgemäß mit DAB zu behandeln, müssen nur die zugehörigen Entitäten und Zuordnungen in der Konfigurationsdatei erstellt werden. Angenommen, die Book
Entität und Author
befinden sich bereits in der Konfigurationsdatei:
dab add BookAuthor --source dbo.books_authors --permissions "anonymous:*"
Um die neue Entität hinzuzufügen, führen Sie aus 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"
Führen Sie erneut aus, dab update
um die Beziehungen zur neu erstellten BookAuthor
Entität hinzuzufügen:
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"
So fügen Sie die Beziehungen von BookAuthor
zu Book
- und Author
-Entitäten hinzu. Mit der bereitgestellten Konfiguration kann DAB geschachtelte Abfragen wie das folgende Beispiel verarbeiten:
{
authors {
items {
first_name
last_name
books {
items {
book {
id
title
}
royalties_percentage
}
}
}
}
}
Wo Sie bitten, alle Autoren zurückzugeben, das Buch, das sie geschrieben haben, zusammen mit den damit verbundenen Lizenzgebühren.
Verwenden eines Verknüpfungsobjekts
Der im vorherigen Abschnitt beschriebene Prozess funktioniert hervorragend, wenn auf alle Entitäten, die an den M:n-Beziehungen beteiligt sind, über GraphQL zugegriffen werden muss. Dieses Szenario ist nicht immer der Fall. Wenn Sie z. B. keine Lizenzgebühren nachverfolgen müssen, bringt die BookAuthor
Entität dem Endbenutzer keinen wirklichen Wert. Die Entität wurde nur verwendet, um ihren Autoren Bücher zuzuordnen. In relationalen Datenbanken werden m:n-Beziehungen mithilfe einer solchen dritten Tabelle erstellt, die die Tabellen verknüpft, die an der m:n-Beziehung teilnehmen:
Im Diagramm sehen Sie, dass es eine Tabelle namens books_authors
gibt, die Autoren mit ihren Büchern und Büchern mit ihren Autoren verknüpft. Diese Verknüpfungstabelle muss nicht für den Endbenutzer verfügbar gemacht werden. Die Verknüpfungstabelle ist nur ein Artefakt, um die m:n-Beziehung zu ermöglichen, aber der Daten-API-Generator muss seine Existenz kennen, um sie ordnungsgemäß verwenden zu können.
Die DAB-CLI kann verwendet werden, um die m:n-Beziehung zu erstellen und auch das Verknüpfungsobjekt zu konfigurieren (stellen Sie sicher, dass Sie alle im vorherigen Abschnitt erstellten Beziehungen entfernen und nur mit der Book
Entität und Author
beginnen, ohne dass bereits eine Beziehung zwischen ihnen konfiguriert ist):
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"
Dadurch wird die JSON-Konfigurationsdatei wie in diesem Beispiel aktualisiert:
"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" ]
}
}
}
Die Konfiguration teilt DAB mit, dass Sie ein authors
Feld in der Entität hinzufügen möchten, das Book
den Autoren des Buchs zugriff ermöglicht. authors
kann seinmany
, sodass eine Liste von Autoren zurückgegeben wird, wenn die GraphQL Abfrage auf das authors
Feld zugreift. Diese Beziehung definiert das Navigieren vonBüchern zu Autoren: Die Datenbankfelder, die zum Navigieren von Büchern zu ihren Autoren verwendet werden, werden in der source.fields
für das Buch und in der target.fields
für die Autoren definiert, ähnlich wie die zuvor in diesem Artikel beschriebene 1:n- oder n:n-Beziehung.
Diese Beziehung ist eine m:n-Beziehung, sodass es keine direkte Verbindung zwischen den beiden Entitäten gibt und daher verwendet linking.object
werden muss. Im Beispiel wird die Datenbanktabelle dbo.books_authors
als Verknüpfungsobjekt verwendet. Wie das verknüpfende Objekt Bücher mit ihren Autoren verbinden kann, ist in den linking.source.fields
Eigenschaften und linking.target.fields
definiert. Die erste teilt DAB mit, wie die Quellentität - die Book
- mit dem likenden Objekt verbunden ist, und die zweite, wie das verknüpfende Objekt mit der Zielentität verbunden ist, Author
im Beispiel.
Um zu verstehen, wie die bereitgestellten Informationen verwendet werden, können Sie diese Beispiel-äquivalente Abfrage verwenden:
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
Mit der bereitgestellten Konfiguration kann DAB GraphQL wie in diesem Beispiel verstehen:
{
books {
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
Wo Sie Bücher und deren Autoren bekommen möchten.
Um die Navigation von Author
zu Book
ermöglichen, können dieselben Prinzipien angewendet werden, indem die Konfiguration mit dem folgenden Befehl aktualisiert wird:
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"
Definiert eine m:n-Beziehung zwischen der Author
Entität und der Book
Entität unter Verwendung des Verknüpfungsobjekts dbo.books_authors
im Hintergrund.