Mit Firebase Data Connect können Sie Connectors für Ihre PostgreSQL-Instanzen erstellen, die mit Google Cloud SQL verwaltet werden. Diese Connectors sind Kombinationen aus einem Schema, Abfragen und Mutationen zur Verwendung Ihrer Daten.
Im Startleitfaden wurde ein Anwendungsschema für PostgreSQL mit Filmrezensionen vorgestellt. In dieser Anleitung wird das Entwerfen von Data Connect-Schemas für PostgreSQL ausführlicher erläutert.
In diesem Leitfaden werden Data Connect-Abfragen und ‑Mutationen mit Schemabeispielen kombiniert. Warum sollten Sie Abfragen (und Mutationen) in einem Leitfaden zu Data Connect-Schemas erörtern? Wie andere GraphQL-basierte Plattformen ist Firebase Data Connect eine Abfrage-first-Entwicklungsplattform. Als Entwickler müssen Sie bei der Datenmodellierung also an die Daten denken, die Ihre Kunden benötigen. Das hat großen Einfluss auf das Datenschema, das Sie für Ihr Projekt entwickeln.
Dieser Leitfaden beginnt mit einem neuen Schema für Filmrezensionen, behandelt dann die Abfragen und Mutationen, die aus diesem Schema abgeleitet wurden, und bietet schließlich eine SQL-Auflistung, die dem Kernschema Data Connect entspricht.
Das Schema für eine App mit Filmrezensionen
Angenommen, Sie möchten einen Dienst erstellen, mit dem Nutzer Filmrezensionen senden und ansehen können.
Für eine solche App benötigen Sie ein Anfangsschema. Dieses Schema erweitern Sie später, um komplexe relationale Abfragen zu erstellen.
Filmtabelle
Das Schema für Filme enthält wichtige Direktiven wie:
@table
, mit dem wir Vorgangsnamen mit den Argumentensingular
undplural
festlegen können@col
zum expliziten Festlegen von Spaltennamen@default
, um das Festlegen von Standardeinstellungen zuzulassen.
# Movies
type Movie
@table(name: "Movies", singular: "movie", plural: "movies", key: ["id"]) {
id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
title: String!
releaseYear: Int @col(name: "release_year")
genre: String
rating: Int @col(name: "rating")
description: String @col(name: "description")
}
Serverwerte und Schlüsselskalare
Bevor wir uns die Filmbewertungs-App ansehen, stellen wir Data ConnectServerwerte und Schlüsselskalare vor.
Mit Serverwerten können Sie Felder in Ihren Tabellen dynamisch mit gespeicherten oder leicht berechenbaren Werten gemäß bestimmten serverseitigen Ausdrücken befüllen lassen. Sie können beispielsweise ein Feld mit einem Zeitstempel definieren, der beim Zugriff auf das Feld mit dem Ausdruck updatedAt: Timestamp! @default(expr: "request.time")
angewendet wird.
Schlüsselskalare sind kompakte Objekt-IDs, die von Data Connect automatisch aus Schlüsselfeldern in Ihren Schemas zusammengestellt werden. Bei Schlüsselskalaren geht es um Effizienz. Sie ermöglichen es Ihnen, in einem einzigen Aufruf Informationen zur Identität und Struktur Ihrer Daten zu finden. Sie sind besonders nützlich, wenn Sie sequenzielle Aktionen auf neue Einträge ausführen und eine eindeutige Kennung für nachfolgende Vorgänge benötigen. Außerdem sind sie nützlich, wenn Sie auf relationale Schlüssel zugreifen möchten, um zusätzliche, komplexere Vorgänge auszuführen.
Tabelle mit Filmmetadaten
Sehen wir uns nun an, wie wir Filmregisseure im Blick behalten und eine persönliche Beziehung zu Movie
aufbauen.
Fügen Sie die Anweisung @ref
hinzu, um Beziehungen zu definieren.
# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata
@table(
name: "MovieMetadata"
) {
# @ref creates a field in the current table (MovieMetadata) that holds the
# primary key of the referenced type
# In this case, @ref(fields: "id") is implied
movie: Movie! @ref
# movieId: UUID <- this is created by the above @ref
director: String @col(name: "director")
}
Schauspieler und Filmschauspieler
Als Nächstes möchten Sie Schauspieler in Ihren Filmen haben. Da zwischen Filmen und Schauspielern eine Beziehung vom Typ „Viele zu Viele“ besteht, erstellen Sie eine Join-Tabelle.
# Actors
# Suppose an actor can participate in multiple movies and movies can have multiple actors
# Movie - Actors (or vice versa) is a many to many relationship
type Actor @table(name: "Actors", singular: "actor", plural: "actors") {
id: UUID! @col(name: "actor_id") @default(expr: "uuidV4()")
name: String! @col(name: "name", dataType: "varchar(30)")
}
# Join table for many-to-many relationship for movies and actors
# The 'key' param signifies the primary key(s) of this table
# In this case, the keys are [movieId, actorId], the generated fields of the reference types [movie, actor]
type MovieActor @table(key: ["movie", "actor"]) {
# @ref creates a field in the current table (MovieActor) that holds the primary key of the referenced type
# In this case, @ref(fields: "id") is implied
movie: Movie! @ref
# movieId: UUID! <- this is created by the above @ref, see: implicit.gql
actor: Actor! @ref
# actorId: UUID! <- this is created by the above @ref, see: implicit.gql
role: String! @col(name: "role") # "main" or "supporting"
# optional other fields
}
Nutzer
Zuletzt die Nutzer Ihrer App.
# Users
# Suppose a user can leave reviews for movies
# user:reviews is a one to many relationship, movie:reviews is a one to many relationship, movie:user is a many to many relationship
type User
@table(name: "Users", singular: "user", plural: "users", key: ["id"]) {
id: UUID! @col(name: "user_id") @default(expr: "uuidV4()")
auth: String @col(name: "user_auth") @default(expr: "auth.uid")
username: String! @col(name: "username", dataType: "varchar(30)")
# The following are generated from the @ref in the Review table
# reviews_on_user
# movies_via_Review
}
Unterstützte Datentypen
Data Connect unterstützt die folgenden skalaren Datentypen, wobei PostgreSQL-Typen mit @col(dataType:)
zugewiesen werden.
Data Connect-Typ | Integrierter GraphQL-Typ oder Data Connect benutzerdefinierter Typ |
Standard-PostgreSQL-Typ | Unterstützte PostgreSQL-Typen (Alias in Klammern) |
---|---|---|---|
String | GraphQL | Text | text bit(n), varbit(n) char(n), varchar(n) |
Integer | GraphQL | int | Int2 (smallint, smallserial), int4 (integer, int, serial) |
Float | GraphQL | float8 | float4 (reelle) float8 (doppelte Genauigkeit) numerisch (Dezimalzahl) |
Boolesch | GraphQL | boolean | boolean |
UUID | Benutzerdefiniert | uuid | uuid |
INT64 | Benutzerdefiniert | bigint | int8 (bigint, Bigserial) numeric (Dezimalzahl) |
Datum | Benutzerdefiniert | Datum | Datum |
Zeitstempel | Benutzerdefiniert | Zeitstempel | Zeitstempeltz Hinweis: Informationen zur lokalen Zeitzone werden nicht gespeichert. |
Vektor | Benutzerdefiniert | vector | Vektor Weitere Informationen finden Sie unter Mit Vertex AI nach Vektorähnlichkeiten suchen. |
- GraphQL
List
ist einem eindimensionalen Array zugeordnet.- Beispiel:
[Int]
wirdint5[]
zugeordnet,[Any]
wirdjsonb[]
zugeordnet. - Data Connect unterstützt keine verschachtelten Arrays.
- Beispiel:
Implizite und vordefinierte Abfragen und Mutationen
Ihre Data Connect-Abfragen und -Mutationen erweitern eine Reihe von impliziten Abfragen und impliziten Mutationen, die von Data Connect basierend auf den Typen und Typbeziehungen in Ihrem Schema generiert werden. Implizite Abfragen und Mutationen werden jedes Mal von lokalen Tools generiert, wenn Sie Ihr Schema bearbeiten.
Im Rahmen Ihres Entwicklungsvorgangs implementieren Sie vordefinierte Abfragen und vordefinierte Mutationen, die auf diesen impliziten Vorgängen basieren.
Namensgebung für implizite Abfragen und Mutationen
Data Connect leitet geeignete Namen für implizite Abfragen und Mutationen aus Ihren Schematypdeklarationen ab. Wenn Sie beispielsweise mit einer PostgreSQL-Quelle arbeiten und eine Tabelle mit dem Namen Movie
definieren, generiert der Server implizit:
- Abfragen für Anwendungsfälle mit einer einzelnen Tabelle mit den Aliasnamen
movie
(Singular, zum Abrufen einzelner Ergebnisse mithilfe von Argumenten wieeq
) undmovies
(Plural, zum Abrufen von Ergebnislisten mithilfe von Argumenten wiegt
und Vorgängen wieorderby
). Data Connect generiert auch Abfragen für relationale Vorgänge mit mehreren Tabellen mit expliziten Namen wieactors_on_movies
oderactors_via_actormovie
. - Mutationen mit den Namen
movie_insert
,movie_upsert
...
Mit der Schemadefinition können Sie auch Namen für Vorgänge explizit mithilfe von singular
- und plural
-Direktivargumenten festlegen.
Abfragen für die Datenbank mit Filmrezensionen
Sie definieren eine Data Connect-Abfrage mit einer Deklaration des Abfragevorgangstyps, dem Namen des Vorgangs, null oder mehr Vorgangsargumenten und null oder mehr Anweisungen mit Argumenten.
In der Kurzanleitung wurden für die Beispielabfrage listEmails
keine Parameter verwendet. In vielen Fällen sind die an Abfragefelder übergebenen Daten natürlich dynamisch. Mit der $variableName
-Syntax können Sie Variablen als eine der Komponenten einer Abfragedefinition verwenden.
Die folgende Abfrage hat also:
- Eine
query
-Typdefinition - Ein
ListMoviesByGenre
-Vorgangsname (Abfrage) - Ein
$genre
-Vorgangsargument einer einzelnen Variablen - Eine einzelne Anweisung,
@auth
.
query ListMoviesByGenre($genre: String!) @auth(level: USER)
Jedes Abfrageargument erfordert eine Typdeklaration, einen integrierten Typ wie String
oder einen benutzerdefinierten, schemadefinierten Typ wie Movie
.
Sehen wir uns die Signatur zunehmend komplexer Abfragen an. Zum Schluss werden leistungsstarke, prägnante Beziehungsausdrücke vorgestellt, die in impliziten Abfragen verfügbar sind und auf denen Sie in Ihren vordefinierten Abfragen aufbauen können.
Wichtige Skalare in Abfragen
Aber zuerst noch ein Hinweis zu Schlüsselskalen.
Data Connect definiert einen speziellen Typ für Schlüsselskalare, die durch _Key
gekennzeichnet sind. Der Typ eines Schlüsselskalaars für unsere Tabelle Movie
ist beispielsweise Movie_Key
.
Schlüsselskaläre werden als Antwort zurückgegeben, die von den meisten impliziten Mutationen zurückgegeben wird, oder natürlich aus Abfragen, bei denen Sie alle Felder abgerufen haben, die zum Erstellen des skalaren Schlüssels erforderlich sind.
Einzelne automatische Abfragen wie movie
in unserem Beispiel unterstützen ein Schlüsselargument, das einen Schlüsselskalar akzeptiert.
Sie können einen Schlüsselskalar als Literal übergeben. Sie können jedoch Variablen definieren, um wichtige Skalare als Eingabe zu übergeben.
query GetMovie($myKey: Movie_Key!) {
movie(key: $myKey) { title }
}
Sie können in einer JSON-Anfrage wie dieser (oder in anderen Serialization-Formaten) angegeben werden:
{
# …
"variables": {
"myKey": {"foo": "some-string-value", "bar": 42}
}
}
Dank des benutzerdefinierten skalaren Parsens kann ein Movie_Key
auch mithilfe der Objektsyntax erstellt werden, die Variablen enthalten kann. Das ist vor allem dann nützlich, wenn Sie einzelne Komponenten aus irgendeinem Grund in verschiedene Variablen aufteilen möchten.
Aliasse in Abfragen
Data Connect unterstützt GraphQL-Aliasing in Abfragen. Mit Aliassen benennen Sie die Daten um, die in den Ergebnissen einer Abfrage zurückgegeben werden. Mit einer einzelnen Data Connect-Abfrage können mehrere Filter oder andere Abfragevorgänge in einer einzigen effizienten Anfrage an den Server angewendet werden, wodurch mehrere „Unterabfragen“ gleichzeitig ausgeführt werden. Um Namenskonflikte im zurückgegebenen Datensatz zu vermeiden, verwenden Sie Aliasse, um die Unterabfragen zu unterscheiden.
Hier ist eine Abfrage, in der ein Ausdruck den Alias mostPopular
verwendet.
query ReviewTopPopularity($genre: String) {
mostPopular: review(first: {
where: {genre: {eq: $genre}},
orderBy: {popularity: DESC}
}) { … }
}
Einfache Abfragen mit Filtern
Data Connect-Abfragen werden allen gängigen SQL-Filtern und -Sortiervorgängen zugeordnet.
where
- und orderBy
-Operatoren (Singular- und Pluralabfragen)
Gibt alle übereinstimmenden Zeilen aus der Tabelle (und verschachtelte Verknüpfungen) zurück. Gibt ein leeres Array zurück, wenn keine Datensätze mit dem Filter übereinstimmen.
query MovieByTopRating($genre: String) {
mostPopular: movies(
where: { genre: { eq: $genre } }, orderBy: { rating: DESC }
) {
# graphql: list the fields from the results to return
id
title
genre
description
}
}
query MoviesByReleaseYear($min: Int, $max: Int) {
movies(where: {releaseYear: {le: $max, ge: $min}}, orderBy: [{releaseYear: ASC}]) { … }
}
limit
- und offset
-Operatoren (Singular- und Pluralabfragen)
Sie können die Ergebnisse paginaieren. Diese Argumente werden akzeptiert, aber nicht in den Ergebnissen zurückgegeben.
query MoviesTop10 {
movies(orderBy: [{ rating: DESC }], limit: 10) {
# graphql: list the fields from the results to return
title
}
}
„includes“ für Arrayfelder
Sie können prüfen, ob ein Arrayfeld ein bestimmtes Element enthält.
# Filter using arrays and embedded fields.
query ListMoviesByTag($tag: String!) {
movies(where: { tags: { includes: $tag }}) {
# graphql: list the fields from the results to return
id
title
}
}
String-Operationen und reguläre Ausdrücke
Für Abfragen können typische Stringsuch- und Vergleichsvorgänge verwendet werden, einschließlich regulärer Ausdrücke. Hinweis: Aus Effizienzgründen bündeln Sie hier mehrere Vorgänge und trennen sie mit Aliassen.
query MoviesTitleSearch($prefix: String, $suffix: String, $contained: String, $regex: String) {
prefixed: movies(where: {title: {startsWith: $prefix}}) {...}
suffixed: movies(where: {title: {endsWith: $suffix}}) {...}
contained: movies(where: {title: {contains: $contained}}) {...}
matchRegex: movies(where: {title: {pattern: {regex: $regex}}}) {...}
}
or
und and
für zusammengesetzte Filter
Verwenden Sie or
und and
für eine komplexere Logik.
query ListMoviesByGenreAndGenre($minRating: Int!, $genre: String) {
movies(
where: { _or: [{ rating: { ge: $minRating } }, { genre: { eq: $genre } }] }
) {
# graphql: list the fields from the results to return
title
}
}
Komplexe Abfragen
Data Connect-Abfragen können auf Daten basierend auf den Beziehungen zwischen Tabellen zugreifen. Sie können die in Ihrem Schema definierten Objektbeziehungen (1:1) oder Arraybeziehungen (1:n) verwenden, um verschachtelte Abfragen auszuführen, d. h. Daten für einen Typ zusammen mit Daten aus einem verschachtelten oder ähnlichen Typ abzurufen.
Solche Abfragen verwenden die magische Data Connect-_on_
- und _via
-Syntax in generierten impliziten Abfragen.
Sie nehmen Änderungen am Schema vor, das auf unserer ursprünglichen Version basiert.
Viele-zu-Eins
Fügen wir unserer App Rezensionen hinzu, mit einer Review
-Tabelle und Änderungen an User
.
# Users
# Suppose a user can leave reviews for movies
# user:reviews is a one to many relationship,
# movie:reviews is a one to many relationship,
# movie:user is a many to many relationship
type User
@table(name: "Users", singular: "user", plural: "users", key: ["id"]) {
id: UUID! @col(name: "user_id") @default(expr: "uuidV4()")
auth: String @col(name: "user_auth") @default(expr: "auth.uid")
username: String! @col(name: "username", dataType: "varchar(30)")
# The following are generated from the @ref in the Review table
# reviews_on_user
# movies_via_Review
}
# Reviews
type Review @table(name: "Reviews", key: ["movie", "user"]) {
id: UUID! @col(name: "review_id") @default(expr: "uuidV4()")
user: User! @ref
movie: Movie! @ref
rating: Int
reviewText: String
reviewDate: Date! @default(expr: "request.time")
}
Abfrage für viele zu eins
Sehen wir uns nun eine Abfrage mit Aliasing an, um die _via_
-Syntax zu veranschaulichen.
query UserMoviePreferences($username: String!) @auth(level: USER) {
users(where: { username: { eq: $username } }) {
likedMovies: movies_via_review(where: { rating: { ge: 4 } }) {
title
genre
description
}
dislikedMovies: movies_via_review(where: { rating: { le: 2 } }) {
title
genre
description
}
}
}
Einzelgespräch
Sie sehen das Muster. Unten ist das Schema zur Veranschaulichung geändert.
# Movies
type Movie
@table(name: "Movies", singular: "movie", plural: "movies", key: ["id"]) {
id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
title: String!
releaseYear: Int @col(name: "release_year")
genre: String
rating: Int @col(name: "rating")
description: String @col(name: "description")
tags: [String] @col(name: "tags")
}
# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata
@table(
name: "MovieMetadata"
) {
# @ref creates a field in the current table (MovieMetadata) that holds the primary key of the referenced type
# In this case, @ref(fields: "id") is implied
movie: Movie! @ref
# movieId: UUID <- this is created by the above @ref
director: String @col(name: "director")
}
extend type MovieMetadata {
movieId: UUID! # matches primary key of referenced type
...
}
extend type Movie {
movieMetadata: MovieMetadata # can only be non-nullable on ref side
# conflict-free name, always generated
movieMetadatas_on_movie: MovieMetadata
}
Abfrage für Einzelgespräch
Sie können Abfragen mit der _on_
-Syntax stellen.
# One to one
query GetMovieMetadata($id: UUID!) @auth(level: PUBLIC) {
movie(id: $id) {
movieMetadatas_on_movie {
director
}
}
}
Viele zu viele
Filme brauchen Schauspieler und Schauspieler brauchen Filme. Sie stehen in einer m:n-Beziehung, die Sie mit einer MovieActors
-Join-Tabelle modellieren können.
# MovieActors Join Table Definition
type MovieActors @table(
key: ["movie", "actor"] # join key triggers many-to-many generation
) {
movie: Movie!
actor: Actor!
}
# generated extensions for the MovieActors join table
extend type MovieActors {
movieId: UUID!
actorId: UUID!
}
# Extensions for Actor and Movie to handle many-to-many relationships
extend type Movie {
movieActors: [MovieActors!]! # standard many-to-one relation to join table
actors: [Actor!]! # many-to-many via join table
movieActors_on_actor: [MovieActors!]!
# since MovieActors joins distinct types, type name alone is sufficiently precise
actors_via_MovieActors: [Actor!]!
}
extend type Actor {
movieActors: [MovieActors!]! # standard many-to-one relation to join table
movies: [Movie!]! # many-to-many via join table
movieActors_on_movie: [MovieActors!]!
movies_via_MovieActors: [Movie!]!
}
Abfrage für viele zu viele
Sehen wir uns eine Abfrage mit Alias an, um die _via_
-Syntax zu veranschaulichen.
query GetMovieCast($movieId: UUID!, $actorId: UUID!) @auth(level: PUBLIC) {
movie(id: $movieId) {
mainActors: actors_via_MovieActor(where: { role: { eq: "main" } }) {
name
}
supportingActors: actors_via_MovieActor(
where: { role: { eq: "supporting" } }
) {
name
}
}
actor(id: $actorId) {
mainRoles: movies_via_MovieActor(where: { role: { eq: "main" } }) {
title
}
supportingRoles: movies_via_MovieActor(
where: { role: { eq: "supporting" } }
) {
title
}
}
}
Mutationen für die Datenbank mit Filmrezensionen
Wie bereits erwähnt, generiert Data Connect beim Definieren einer Tabelle in Ihrem Schema grundlegende implizite Mutationen für jede Tabelle.
type Movie @table { ... }
extend type Mutation {
# Insert a row into the movie table.
movie_insert(...): Movie_Key!
# Upsert a row into movie."
movie_upsert(...): Movie_Key!
# Update a row in Movie. Returns null if a row with the specified id/key does not exist
movie_update(...): Movie_Key
# Update rows based on a filter in Movie.
movie_updateMany(...): Int!
# Delete a single row in Movie. Returns null if a row with the specified id/key does not exist
movie_delete(...): Movie_Key
# Delete rows based on a filter in Movie.
movie_deleteMany(...): Int!
}
So können Sie immer komplexere CRUD-Grundfälle implementieren. Sagen Sie das fünfmal schnell!
Erstellen
Beginnen wir mit den Grundlagen.
# Create a movie based on user input
mutation CreateMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
movie_insert(data: {
title: $title
releaseYear: $releaseYear
genre: $genre
rating: $rating
})
}
# Create a movie with default values
mutation CreateMovie2 {
movie_insert(data: {
title: "Sherlock Holmes"
releaseYear: 2009
genre: "Mystery"
rating: 5
})
}
Oder ein Upsert.
# Movie upsert using combination of variables and literals
mutation UpsertMovie($title: String!) {
movie_upsert(data: {
title: $title
releaseYear: 2009
genre: "Mystery"
rating: 5
genre: "Mystery/Thriller"
})
}
Updates ausführen
Hier sind die Neuigkeiten. Produzenten und Regisseure hoffen natürlich, dass diese durchschnittlichen Bewertungen dem Trend entsprechen.
mutation UpdateMovie(
$id: UUID!,
$genre: String!,
$rating: Int!,
$description: String!
) {
movie_update(id: $id, data: {
genre: $genre
rating: $rating
description: $description
})
}
# Multiple updates (increase all ratings of a genre)
mutation IncreaseRatingForGenre($genre: String!, $ratingIncrement: Int!) {
movie_updateMany(
where: { genre: { eq: $genre } },
update: { rating: { inc: $ratingIncrement } }
)
}
Löschen
Sie können Filmdaten natürlich auch löschen. Filmerhaltungsfachleute möchten sicherlich, dass die physischen Filme so lange wie möglich aufbewahrt werden.
# Delete by key
mutation DeleteMovie($id: UUID!) {
movie_delete(id: $id)
}
Hier können Sie _deleteMany
verwenden.
# Multiple deletes
mutation DeleteUnpopularMovies($minRating: Int!) {
movie_deleteMany(where: { rating: { le: $minRating } })
}
Mutationen für Beziehungen schreiben
Hier sehen Sie, wie die implizite _upsert
-Mutation auf eine Beziehung angewendet wird.
# Create or update a one to one relation
mutation MovieMetadataUpsert($movieId: UUID!, $director: String!) {
movieMetadata_upsert(
data: { movie: { id: $movieId }, director: $director }
)
}
Entsprechendes SQL-Schema
-- Movies Table
CREATE TABLE Movies (
movie_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
title VARCHAR(255) NOT NULL,
release_year INT,
genre VARCHAR(30),
rating INT,
description TEXT,
tags TEXT[]
);
-- Movie Metadata Table
CREATE TABLE MovieMetadata (
movie_id UUID REFERENCES Movies(movie_id) UNIQUE,
director VARCHAR(255) NOT NULL,
PRIMARY KEY (movie_id)
);
-- Actors Table
CREATE TABLE Actors (
actor_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name VARCHAR(30) NOT NULL
);
-- MovieActor Join Table for Many-to-Many Relationship
CREATE TABLE MovieActor (
movie_id UUID REFERENCES Movies(movie_id),
actor_id UUID REFERENCES Actors(actor_id),
role VARCHAR(50) NOT NULL, # "main" or "supporting"
PRIMARY KEY (movie_id, actor_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id),
FOREIGN KEY (actor_id) REFERENCES Actors(actor_id)
);
-- Users Table
CREATE TABLE Users (
user_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_auth VARCHAR(255) NOT NULL
username VARCHAR(30) NOT NULL
);
-- Reviews Table
CREATE TABLE Reviews (
review_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES Users(user_id),
movie_id UUID REFERENCES Movies(movie_id),
rating INT,
review_text TEXT,
review_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE (movie_id, user_id)
FOREIGN KEY (user_id) REFERENCES Users(user_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id)
);
-- Self Join Example for Movie Sequel Relationship
ALTER TABLE Movies
ADD COLUMN sequel_to UUID REFERENCES Movies(movie_id);
Nächste Schritte
- Hier erfahren Sie, wie Sie Abfragen und Mutationen über ein automatisch generiertes Web SDK, ein Android SDK, ein iOS SDK und ein Flutter SDK aufrufen.