Firebase Data Connect umożliwia tworzenie łączników do instancji PostgreSQL zarządzanych za pomocą Google Cloud SQL. Te konektory to kombinacje zapytań i mutacji, które umożliwiają korzystanie z danych ze schematu.
W przewodniku dla początkujących przedstawiliśmy schemat aplikacji do oceniania filmów w PostgreSQL.
W tym przewodniku przedstawiliśmy też operacje administracyjne, które można wdrożyć i wykonywać ad hoc, w tym zapytania.
- Zapytania do wdrożenia to zapytania, które implementujesz w celu wywoływania z aplikacji klienckich za pomocą zdefiniowanych przez Ciebie punktów końcowych interfejsu API. Łączysz je w łącznik wdrożony na serwerze. Data Connect narzędzie generuje pakiety SDK klienta
na podstawie Twojego interfejsu API. Wdrożone zapytania nie są chronione przez zasady IAM, więc pamiętaj, aby zabezpieczyć je za pomocą dyrektywy Data Connect
@auth
. - Zapytania administracyjne ad hoc są uruchamiane w środowiskach z uprawnieniami do odczytywania danych. Możesz je tworzyć i wykonywać w konsoli Firebase lub w lokalnych środowiskach deweloperskich za pomocą naszego rozszerzenia Data Connect VS Code.
W tym przewodniku znajdziesz szczegółowe informacje o zapytaniach, które można wdrożyć.
Funkcje zapytań Data Connect
Data Connect umożliwia wykonywanie podstawowych zapytań na wszystkie sposoby, jakich można oczekiwać w przypadku bazy danych PostgreSQL.
Dzięki rozszerzeniom Data Connect do GraphQL możesz jednak wdrażać zaawansowane zapytania, aby tworzyć szybsze i wydajniejsze aplikacje:
- Używaj skalarów kluczy zwracanych przez wiele operacji, aby uprościć powtarzające się operacje na rekordach.
- Wykonywanie zapytań w trakcie wieloetapowych operacji mutacji w celu wyszukiwania danych, co pozwala zaoszczędzić wiersze kodu i podróże do serwera.
Używanie wygenerowanych pól do tworzenia zapytań
Operacje Data Connect rozszerzą zestaw pól automatycznie wygenerowanych Data Connect na podstawie typów i relacji między typami w schemacie. Pola te są generowane przez narzędzia lokalne za każdym razem, gdy edytujesz schemat.
Wygenerowanych pól możesz używać do wdrażania coraz bardziej złożonych zapytań, od pobierania pojedynczych lub wielu rekordów z pojedynczych tabel po pobieranie wielu rekordów z powiązanych tabel.Załóżmy, że schemat zawiera typ Movie
i powiązany z nim typ Actor
.
Data Connect generuje pola movie
, movies
, actors_on_movies
i inne.
Zapytanie z polem
movie
Pole |
Użyj tego pola, aby wysłać zapytanie o jeden film na podstawie jego klucza. query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } } |
Zapytanie z polem
movies
Pole |
Użyj tego pola, aby wysłać zapytanie dotyczące wielu filmów, np. wszystkich filmów z danego roku. query GetMovies($myYear: Int!) { movies(where: { year: { eq: $myYear } }) { title } } |
Zapytanie z polem
actors_on_movies
Pole |
Użyj tego pola, aby wysłać zapytanie o wszystkich aktorów powiązanych z danym filmem. query GetActorsOnMovie($myKey: Movie_Key!) { actors_on_movies(where: { movie: { key: { eq: $myKey } } }) { actor { name } } } |
Podstawowe elementy zapytania
Zapytania Data Connect to zapytania GraphQL z rozszerzeniami Data Connect. Podobnie jak w przypadku zwykłego zapytania GraphQL możesz zdefiniować nazwę operacji i listę zmiennych GraphQL.
Data Connect rozszerza zapytania GraphQL o niestandardowe dyrektywy, takie jak @auth
.
Zapytanie:
- Definicja typu
query
- Nazwa operacji (zapytania)
ListMoviesByGenre
- Jeden argument zapytania, w tym przypadku zmienna
$genre
typuString
- Jedna dyrektywa,
@auth
. - jedno pole
movies
,
query ListMoviesByGenre($genre: String!) @auth(level: PUBLIC) {
movies(where: { genre: { eq: $genre } }) {
id
title
}
}
Każdy argument zapytania wymaga deklaracji typu, wbudowanego typu, takiego jak String
, lub niestandardowego typu zdefiniowanego w schemacie, takiego jak Movie
.
W tym przewodniku przyjrzymy się sygnaturom coraz bardziej złożonych zapytań. Na koniec przedstawimy Ci zwięzłe wyrażenia relacji, których możesz używać do tworzenia zapytań gotowych do wdrożenia.
Kluczowe wartości skalarne w zapytaniach
Najpierw jednak uwaga na temat kluczowych wartości skalarnych.
Data Connect definiuje specjalny skalar klucza, który reprezentuje klucze podstawowe każdej tabeli, identyfikowane przez {TableType}_Key. Jest to obiekt JSON zawierający wartości klucza podstawowego.
Kluczowe wartości skalarne możesz pobierać jako odpowiedź zwracaną przez większość automatycznie generowanych pól odczytu lub oczywiście z zapytań, w których pobrano wszystkie pola potrzebne do utworzenia klucza skalarnego.
Pojedyncze zapytania automatyczne, takie jak movie
w naszym przykładzie, obsługują argument klucza, który akceptuje skalar klucza.
Skalar klucza możesz przekazać jako literał. Możesz jednak zdefiniować zmienne, aby przekazywać skalarne klucze dostępu jako dane wejściowe.
Zapytanie
query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } }
Odpowiedź
{ "data": { "movie": { "title": "Example Movie Title" } } }
Możesz je podać w żądaniu JSON w ten sposób (lub w innych formatach serializacji):
{
# …
"variables": {
"myKey": {"id": "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"}
}
}
Dzięki niestandardowej analizie skalarnej obiekt Movie_Key
można też utworzyć za pomocą składni obiektu, która może zawierać zmienne. Jest to przydatne głównie wtedy, gdy z jakiegoś powodu chcesz podzielić poszczególne komponenty na różne zmienne.
Tworzenie podstawowych zapytań
Możesz zacząć pisać zapytania, aby pobierać poszczególne rekordy z bazy danych, lub wyświetlać listę rekordów z tabeli z opcją ograniczenia i sortowania wyników.
Pobieranie poszczególnych rekordów
Najprostsze zapytanie pobiera pojedynczy rekord według identyfikatora. Zapytanie będzie używać wygenerowanego automatycznie pola movie
.
Zapytanie
query GetMovieById($id: UUID!) @auth(level: PUBLIC) { movie(id: $id) { id title imageUrl genre } }
Odpowiedź
{ "data": { "movie": { "id": "some-uuid", "title": "Example Movie Title", "imageUrl": "https://example.com/movie.jpg", "genre": "Action" } } }
Pobieranie wszystkich rekordów w tabeli
Aby pobrać podzbiór pól z pełnej listy filmów z tabeli Movies
, zapytanie będzie korzystać z automatycznie wygenerowanego pola movies
, a implementacja może wyglądać tak:
Zapytanie
query ListMovies @auth(level: PUBLIC) { movies { id title imageUrl genre } }
Odpowiedź
{ "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" } ] } }
Używanie operatorów orderBy
, limit
i offset
Wyświetlanie wszystkich rekordów z tabeli ma oczywiście ograniczoną przydatność.
Możesz sortować wyniki i dzielić je na strony. Te argumenty są akceptowane, ale nie są zwracane w wynikach.
W tym przypadku zapytanie zwraca tytuły 10 najwyżej ocenianych filmów.
Zapytanie
query MoviesTop10 { movies(orderBy: [{ rating: DESC }], limit: 10) { # graphql: list the fields from the results to return title } }
Odpowiedź
{ "data": { "movies": [ { "title": "Top Movie 1" }, { "title": "Top Movie 2" }, { "title": "Top Movie 3" } // ... other 7 movies ] } }
Możesz mieć przypadek użycia, w którym chcesz pobrać wiersze z przesunięciem, np. filmy od 11 do 20 posortowane według oceny.
Zapytanie
query Movies11to20 { movies(orderBy: [{ rating: DESC }], limit: 10, offset: 10) { # graphql: list the fields from the results to return title } }
Odpowiedź
{ "data": { "movies": [ { "title": "Movie 11" }, { "title": "Movie 12" }, { "title": "Movie 13" } // ... other 7 movies ] } }
Używanie aliasów w zapytaniach
Data Connect obsługuje w zapytaniach aliasy GraphQL. Za pomocą aliasów możesz zmieniać nazwy danych zwracanych w wynikach zapytania. Pojedyncze zapytanie Data Connect może stosować wiele filtrów lub innych operacji w ramach jednego wydajnego żądania do serwera, co w praktyce oznacza wysyłanie kilku „podzapytań” jednocześnie. Aby uniknąć kolizji nazw w zwróconym zbiorze danych, użyj aliasów do odróżnienia zapytań podrzędnych.
Oto zapytanie, w którym wyrażenie używa aliasów mostPopular
i leastPopular
.
Zapytanie
query ReviewPopularitySpread($genre: String) { mostPopular: review( first: { where: {genre: {eq: $genre}}, orderBy: {popularity: DESC} } ), leastPopular: review( last: { where: {genre: {eq: $genre}}, orderBy: {popularity: DESC} } ) }
Odpowiedź
{ "data": { "mostPopular": [ { "popularity": 9 } ], "leastPopular": [ { "popularity": 1 } ] } }
Używanie filtrów zapytań
Data Connect zapytania są mapowane na wszystkie typowe filtry i operacje porządkowania SQL.
Filtrowanie za pomocą operatorów where
i orderBy
Zwraca wszystkie dopasowane wiersze z tabeli (i zagnieżdżonych powiązań). Zwraca pustą tablicę, jeśli żaden rekord nie pasuje do filtra.
Zapytanie
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 } }
Odpowiedź
{ "data": { "mostPopular": [ { "id": "some-uuid", "title": "Example Movie Title", "genre": "Action", "description": "A great movie" } ] } }
Filtrowanie przez sprawdzanie wartości null
Wartości null
możesz testować za pomocą operatora isNull
.
Zapytanie
query ListMoviesWithoutDescription { movies(where: { description: { isNull: true }}) { id title } }
Odpowiedź
{ "data": { "movies": [ { "id": "some-uuid", "title": "Example Movie Title" }, { "id": "another-uuid", "title": "Another Movie Title" } ] } }
Więcej operatorów znajdziesz w przewodniku po typach obiektów wejściowych.
Filtrowanie za pomocą porównań wartości
W zapytaniach możesz używać operatorów takich jak lt
(mniejsze niż) i ge
(większe lub równe), aby porównywać wartości.
Zapytanie
query ListMoviesByRating($minRating: Int!, $maxRating: Int!) { movies(where: { rating: { ge: $minRating, lt: $maxRating }}) { id title } }
Odpowiedź
{ "data": { "movies": [ { "id": "some-uuid", "title": "Example Movie Title" }, { "id": "another-uuid", "title": "Another Movie Title" } ] } }
Filtrowanie za pomocą operatorów includes
i excludes
w przypadku pól tablicowych
Możesz sprawdzić, czy pole tablicy zawiera określony element.
Poniższy przykład ilustruje działanie operatora includes
.
Data Connect obsługuje includesAll
, excludes
, excludesAll
i inne. Wszystkie operatory dotyczące liczb całkowitych, ciągów znaków, dat i innych typów danych znajdziesz w _ListFilter
nagłówkach dokumentacji referencyjnej.
Zapytanie
query ListMoviesByTag($tag: String!) { movies(where: { tags: { includes: $tag }}) { # graphql: list the fields from the results to return id title } }
Odpowiedź
{ "data": { "movies": [ { "id": "some-uuid", "title": "Example Movie Title" } ] } }
Filtrowanie za pomocą operacji na ciągach znaków i wyrażeń regularnych
Zapytania mogą korzystać z typowych operacji wyszukiwania i porównywania ciągów znaków, w tym z wyrażeń regularnych. Uwaga: w celu zwiększenia wydajności łączysz tutaj kilka operacji i rozróżniasz je za pomocą aliasów.
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}}) {...}
}
Filtrowanie za pomocą operatorów logicznych _or
, _and
i _not
W przypadku bardziej złożonej logiki użyj elementu _or
. Data Connect obsługuje też operatory _and
i _not
.
Zapytanie
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 } }
Odpowiedź
{ "data": { "movies": [ { "title": "Movie Title 1" }, { "title": "Movie Title 2" } ] } }
Tworzenie zapytań relacyjnych
Zapytania Data Connect mogą uzyskiwać dostęp do danych na podstawie relacji między tabelami. Możesz używać relacji obiektów (jeden do jednego) lub tablic (jeden do wielu) zdefiniowanych w schemacie do tworzenia zagnieżdżonych zapytań, czyli pobierania danych jednego typu wraz z danymi z zagnieżdżonego lub powiązanego typu.
Takie zapytania używają magicznej składni Data Connect _on_
i _via
w wygenerowanych polach odczytu.
Pamiętaj, aby zapoznać się z przykładowym schematem.
Wiele do jednego
Przyjrzyjmy się teraz zapytaniu, aby zilustrować _on_
składnię.
Zapytanie
query MyReviews @auth(level: USER) { user(key: {id_expr: "auth.uid"}) { reviews: reviews_on_user { movie { name } rating } } }
Odpowiedź
{ "data": { "user": { "reviews": [ { "movie": { "name": "Movie Title" }, "rating": 5 } ] } } }
Jeden do jednego
Możesz napisać zapytanie typu 1:1, używając składni _on_
.
Zapytanie
query GetMovieMetadata($id: UUID!) @auth(level: PUBLIC) { movie(id: $id) { movieMetadatas_on_movie { director } } }
Odpowiedź
{ "data": { "movie": { "movieMetadatas_on_movie": { "director": "Some Director" } } } }
Wiele do wielu
Zapytania typu „wiele do wielu” korzystają ze składni _via_
. Zapytanie typu wiele-do-wielu może pobrać aktorów dla określonego filmu.
Zapytanie
query MoviesActors($id: UUID!) @auth(level: USER) { movie(id: $id) { actors: actors_via_MovieActors { name } } }
Odpowiedź
{ "data": { "movie": { "actors": [ { "name": "Actor Name" } ] } } }
Możemy jednak napisać bardziej złożone zapytanie z użyciem aliasów, aby filtrować wyniki na podstawie role
i pobrać aktorów i powiązane z nimi filmy w mainActors
i supportingActors
. Ponieważ jest to relacja wiele-do-wielu, używana jest składnia _via_
.
Zapytanie
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 } } }
Odpowiedź
{ "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" } ] } } }
Zapytania agregujące
Czym są agregaty i dlaczego warto ich używać?
Pola agregacji umożliwiają wykonywanie obliczeń na liście wyników. W przypadku pól zbiorczych możesz na przykład:
- Znajdowanie średniej oceny
- Sprawdzanie łącznego kosztu produktów w koszyku
- Znajdowanie produktu z najwyższą lub najniższą oceną
- Sprawdź liczbę produktów w sklepie
Agregacje są wykonywane na serwerze, co ma wiele zalet w porównaniu z obliczaniem ich po stronie klienta:
- szybsze działanie aplikacji (dzięki unikaniu obliczeń po stronie klienta);
- Niższe koszty przesyłania danych (ponieważ wysyłasz tylko zagregowane wyniki, a nie wszystkie dane wejściowe)
- większe bezpieczeństwo (ponieważ możesz przyznawać klientom dostęp do zagregowanych danych zamiast do całego zbioru danych);
Przykładowy schemat danych zbiorczych
W tej sekcji przejdziemy do przykładowego schematu sklepu, który dobrze ilustruje, jak używać agregatów:
type Product @table {
name: String!
manufacturer: String!
quantityInStock: Int!
price: Float!
expirationDate: Date
}
Proste agregacje
_count dla wszystkich pól
Najprostszym polem agregacji jest _count
. Zwraca ono liczbę wierszy pasujących do zapytania. W przypadku każdego pola w typie Data Connectgeneruje odpowiednie pola zbiorcze w zależności od typu pola.
Zapytanie
query CountProducts {
products {
_count
}
}
Odpowiedź one
one
Jeśli na przykład w bazie danych masz 5 produktów, wynik będzie wyglądać tak:
{
"products": [
{
"_count": 5
}
]
}
Wszystkie pola mają pole <field>_count
, które zlicza, ile wierszy ma wartość inną niż null w tym polu.
Zapytanie
query CountProductsWithExpirationDate {
products {
expirationDate_count
}
}
Odpowiedźfield_count
field_count
Jeśli na przykład masz 3 produkty z datą ważności, wynik będzie wyglądać tak:
{
"products": [
{
"expirationDate_count": 3
}
]
}
_min, _max, _sum i _avg w przypadku pól liczbowych
Pola numeryczne (int, float, int64) mają też <field>_min
, <field>_max
,<field>_sum
i <field>_avg
.
Zapytanie
query NumericAggregates {
products {
quantityInStock_max
price_min
price_avg
quantityInStock_sum
}
}
Odpowiedź_min _max _sum _avg
_min _max _sum _avg
Załóżmy, że masz te produkty:
- Produkt A:
quantityInStock: 10
,price: 2.99
- Produkt B:
quantityInStock: 5
,price: 5.99
- Produkt C:
quantityInStock: 20
,price: 1.99
Wynik będzie taki:
{
"products": [
{
"quantityInStock_max": 20,
"price_min": 1.99,
"price_avg": 3.6566666666666666,
"quantityInStock_sum": 35
}
]
}
_min i _max w przypadku dat i sygnatur czasowych
Pola daty i sygnatury czasowej mają wartości <field>_min
i <field>_max
.
Zapytanie
query DateAndTimeAggregates {
products {
expirationDate_max
expirationDate_min
}
}
Odpowiedź_min _maxdatetime
_min _maxdatetime
Załóżmy, że masz te daty ważności:
- Produkt A:
2024-01-01
- Produkt B:
2024-03-01
- Produkt C:
2024-02-01
Wynik będzie taki:
{
"products": [
{
"expirationDate_max": "2024-03-01",
"expirationDate_min": "2024-01-01"
}
]
}
Niepowtarzalne
Argument distinct
umożliwia uzyskanie wszystkich unikalnych wartości w polu (lub kombinacji pól). Przykład:
Zapytanie
query ListDistinctManufacturers {
products(distinct: true) {
manufacturer
}
}
Odpowiedźdistinct
distinct
Załóżmy, że masz tych producentów:
- Produkt A:
manufacturer: "Acme"
- Produkt B:
manufacturer: "Beta"
- Produkt C:
manufacturer: "Acme"
Wynik będzie taki:
{
"products": [
{ "manufacturer": "Acme" },
{ "manufacturer": "Beta" }
]
}
W przypadku pól agregacji możesz też użyć argumentu distinct
, aby zamiast tego agregować odrębne wartości. Przykład:
Zapytanie
query CountDistinctManufacturers {
products {
manufacturer_count(distinct: true)
}
}
Odpowiedźdistinctonaggregate
distinctonaggregate
Załóżmy, że masz tych producentów:
- Produkt A:
manufacturer: "Acme"
- Produkt B:
manufacturer: "Beta"
- Produkt C:
manufacturer: "Acme"
Wynik będzie taki:
{
"products": [
{
"manufacturer_count": 2
}
]
}
Agregacje pogrupowane
Agregację grupową możesz przeprowadzić, wybierając kombinację pól agregacji i pól niebędących agregacjami w danym typie. Grupuje ona wszystkie pasujące wiersze, które mają taką samą wartość w polach niezagregowanych, i oblicza pola zagregowane dla tej grupy. Przykład:
Zapytanie
query MostExpensiveProductByManufacturer {
products {
manufacturer
price_max
}
}
Odpowiedźgroupedaggregates
groupedaggregates
Załóżmy, że masz te produkty:
- Produkt A:
manufacturer: "Acme"
,price: 2.99
- Produkt B:
manufacturer: "Beta"
,price: 5.99
- Produkt C:
manufacturer: "Acme"
,price: 1.99
Wynik będzie taki:
{
"products": [
{ "manufacturer": "Acme", "price_max": 2.99 },
{ "manufacturer": "Beta", "price_max": 5.99 }
]
}
having
i where
z pogrupowanymi wartościami zagregowanymi
Możesz też użyć argumentów having
i where
, aby zwracać tylko grupy, które spełniają podane kryteria.
having
umożliwia filtrowanie grup według pól zbiorczych.where
umożliwia filtrowanie wierszy na podstawie pól niezagregowanych.
Zapytanie
query FilteredMostExpensiveProductByManufacturer {
products(having: {price_max: {ge: 2.99}}) {
manufacturer
price_max
}
}
Odpowiedźhavingwhere
havingwhere
Załóżmy, że masz te produkty:
- Produkt A:
manufacturer: "Acme"
,price: 2.99
- Produkt B:
manufacturer: "Beta"
,price: 5.99
- Produkt C:
manufacturer: "Acme"
,price: 1.99
Wynik będzie taki:
{
"products": [
{ "manufacturer": "Acme", "price_max": 2.99 },
{ "manufacturer": "Beta", "price_max": 5.99 }
]
}
Agregacje w tabelach
Pola agregacji można wykorzystywać w połączeniu z wygenerowanymi polami relacji jeden-do-wielu, aby uzyskiwać odpowiedzi na złożone pytania dotyczące danych. Oto zmodyfikowany schemat z osobną tabelą Manufacturer
, której możemy użyć w przykładach:
type Product @table {
name: String!
manufacturer: Manufacturer!
quantityInStock: Int!
price: Float!
expirationDate: Date
}
type Manufacturer @table {
name: String!
headquartersCountry: String!
}
Teraz możemy używać pól zbiorczych do wykonywania takich czynności jak sprawdzanie, ile produktów wytwarza dany producent:
Zapytanie
query GetProductCount($id: UUID) {
manufacturers {
name
products_on_manufacturer {
_count
}
}
}
Odpowiedź aggregatesacrosstables
aggregatesacrosstables
Załóżmy, że masz tych producentów:
- Producent A:
name: "Acme"
,products_on_manufacturer: 2
- Producent B:
name: "Beta"
,products_on_manufacturer: 1
Wynik będzie taki:
{
"manufacturers": [
{ "name": "Acme", "products_on_manufacturer": { "_count": 2 } },
{ "name": "Beta", "products_on_manufacturer": { "_count": 1 } }
]
}
Pisanie zaawansowanych zapytań: używaj pól query
do odczytywania danych w operacjach wieloetapowych.
W wielu sytuacjach możesz chcieć odczytać bazę danych podczas wykonywania mutacji, aby wyszukać i zweryfikować istniejące dane przed wykonaniem np. wstawień lub aktualizacji. Te opcje pozwalają zaoszczędzić operacje w obie strony, a tym samym koszty.
Data Connect obsługuje tę funkcję. Zobacz operacje wieloetapowe.
Dalsze kroki
Może Cię zainteresować:
- Generowanie zapytań do aplikacji za pomocą narzędzi wspomaganych przez AI
- Autoryzowanie zapytań zgodnie z przewodnikiem po autoryzacji
- Wywoływanie zapytań z kodu klienta w przypadku internetu, iOS, Androida i Fluttera.