Data Connect-Abfragen implementieren

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 Abfragen und Mutationen, mit denen Sie Ihre Daten aus Ihrem Schema verwenden können.

In der Anleitung für die ersten Schritte wurde ein Schema für eine Filmbewertungs-App für PostgreSQL vorgestellt.

In dieser Anleitung wurden auch bereitstellbare und Ad-hoc-Verwaltungsvorgänge, einschließlich Abfragen, eingeführt.

  • Bereitstellbare Abfragen sind Abfragen, die Sie implementieren, um sie über Client-Apps mit von Ihnen definierten API-Endpunkten aufzurufen. Sie bündeln sie in einem Connector, der auf dem Server bereitgestellt wird. Mit Data Connect-Tools werden Client-SDKs basierend auf Ihrer API generiert. Bereitgestellte Abfragen sind nicht durch IAM-Richtlinien geschützt. Sorgen Sie daher dafür, dass sie mit der Direktive Data Connect @auth geschützt werden.
  • Ad-hoc-Verwaltungsabfragen werden in privilegierten Umgebungen ausgeführt, um Daten zu lesen. Sie können sie in der Firebase-Konsole oder in lokalen Entwicklungsumgebungen mit unserer Data Connect VS Code-Erweiterung erstellen und ausführen.

In diesem Leitfaden werden bereitstellbare Abfragen genauer betrachtet.

Funktionen von Data Connect-Abfragen

Mit Data Connect können Sie grundlegende Abfragen auf alle Arten ausführen, die Sie von einer PostgreSQL-Datenbank erwarten.

Mit den Erweiterungen von Data Connect für GraphQL können Sie jedoch erweiterte Abfragen für schnellere und effizientere Apps implementieren:

  • Verwenden Sie Schlüssel-Skalare, die von vielen Vorgängen zurückgegeben werden, um wiederholte Vorgänge für Datensätze zu vereinfachen.
  • Führen Sie Abfragen im Rahmen von mehrstufigen Mutationsvorgängen aus, um Daten abzurufen. So sparen Sie Codezeilen und Roundtrips zum Server.

Generierte Felder zum Erstellen von Abfragen verwenden

Ihre Data Connect-Vorgänge erweitern automatisch eine Reihe von Feldern, die auf Grundlage der Typen und Typbeziehungen in Ihrem Schema automatisch generiert werden.Data Connect Diese Felder werden von lokalen Tools generiert, wenn Sie Ihr Schema bearbeiten.

Mit generierten Feldern können Sie immer komplexere Abfragen implementieren, vom Abrufen einzelner oder mehrerer Datensätze aus einzelnen Tabellen bis hin zu mehreren Datensätzen aus verknüpften Tabellen.

Angenommen, Ihr Schema enthält einen Typ Movie und einen zugehörigen Typ Actor. Data Connect generiert die Felder movie, movies, actors_on_movies und weitere.

Mit dem Feld
movie abfragen

Das Feld movie stellt einen einzelnen Datensatz in der Tabelle Movie dar.

Mit diesem Feld können Sie einen einzelnen Film anhand seines Schlüssels abfragen.

query GetMovie($myKey: Movie_Key!) {
  movie(key: $myKey) { title }
}

Mit dem Feld
movies abfragen

Das Feld movies stellt eine Liste von Datensätzen in der Tabelle Movie dar.

Mit diesem Feld können Sie mehrere Filme abfragen, z. B. alle Filme eines bestimmten Jahres.

query GetMovies($myYear: Int!) {
  movies(where: { year: { eq: $myYear } }) { title }
}

Mit dem Feld
actors_on_movies abfragen

Das Feld actors_on_movies stellt eine Liste von Datensätzen dar, die die Tabellen Actor und Movie verbinden. Mit diesem Feld können Sie alle Schauspieler abfragen, die mit einem bestimmten Film in Verbindung stehen.

Mit diesem Feld können Sie alle Schauspieler abfragen, die mit einem bestimmten Film in Verbindung stehen.

  query GetActorsOnMovie($myKey: Movie_Key!) {
    actors_on_movies(where: { movie: { key: { eq: $myKey } } }) {
      actor { name }
    }
  }

Wichtige Elemente einer Anfrage

Data Connect-Abfragen sind GraphQL-Abfragen mit Data Connect-Erweiterungen. Genau wie bei einer regulären GraphQL-Abfrage können Sie einen Vorgangsnamen und eine Liste von GraphQL-Variablen definieren.

Data Connect erweitert GraphQL-Abfragen mit benutzerdefinierten Direktiven wie @auth.

Die folgende Abfrage enthält also:

  • Eine query-Typdefinition
  • Name eines ListMoviesByGenre-Vorgangs (Abfrage)
  • Ein einzelnes Abfrageargument, hier eine $genre-Variable vom Typ String
  • Eine einzelne Anweisung: @auth.
  • Ein einzelnes Feld: movies.
query ListMoviesByGenre($genre: String!) @auth(level: PUBLIC) {
  movies(where: { genre: { eq: $genre } }) {
    id
    title
  }
}

Für jedes Abfrageargument ist eine Typdeklaration, ein integrierter Typ wie String oder ein benutzerdefinierter, schemadefinierter Typ wie Movie erforderlich.

In diesem Leitfaden wird die Signatur von immer komplexeren Anfragen untersucht. Zum Schluss werden leistungsstarke, prägnante Beziehungs-Ausdrücke vorgestellt, mit denen Sie Ihre bereitstellbaren Abfragen erstellen können.

Wichtige Skalare in Abfragen

Zuerst aber ein Hinweis zu wichtigen Skalaren.

Data Connect definiert einen speziellen Schlüssel-Skalar, um Primärschlüssel jeder Tabelle darzustellen, die durch {TableType}_Key identifiziert werden. Es handelt sich um ein JSON-Objekt mit Primärschlüsselwerten.

Sie rufen wichtige Skalare als Antwort ab, die von den meisten automatisch generierten Lesefeldern zurückgegeben wird, oder natürlich aus Abfragen, in denen Sie alle Felder abgerufen haben, die zum Erstellen des Skalar-Schlüssels erforderlich sind.

Für automatische Einzelabfragen wie movie in unserem laufenden Beispiel wird ein Schlüsselargument unterstützt, das einen Schlüssel-Skalarwert akzeptiert.

Sie können einen Schlüssel-Skalar als Literal übergeben. Sie können jedoch Variablen definieren, um wichtige Skalare als Eingabe zu übergeben.

Abfrage

query GetMovie($myKey: Movie_Key!) {
  movie(key: $myKey) { title }
}
    

Antwort

{
  "data": {
    "movie": {
      "title": "Example Movie Title"
    }
  }
}
    

Diese können in der JSON-Anfrage so (oder in anderen Serialisierungsformaten) angegeben werden:

{
  # 
  "variables": {
    "myKey": {"id": "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"}
  }
}

Dank des benutzerdefinierten Skalar-Parsings kann ein Movie_Key auch mit 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.

Einfache Abfragen schreiben

Sie können mit dem Schreiben von Abfragen beginnen, um einzelne Datensätze aus Ihrer Datenbank abzurufen, oder Datensätze aus einer Tabelle auflisten. Dabei haben Sie die Möglichkeit, die Ergebnisse zu begrenzen und zu sortieren.

Einzelne Datensätze abrufen

Bei der einfachsten Abfrage wird ein einzelner Datensatz nach ID abgerufen. In Ihrer Abfrage wird das automatisch generierte Feld movie verwendet.

Abfrage

query GetMovieById($id: UUID!) @auth(level: PUBLIC) {
  movie(id: $id) {
    id
    title
    imageUrl
    genre
  }
}
    

Antwort

{
  "data": {
    "movie": {
      "id": "some-uuid",
      "title": "Example Movie Title",
      "imageUrl": "https://example.com/movie.jpg",
      "genre": "Action"
    }
  }
}
    

Alle Datensätze in einer Tabelle abrufen

Wenn Sie eine Teilmenge von Feldern für die vollständige Liste der Filme aus der Tabelle Movies abrufen möchten, wird in Ihrer Abfrage das automatisch generierte Feld movies verwendet. Ihre Implementierung könnte so aussehen:

Abfrage

query ListMovies @auth(level: PUBLIC) {
  movies {
    id
    title
    imageUrl
    genre
  }
}
    

Antwort

{
  "data": {
    "movies": [
      {
        "id": "some-uuid",
        "title": "Example Movie Title",
        "imageUrl": "https://example.com/movie.jpg",
        "genre": "Action"
      },
      {
        "id": "another-uuid",
        "title": "Another Movie Title",
        "imageUrl": "https://example.com/another-movie.jpg",
        "genre": "Comedy"
      }
    ]
  }
}
    

Operatoren orderBy, limit und offset verwenden

Natürlich ist es nur begrenzt nützlich, alle Datensätze aus einer Tabelle aufzulisten.

Sie können Ergebnisse sortieren und paginieren. Diese Argumente werden akzeptiert, aber nicht in den Ergebnissen zurückgegeben.

Hier werden die Titel der zehn Filme mit der höchsten Bewertung abgerufen.

Abfrage

query MoviesTop10 {
  movies(orderBy: [{ rating: DESC }], limit: 10) {
    # graphql: list the fields from the results to return
    title
  }
}
    

Antwort

{
  "data": {
    "movies": [
      { "title": "Top Movie 1" },
      { "title": "Top Movie 2" },
      { "title": "Top Movie 3" }
      // ... other 7 movies
    ]
  }
}
    

Möglicherweise möchten Sie Zeilen ab einem bestimmten Offset abrufen, z. B. Filme 11 bis 20, sortiert nach Bewertung.

Abfrage

query Movies11to20 {
  movies(orderBy: [{ rating: DESC }], limit: 10, offset: 10) {
    # graphql: list the fields from the results to return
    title
  }
}
    

Antwort

{
  "data": {
    "movies": [
      { "title": "Movie 11" },
      { "title": "Movie 12" },
      { "title": "Movie 13" }
      // ... other 7 movies
    ]
  }
}
    

Aliasse in Abfragen verwenden

Data Connect unterstützt GraphQL-Aliasing in Abfragen. Mit Aliasen 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 effizienten Anfrage an den Server angewendet werden. So werden effektiv mehrere „Unterabfragen“ gleichzeitig ausgeführt. Um Namenskonflikte im zurückgegebenen Dataset zu vermeiden, verwenden Sie Aliase, um die Unterabfragen zu unterscheiden.

Hier ist eine Abfrage, in der in einem Ausdruck die Aliase mostPopular und leastPopular verwendet werden.

Abfrage

query ReviewPopularitySpread($genre: String) {
  mostPopular: review(
    first: {
      where: {genre: {eq: $genre}},
      orderBy: {popularity: DESC}
    }
  ),
  leastPopular: review(
    last: {
      where: {genre: {eq: $genre}},
      orderBy: {popularity: DESC}
    }
  )
}
    

Antwort

{
  "data": {
    "mostPopular": [
      { "popularity": 9 }
    ],
    "leastPopular": [
      { "popularity": 1 }
    ]
  }
}
    

Abfragefilter verwenden

Data Connect-Abfragen werden allen gängigen SQL-Filtern und Sortiervorgängen zugeordnet.

Mit where und orderBy filtern

Gibt alle übereinstimmenden Zeilen aus der Tabelle (und den verschachtelten Zuordnungen) zurück. Gibt ein leeres Array zurück, wenn keine Datensätze dem Filter entsprechen.

Abfrage

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
  }
}
    

Antwort

{
  "data": {
    "mostPopular": [
      {
        "id": "some-uuid",
        "title": "Example Movie Title",
        "genre": "Action",
        "description": "A great movie"
      }
    ]
  }
}
    

Nach NULL-Werten filtern

Mit dem Operator isNull können Sie auf null-Werte testen.

Abfrage

query ListMoviesWithoutDescription {
  movies(where: { description: { isNull: true }}) {
    id
    title
  }
}
    

Antwort

{
  "data": {
    "movies": [
      {
        "id": "some-uuid",
        "title": "Example Movie Title"
      },
      {
        "id": "another-uuid",
        "title": "Another Movie Title"
      }
    ]
  }
}
    

Weitere Operatoren finden Sie im Referenzhandbuch für Eingabeobjekttypen.

Mit Wertvergleichen filtern

Mit Operatoren wie lt (kleiner als) und ge (größer als oder gleich) können Sie Werte in Ihren Abfragen vergleichen.

Abfrage

query ListMoviesByRating($minRating: Int!, $maxRating: Int!) {
  movies(where: { rating: { ge: $minRating, lt: $maxRating }}) {
    id
    title
  }
}
    

Antwort

{
  "data": {
    "movies": [
      {
        "id": "some-uuid",
        "title": "Example Movie Title"
      },
      {
        "id": "another-uuid",
        "title": "Another Movie Title"
      }
    ]
  }
}
    

Mit den Operatoren includes und excludes für Arrayfelder filtern

Sie können prüfen, ob ein Arrayfeld ein bestimmtes Element enthält.

Das folgende Beispiel veranschaulicht den Operator includes.

Data Connect unterstützt includesAll, excludes, excludesAll und mehr. Alle Operatoren für Ganzzahlen, Strings, Datumsangaben und andere Datentypen finden Sie in der Referenzdokumentation unter den _ListFilter-Überschriften.

Abfrage

query ListMoviesByTag($tag: String!) {
  movies(where: { tags: { includes: $tag }}) {
    # graphql: list the fields from the results to return
    id
    title
  }
}
    

Antwort

{
  "data": {
    "movies": [
      {
        "id": "some-uuid",
        "title": "Example Movie Title"
      }
    ]
  }
}
    

Mit String-Operationen und regulären Ausdrücken filtern

Für Ihre Abfragen können Sie die üblichen String-Such- und Vergleichsvorgänge verwenden, einschließlich regulärer Ausdrücke. Hinweis: Aus Effizienzgründen werden hier mehrere Vorgänge gebündelt und mit Aliasen eindeutig gemacht.

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}}) {...}
}

Filtern mit der Operatorlogik _or, _and, _not

Verwenden Sie _or für komplexere Logik. Data Connect unterstützt auch die Operatoren _and und _not.

Abfrage

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
  }
}
    

Antwort

{
  "data": {
    "movies": [
      { "title": "Movie Title 1" },
      { "title": "Movie Title 2" }
    ]
  }
}
    

Relationale Abfragen schreiben

Mit Data Connect-Abfragen kann auf Daten auf Grundlage der Beziehungen zwischen Tabellen zugegriffen werden. Sie können die in Ihrem Schema definierten Objekt- (1:1) oder Array-Beziehungen (1:n) verwenden, um verschachtelte Abfragen zu erstellen. So können Sie Daten für einen Typ zusammen mit Daten aus einem verschachtelten oder verknüpften Typ abrufen.

Für solche Abfragen wird die magische Syntax Data Connect _on_ und _via in generierten Lesefeldern verwendet.

Sehen Sie sich das Beispielschema an.

Viele zu eins

Sehen wir uns nun eine Abfrage an, um die _on_-Syntax zu veranschaulichen.

Abfrage

query MyReviews @auth(level: USER) {
  user(key: {id_expr: "auth.uid"}) {
    reviews: reviews_on_user {
      movie { name }
      rating
    }
  }
}
    

Antwort

{
  "data": {
    "user": {
      "reviews": [
        {
          "movie": { "name": "Movie Title" },
          "rating": 5
        }
      ]
    }
  }
}
    

Einzelgespräch

Sie können eine 1:1-Abfrage mit der _on_-Syntax schreiben.

Abfrage

query GetMovieMetadata($id: UUID!) @auth(level: PUBLIC) {
  movie(id: $id) {
    movieMetadatas_on_movie {
      director
    }
  }
}
    

Antwort

{
  "data": {
    "movie": {
      "movieMetadatas_on_movie": {
        "director": "Some Director"
      }
    }
  }
}
    

Viele-zu-viele

Bei Many-to-Many-Abfragen wird die _via_-Syntax verwendet. Bei einer Many-to-Many-Abfrage werden möglicherweise Schauspieler für einen bestimmten Film abgerufen.

Abfrage

query MoviesActors($id: UUID!) @auth(level: USER) {
  movie(id: $id) {
     actors: actors_via_MovieActors {
        name
     }
  }
}
    

Antwort

{
  "data": {
    "movie": {
      "actors": [
        {
          "name": "Actor Name"
        }
      ]
    }
  }
}
    

Wir können aber eine komplexere Abfrage mit Aliasen schreiben, um nach role zu filtern und Schauspieler und zugehörige Filme in den Ergebnissen mainActors und supportingActors abzurufen. Da es sich um eine Many-to-Many-Beziehung handelt, wird die _via_-Syntax verwendet.

Abfrage

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
    }
  }
}
    

Antwort

{
  "data": {
    "movie": {
      "mainActors": [
        {
          "name": "Main Actor Name"
        }
      ],
      "supportingActors": [
        {
          "name": "Supporting Actor Name"
        }
      ]
    },
    "actor": {
      "mainRoles": [
        {
          "title": "Main Role Movie Title"
        }
      ],
      "supportingRoles": [
        {
          "title": "Supporting Role Movie Title"
        }
      ]
    }
  }
}
    

Aggregationsabfragen

Was sind Aggregate und warum sollte man sie verwenden?

Mit Aggregatfeldern können Sie Berechnungen für eine Liste von Ergebnissen durchführen. Mit Aggregatfeldern haben Sie beispielsweise folgende Möglichkeiten:

  • Durchschnittliche Bewertung einer Rezension ermitteln
  • Gesamtkosten der Artikel in einem Einkaufswagen ermitteln
  • Produkte mit der höchsten oder niedrigsten Bewertung finden
  • Anzahl der Produkte in Ihrem Geschäft zählen

Aggregationen werden auf dem Server ausgeführt. Das bietet eine Reihe von Vorteilen gegenüber der clientseitigen Berechnung:

  • Schnellere App-Leistung, da clientseitige Berechnungen vermieden werden
  • Geringere Kosten für den Daten-Egress, da Sie nur die aggregierten Ergebnisse und nicht alle Eingaben senden
  • Verbesserte Sicherheit, da Sie Clients Zugriff auf aggregierte Daten anstelle des gesamten Datensatzes gewähren können

Beispielschema für Aggregate

In diesem Abschnitt verwenden wir ein Beispielschema für einen Onlineshop, das sich gut eignet, um die Verwendung von Aggregaten zu erläutern:

  type Product @table {
    name: String!
    manufacturer: String!
    quantityInStock: Int!
    price: Float!
    expirationDate: Date
  }

Einfache Aggregate

_count für alle Felder

Das einfachste aggregierte Feld ist _count. Es gibt zurück, wie viele Zeilen Ihrer Abfrage entsprechen. Für jedes Feld in Ihrem Typ generiert Data Connect entsprechende aggregierte Felder, die vom Feldtyp abhängen.

Abfrage

query CountProducts {
  products {
    _count
  }
}

Antwort
one

Wenn Sie beispielsweise fünf Produkte in Ihrer Datenbank haben, sieht das Ergebnis so aus:

{
  "products": [
    {
    "_count": 5
    }
  ]
}

Alle Felder haben ein <field>_count-Feld, in dem gezählt wird, wie viele Zeilen einen Wert ungleich null in diesem Feld haben.

Abfrage

query CountProductsWithExpirationDate {
  products {
    expirationDate_count
  }
}

Antwort
field_count

Wenn Sie beispielsweise drei Produkte mit einem Ablaufdatum haben, sieht das Ergebnis so aus:

{
  "products": [
    {
    "expirationDate_count": 3
    }
  ]
}
_min, _max, _sum und _avg für numerische Felder

Numerische Felder (int, float, int64) haben auch <field>_min, <field>_max, <field>_sum und <field>_avg.

Abfrage

query NumericAggregates {
  products {
  quantityInStock_max
  price_min
  price_avg
  quantityInStock_sum
  }
}

Antwort
_min _max _sum _avg

Angenommen, Sie haben die folgenden Produkte:

  • Produkt A: quantityInStock: 10, price: 2.99
  • Produkt B: quantityInStock: 5, price: 5.99
  • Produkt C: quantityInStock: 20, price: 1.99

Das Ergebnis wäre:

{
  "products": [
    {
    "quantityInStock_max": 20,
    "price_min": 1.99,
    "price_avg": 3.6566666666666666,
    "quantityInStock_sum": 35
    }
  ]
}
_min und _max für Datumsangaben und Zeitstempel

Datums- und Zeitstempelfelder haben <field>_min und <field>_max.

Abfrage

query DateAndTimeAggregates {
  products {
  expirationDate_max
  expirationDate_min
  }
}

Antwort
_min _maxdatetime

Angenommen, Sie haben die folgenden Ablaufdaten:

  • Produkt A: 2024-01-01
  • Produkt B: 2024-03-01
  • Produkt C: 2024-02-01

Das Ergebnis wäre:

{
  "products": [
    {
    "expirationDate_max": "2024-03-01",
    "expirationDate_min": "2024-01-01"
    }
  ]
}

Distinct

Mit dem Argument distinct können Sie alle eindeutigen Werte für ein Feld (oder eine Kombination von Feldern) abrufen. Beispiel:

Abfrage

query ListDistinctManufacturers {
  products(distinct: true) {
    manufacturer
  }
}

Antwort
distinct

Angenommen, Sie haben die folgenden Hersteller:

  • Produkt A: manufacturer: "Acme"
  • Produkt B: manufacturer: "Beta"
  • Produkt C: manufacturer: "Acme"

Das Ergebnis wäre:

{
  "products": [
    { "manufacturer": "Acme" },
    { "manufacturer": "Beta" }
  ]
}

Sie können das distinct-Argument auch für aggregierte Felder verwenden, um stattdessen die einzelnen Werte zu aggregieren. Beispiel:

Abfrage

query CountDistinctManufacturers {
  products {
    manufacturer_count(distinct: true)
  }
}

Antwort
distinctonaggregate

Angenommen, Sie haben die folgenden Hersteller:

  • Produkt A: manufacturer: "Acme"
  • Produkt B: manufacturer: "Beta"
  • Produkt C: manufacturer: "Acme"

Das Ergebnis wäre:

{
  "products": [
    {
    "manufacturer_count": 2
    }
  ]
}

Gruppierte Aggregate

Sie führen eine gruppierte Aggregation durch, indem Sie eine Kombination aus aggregierten und nicht aggregierten Feldern für einen Typ auswählen. Dadurch werden alle übereinstimmenden Zeilen mit demselben Wert für die nicht aggregierten Felder gruppiert und die aggregierten Felder für diese Gruppe berechnet. Beispiel:

Abfrage

query MostExpensiveProductByManufacturer {
  products {
  manufacturer
  price_max
  }
}

Antwort
groupedaggregates

Angenommen, Sie haben die folgenden Produkte:

  • Produkt A: manufacturer: "Acme", price: 2.99
  • Produkt B: manufacturer: "Beta", price: 5.99
  • Produkt C: manufacturer: "Acme", price: 1.99

Das Ergebnis wäre:

{
  "products": [
    { "manufacturer": "Acme", "price_max": 2.99 },
    { "manufacturer": "Beta", "price_max": 5.99 }
  ]
}
having und where mit gruppierten Aggregaten

Sie können auch das Argument having und where verwenden, um nur Gruppen zurückzugeben, die ein bestimmtes Kriterium erfüllen.

  • Mit having können Sie Gruppen nach ihren aggregierten Feldern filtern.
  • Mit where können Sie die Zeilen anhand von Feldern filtern, die keine Aggregate sind.

Abfrage

query FilteredMostExpensiveProductByManufacturer {
  products(having: {price_max: {ge: 2.99}}) {
  manufacturer
  price_max
  }
}

Antwort
havingwhere

Angenommen, Sie haben die folgenden Produkte:

  • Produkt A: manufacturer: "Acme", price: 2.99
  • Produkt B: manufacturer: "Beta", price: 5.99
  • Produkt C: manufacturer: "Acme", price: 1.99

Das Ergebnis wäre:

{
  "products": [
    { "manufacturer": "Acme", "price_max": 2.99 },
    { "manufacturer": "Beta", "price_max": 5.99 }
  ]
}

Tabellenübergreifende Aggregationen

Aggregatfelder können zusammen mit generierten 1:n-Beziehungsfeldern verwendet werden, um komplexe Fragen zu Ihren Daten zu beantworten. Hier ist ein geändertes Schema mit einer separaten Tabelle, Manufacturer, die wir in Beispielen verwenden können:

  type Product @table {
    name: String!
    manufacturer: Manufacturer!
    quantityInStock: Int!
    price: Float!
    expirationDate: Date
  }

  type Manufacturer @table {
    name: String!
    headquartersCountry: String!
  }

Jetzt können wir zusammengefasste Felder verwenden, um beispielsweise herauszufinden, wie viele Produkte ein Hersteller herstellt:

Abfrage

query GetProductCount($id: UUID) {
  manufacturers {
    name
    products_on_manufacturer {
      _count
    }
  }
}

Antwort
aggregatesacrosstables

Angenommen, Sie haben die folgenden Hersteller:

  • Hersteller A: name: "Acme", products_on_manufacturer: 2
  • Hersteller B: name: "Beta", products_on_manufacturer: 1

Das Ergebnis wäre:

{
  "manufacturers": [
    { "name": "Acme", "products_on_manufacturer": { "_count": 2 } },
    { "name": "Beta", "products_on_manufacturer": { "_count": 1 } }
  ]
}

Erweiterte Abfragen schreiben: query-Felder verwenden, um Daten in mehrstufigen Vorgängen zu lesen

Es gibt viele Situationen, in denen Sie während der Ausführung einer Mutation auf Ihre Datenbank zugreifen möchten, um vorhandene Daten zu suchen und zu überprüfen, bevor Sie beispielsweise Einfügungen oder Aktualisierungen vornehmen. Mit diesen Optionen werden Roundtrip-Vorgänge und damit Kosten eingespart.

Data Connect unterstützt diese Funktion. Weitere Informationen finden Sie unter Vorgänge mit mehreren Schritten.

Nächste Schritte

Folgendes könnte Sie interessieren: