Firebase Data Connect memungkinkan Anda membuat konektor untuk instance PostgreSQL yang dikelola dengan Google Cloud SQL. Konektor ini adalah kombinasi kueri dan mutasi untuk menggunakan data dari skema Anda.
Panduan memulai memperkenalkan skema aplikasi ulasan film untuk PostgreSQL.
Panduan tersebut juga memperkenalkan operasi administratif yang dapat di-deploy dan ad hoc, termasuk kueri.
- Kueri yang dapat di-deploy adalah kueri yang Anda terapkan untuk dipanggil dari aplikasi
klien, dengan endpoint API yang Anda tentukan. Anda menggabungkannya ke dalam konektor
yang di-deploy ke server. Alat Data Connect membuat SDK klien
berdasarkan API Anda. Kueri yang di-deploy tidak dilindungi oleh kebijakan IAM, jadi pastikan untuk mengamankannya menggunakan direktif Data Connect
@auth
. - Kueri administratif ad hoc dijalankan dari lingkungan yang memiliki hak istimewa untuk membaca data. Anda dapat membuat dan mengeksekusinya di konsol Firebase atau di lingkungan pengembangan lokal menggunakan ekstensi VS Code Data Connect kami.
Panduan ini membahas lebih dalam kueri yang dapat di-deploy.
Fitur kueri Data Connect
Data Connect memungkinkan Anda melakukan kueri dasar dengan semua cara yang Anda harapkan mengingat database PostgreSQL.
Namun, dengan ekstensi Data Connect ke GraphQL, Anda dapat menerapkan kueri lanjutan untuk aplikasi yang lebih cepat dan efisien:
- Gunakan skalar kunci yang ditampilkan oleh banyak operasi untuk menyederhanakan operasi berulang pada kumpulan data
- Lakukan kueri selama operasi mutasi multi-langkah untuk mencari data, sehingga menghemat baris kode dan perjalanan pulang pergi ke server.
Menggunakan kolom yang dibuat untuk membuat kueri
Operasi Data Connect Anda akan memperluas sekumpulan kolom Data Connect yang dibuat secara otomatis berdasarkan jenis dan hubungan jenis dalam skema Anda. Kolom ini dibuat oleh alat lokal setiap kali Anda mengedit skema.
Anda dapat menggunakan kolom yang dibuat untuk menerapkan kueri yang semakin kompleks, mulai dari mengambil satu atau beberapa data dari satu tabel hingga beberapa data dari tabel terkait.Asumsikan skema Anda berisi jenis Movie
dan jenis Actor
terkait.
Data Connect menghasilkan kolom movie
, movies
,
actors_on_movies
, dan lainnya.
Membuat kueri dengan kolom
movie
Kolom |
Gunakan kolom ini untuk membuat kueri satu film berdasarkan kuncinya. query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } } |
Membuat kueri dengan kolom
movies
Kolom |
Gunakan kolom ini untuk membuat kueri beberapa film, misalnya, semua film dengan tahun tertentu. query GetMovies($myYear: Int!) { movies(where: { year: { eq: $myYear } }) { title } } |
Membuat kueri dengan kolom
actors_on_movies
Kolom |
Gunakan kolom ini untuk membuat kueri semua aktor yang terkait dengan film tertentu. query GetActorsOnMovie($myKey: Movie_Key!) { actors_on_movies(where: { movie: { key: { eq: $myKey } } }) { actor { name } } } |
Elemen penting kueri
Kueri Data Connect adalah kueri GraphQL dengan ekstensi Data Connect. Sama seperti kueri GraphQL biasa, Anda dapat menentukan nama operasi dan daftar variabel GraphQL.
Data Connect memperluas kueri GraphQL dengan direktif yang disesuaikan seperti
@auth
.
Jadi, kueri berikut memiliki:
- Definisi jenis
query
- Nama operasi (kueri)
ListMoviesByGenre
- Satu argumen kueri, di sini variabel
$genre
dari jenisString
- Satu arahan,
@auth
. - Satu kolom,
movies
.
query ListMoviesByGenre($genre: String!) @auth(level: PUBLIC) {
movies(where: { genre: { eq: $genre } }) {
id
title
}
}
Setiap argumen kueri memerlukan deklarasi jenis, bawaan seperti String
, atau
jenis yang ditentukan skema kustom seperti Movie
.
Panduan ini akan membahas tanda tangan kueri yang semakin kompleks. Anda akan mengakhiri dengan memperkenalkan ekspresi hubungan yang efektif dan ringkas yang dapat Anda gunakan untuk membuat kueri yang dapat di-deploy.
Skalar utama dalam kueri
Namun sebelumnya, perhatikan skalar utama.
Data Connect menentukan skalar kunci khusus untuk merepresentasikan kunci primer setiap tabel, yang diidentifikasi oleh {TableType}_Key. Objek ini adalah objek JSON dari nilai kunci utama.
Anda mengambil skalar utama sebagai respons yang ditampilkan oleh sebagian besar kolom baca yang dibuat otomatis, atau tentu saja dari kueri tempat Anda mengambil semua kolom yang diperlukan untuk membuat kunci skalar.
Kueri otomatis tunggal, seperti movie
dalam contoh yang sedang berjalan, mendukung argumen
kunci yang menerima skalar kunci.
Anda dapat meneruskan skalar kunci sebagai literal. Namun, Anda dapat menentukan variabel untuk meneruskan skalar kunci sebagai input.
Kueri
query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } }
Respons
{ "data": { "movie": { "title": "Example Movie Title" } } }
Nilai ini dapat diberikan dalam JSON permintaan seperti ini (atau format serialisasi lainnya):
{
# …
"variables": {
"myKey": {"id": "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"}
}
}
Berkat parsing skalar kustom, Movie_Key
juga dapat dibuat menggunakan
sintaksis objek, yang dapat berisi variabel. Hal ini sebagian besar berguna saat Anda ingin
memecah setiap komponen menjadi variabel yang berbeda karena alasan tertentu.
Menulis kueri dasar
Anda dapat mulai menulis kueri untuk mendapatkan setiap catatan dari database, atau mencantumkan catatan dari tabel dengan opsi untuk membatasi dan mengurutkan hasil.
Mengambil data satu per satu
Kueri paling sederhana mendapatkan satu catatan menurut ID. Kueri Anda akan menggunakan kolom movie
yang dihasilkan secara otomatis.
Kueri
query GetMovieById($id: UUID!) @auth(level: PUBLIC) { movie(id: $id) { id title imageUrl genre } }
Respons
{ "data": { "movie": { "id": "some-uuid", "title": "Example Movie Title", "imageUrl": "https://example.com/movie.jpg", "genre": "Action" } } }
Mengambil semua data dalam tabel
Untuk mengambil subset kolom untuk daftar lengkap film dari tabel Movies
, kueri Anda akan menggunakan kolom movies
yang dihasilkan secara otomatis, dan implementasi Anda mungkin terlihat seperti berikut.
Kueri
query ListMovies @auth(level: PUBLIC) { movies { id title imageUrl genre } }
Respons
{ "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" } ] } }
Menggunakan operator orderBy
, limit
, dan offset
Tentu saja, mencantumkan semua data dari tabel memiliki kegunaan yang terbatas.
Anda dapat mengurutkan dan melakukan penomoran halaman pada hasil. Argumen ini diterima, tetapi tidak ditampilkan dalam hasil.
Di sini, kueri mendapatkan judul 10 film teratas berdasarkan rating.
Kueri
query MoviesTop10 { movies(orderBy: [{ rating: DESC }], limit: 10) { # graphql: list the fields from the results to return title } }
Respons
{ "data": { "movies": [ { "title": "Top Movie 1" }, { "title": "Top Movie 2" }, { "title": "Top Movie 3" } // ... other 7 movies ] } }
Anda mungkin memiliki kasus penggunaan untuk mengambil baris dari offset, seperti film 11-20 yang diurutkan berdasarkan rating.
Kueri
query Movies11to20 { movies(orderBy: [{ rating: DESC }], limit: 10, offset: 10) { # graphql: list the fields from the results to return title } }
Respons
{ "data": { "movies": [ { "title": "Movie 11" }, { "title": "Movie 12" }, { "title": "Movie 13" } // ... other 7 movies ] } }
Menggunakan alias dalam kueri
Data Connect mendukung pemberian alias GraphQL dalam kueri. Dengan alias, Anda dapat mengganti nama data yang ditampilkan dalam hasil kueri. Satu kueri Data Connect dapat menerapkan beberapa filter atau operasi kueri lainnya dalam satu permintaan yang efisien ke server, sehingga secara efektif mengeluarkan beberapa "sub-kueri" sekaligus. Untuk menghindari konflik nama dalam set data yang ditampilkan, Anda menggunakan alias untuk membedakan sub-kueri.
Berikut adalah kueri yang menggunakan alias mostPopular
dan
leastPopular
dalam ekspresi.
Kueri
query ReviewPopularitySpread($genre: String) { mostPopular: review( first: { where: {genre: {eq: $genre}}, orderBy: {popularity: DESC} } ), leastPopular: review( last: { where: {genre: {eq: $genre}}, orderBy: {popularity: DESC} } ) }
Respons
{ "data": { "mostPopular": [ { "popularity": 9 } ], "leastPopular": [ { "popularity": 1 } ] } }
Menggunakan filter kueri
Kueri Data Connect dipetakan ke semua filter dan operasi pengurutan SQL umum.
Memfilter dengan where
dengan operator orderBy
Menampilkan semua baris yang cocok dari tabel (dan asosiasi bertingkat). Menampilkan array kosong jika tidak ada data yang cocok dengan filter.
Kueri
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 } }
Respons
{ "data": { "mostPopular": [ { "id": "some-uuid", "title": "Example Movie Title", "genre": "Action", "description": "A great movie" } ] } }
Memfilter dengan menguji nilai null
Anda dapat menguji nilai null
menggunakan operator isNull
.
Kueri
query ListMoviesWithoutDescription { movies(where: { description: { isNull: true }}) { id title } }
Respons
{ "data": { "movies": [ { "id": "some-uuid", "title": "Example Movie Title" }, { "id": "another-uuid", "title": "Another Movie Title" } ] } }
Untuk mengetahui operator lainnya, lihat panduan referensi jenis objek input.
Memfilter dengan perbandingan nilai
Anda dapat menggunakan operator seperti lt
(kurang dari) dan ge
(lebih besar dari atau sama dengan)
untuk membandingkan nilai dalam kueri.
Kueri
query ListMoviesByRating($minRating: Int!, $maxRating: Int!) { movies(where: { rating: { ge: $minRating, lt: $maxRating }}) { id title } }
Respons
{ "data": { "movies": [ { "id": "some-uuid", "title": "Example Movie Title" }, { "id": "another-uuid", "title": "Another Movie Title" } ] } }
Memfilter dengan operator includes
dan excludes
untuk kolom array
Anda dapat menguji apakah kolom array menyertakan item tertentu.
Contoh berikut mengilustrasikan operator includes
.
Data Connect mendukung includesAll
, excludes
, excludesAll
, dan lainnya. Tinjau semua operator tersebut untuk bilangan bulat, string, tanggal, dan jenis data lainnya di judul _ListFilter
dalam dokumentasi referensi.
Kueri
query ListMoviesByTag($tag: String!) { movies(where: { tags: { includes: $tag }}) { # graphql: list the fields from the results to return id title } }
Respons
{ "data": { "movies": [ { "id": "some-uuid", "title": "Example Movie Title" } ] } }
Memfilter dengan operasi string dan ekspresi reguler
Kueri Anda dapat menggunakan operasi perbandingan dan penelusuran string umum, termasuk ekspresi reguler. Perhatikan bahwa untuk efisiensi, Anda menggabungkan beberapa operasi di sini dan membedakannya dengan alias.
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}}) {...}
}
Memfilter dengan logika operator _or
, _and
, _not
Gunakan _or
untuk logika yang lebih kompleks. Data Connect juga mendukung operator _and
dan _not
.
Kueri
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 } }
Respons
{ "data": { "movies": [ { "title": "Movie Title 1" }, { "title": "Movie Title 2" } ] } }
Menulis kueri relasional
Kueri Data Connect dapat mengakses data berdasarkan hubungan antar-tabel. Anda dapat menggunakan hubungan objek (one-to-one) atau array (one-to-many) yang ditentukan dalam skema untuk membuat kueri bertingkat, yaitu mengambil data untuk satu jenis bersama dengan data dari jenis bertingkat atau terkait.
Kueri tersebut menggunakan sintaksis Data Connect _on_
dan _via
ajaib di kolom baca yang dihasilkan.
Jangan lupa untuk meninjau skema contoh.
Many-to-one
Sekarang lihat kueri untuk mengilustrasikan sintaksis _on_
.
Kueri
query MyReviews @auth(level: USER) { user(key: {id_expr: "auth.uid"}) { reviews: reviews_on_user { movie { name } rating } } }
Respons
{ "data": { "user": { "reviews": [ { "movie": { "name": "Movie Title" }, "rating": 5 } ] } } }
Satu lawan satu
Anda dapat menulis kueri satu-ke-satu menggunakan sintaksis _on_
.
Kueri
query GetMovieMetadata($id: UUID!) @auth(level: PUBLIC) { movie(id: $id) { movieMetadatas_on_movie { director } } }
Respons
{ "data": { "movie": { "movieMetadatas_on_movie": { "director": "Some Director" } } } }
Many-to-many
Kueri banyak-ke-banyak menggunakan sintaksis _via_
. Kueri banyak-ke-banyak dapat mengambil aktor untuk film tertentu.
Kueri
query MoviesActors($id: UUID!) @auth(level: USER) { movie(id: $id) { actors: actors_via_MovieActors { name } } }
Respons
{ "data": { "movie": { "actors": [ { "name": "Actor Name" } ] } } }
Namun, kita dapat menulis kueri yang lebih kompleks, menggunakan alias, untuk memfilter berdasarkan role
guna mengambil aktor dan film terkait dalam hasil mainActors
dan
supportingActors
. Karena ini adalah hubungan banyak-ke-banyak, sintaksis _via_
digunakan.
Kueri
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 } } }
Respons
{ "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" } ] } } }
Kueri agregasi
Apa itu gabungan, dan mengapa menggunakannya?
Kolom agregasi memungkinkan Anda melakukan penghitungan pada daftar hasil. Dengan kolom agregasi, Anda dapat melakukan hal-hal seperti:
- Menemukan skor rata-rata ulasan
- Menemukan total biaya item dalam keranjang belanja
- Menemukan produk dengan rating tertinggi atau terendah
- Menghitung jumlah produk di toko Anda
Agregasi dilakukan di server, yang menawarkan sejumlah manfaat dibandingkan menghitungnya di sisi klien:
- Performa aplikasi yang lebih cepat (karena Anda menghindari penghitungan sisi klien)
- Biaya traffic keluar data yang lebih rendah (karena Anda hanya mengirimkan hasil gabungan, bukan semua input)
- Keamanan yang ditingkatkan (karena Anda dapat memberi klien akses ke data gabungan, bukan seluruh set data)
Contoh skema untuk agregat
Di bagian ini, kita akan beralih ke skema contoh etalase, yang cocok untuk menjelaskan cara menggunakan agregat:
type Product @table {
name: String!
manufacturer: String!
quantityInStock: Int!
price: Float!
expirationDate: Date
}
Agregat sederhana
_count untuk semua kolom
Kolom gabungan paling sederhana adalah _count
: kolom ini menampilkan jumlah baris yang cocok dengan kueri Anda. Untuk setiap kolom dalam jenis Anda, Data Connect
membuat kolom gabungan yang sesuai, bergantung pada jenis kolom.
Kueri
query CountProducts {
products {
_count
}
}
Respons one
one
Misalnya, jika Anda memiliki 5 produk dalam database, hasilnya adalah:
{
"products": [
{
"_count": 5
}
]
}
Semua kolom memiliki kolom <field>_count
, yang menghitung jumlah baris yang memiliki
nilai bukan null dalam kolom tersebut.
Kueri
query CountProductsWithExpirationDate {
products {
expirationDate_count
}
}
Responsfield_count
field_count
Misalnya, jika Anda memiliki 3 produk dengan tanggal habis masa berlaku, hasilnya adalah:
{
"products": [
{
"expirationDate_count": 3
}
]
}
_min, _max, _sum, dan _avg untuk kolom numerik
Kolom numerik (int, float, int64) juga memiliki <field>_min
, <field>_max
,
<field>_sum
, dan <field>_avg
.
Kueri
query NumericAggregates {
products {
quantityInStock_max
price_min
price_avg
quantityInStock_sum
}
}
Respons_min _max _sum _avg
_min _max _sum _avg
Misalnya, jika Anda memiliki produk berikut:
- Produk A:
quantityInStock: 10
,price: 2.99
- Produk B:
quantityInStock: 5
,price: 5.99
- Produk C:
quantityInStock: 20
,price: 1.99
Hasilnya adalah:
{
"products": [
{
"quantityInStock_max": 20,
"price_min": 1.99,
"price_avg": 3.6566666666666666,
"quantityInStock_sum": 35
}
]
}
_min dan _max untuk tanggal dan stempel waktu
Kolom tanggal dan stempel waktu memiliki <field>_min
dan <field>_max
.
Kueri
query DateAndTimeAggregates {
products {
expirationDate_max
expirationDate_min
}
}
Respons_min _maxdatetime
_min _maxdatetime
Misalnya, jika Anda memiliki tanggal habis masa berlaku berikut:
- Produk A:
2024-01-01
- Produk B:
2024-03-01
- Produk C:
2024-02-01
Hasilnya adalah:
{
"products": [
{
"expirationDate_max": "2024-03-01",
"expirationDate_min": "2024-01-01"
}
]
}
Distinct
Dengan argumen distinct
, Anda bisa mendapatkan semua nilai unik untuk kolom (atau kombinasi kolom). Contoh:
Kueri
query ListDistinctManufacturers {
products(distinct: true) {
manufacturer
}
}
Responsdistinct
distinct
Misalnya, jika Anda memiliki produsen berikut:
- Produk A:
manufacturer: "Acme"
- Produk B:
manufacturer: "Beta"
- Produk C:
manufacturer: "Acme"
Hasilnya adalah:
{
"products": [
{ "manufacturer": "Acme" },
{ "manufacturer": "Beta" }
]
}
Anda juga dapat menggunakan argumen distinct
pada kolom gabungan untuk menggabungkan nilai unik. Contoh:
Kueri
query CountDistinctManufacturers {
products {
manufacturer_count(distinct: true)
}
}
Responsdistinctonaggregate
distinctonaggregate
Misalnya, jika Anda memiliki produsen berikut:
- Produk A:
manufacturer: "Acme"
- Produk B:
manufacturer: "Beta"
- Produk C:
manufacturer: "Acme"
Hasilnya adalah:
{
"products": [
{
"manufacturer_count": 2
}
]
}
Agregat yang dikelompokkan
Anda melakukan penggabungan yang dikelompokkan dengan memilih campuran kolom gabungan dan non-gabungan pada suatu jenis. Hal ini mengelompokkan semua baris yang cocok yang memiliki nilai yang sama untuk kolom non-agregat, dan menghitung kolom agregat untuk grup tersebut. Contoh:
Kueri
query MostExpensiveProductByManufacturer {
products {
manufacturer
price_max
}
}
Responsgroupedaggregates
groupedaggregates
Misalnya, jika Anda memiliki produk berikut:
- Produk A:
manufacturer: "Acme"
,price: 2.99
- Produk B:
manufacturer: "Beta"
,price: 5.99
- Produk C:
manufacturer: "Acme"
,price: 1.99
Hasilnya adalah:
{
"products": [
{ "manufacturer": "Acme", "price_max": 2.99 },
{ "manufacturer": "Beta", "price_max": 5.99 }
]
}
having
dan where
dengan gabungan yang dikelompokkan
Anda juga dapat menggunakan argumen having
dan where
untuk hanya menampilkan grup yang memenuhi kriteria yang diberikan.
having
memungkinkan Anda memfilter grup berdasarkan kolom gabungannyawhere
memungkinkan Anda memfilter baris berdasarkan kolom non-gabungan.
Kueri
query FilteredMostExpensiveProductByManufacturer {
products(having: {price_max: {ge: 2.99}}) {
manufacturer
price_max
}
}
Responshavingwhere
havingwhere
Misalnya, jika Anda memiliki produk berikut:
- Produk A:
manufacturer: "Acme"
,price: 2.99
- Produk B:
manufacturer: "Beta"
,price: 5.99
- Produk C:
manufacturer: "Acme"
,price: 1.99
Hasilnya adalah:
{
"products": [
{ "manufacturer": "Acme", "price_max": 2.99 },
{ "manufacturer": "Beta", "price_max": 5.99 }
]
}
Agregasi di seluruh tabel
Kolom gabungan dapat digunakan bersama dengan kolom hubungan satu-ke-banyak yang dihasilkan untuk menjawab pertanyaan kompleks tentang data Anda. Berikut adalah skema yang diubah, dengan tabel terpisah, Manufacturer
, yang dapat kita gunakan dalam contoh:
type Product @table {
name: String!
manufacturer: Manufacturer!
quantityInStock: Int!
price: Float!
expirationDate: Date
}
type Manufacturer @table {
name: String!
headquartersCountry: String!
}
Sekarang kita dapat menggunakan kolom agregat untuk melakukan hal-hal seperti menemukan jumlah produk yang dibuat oleh produsen:
Kueri
query GetProductCount($id: UUID) {
manufacturers {
name
products_on_manufacturer {
_count
}
}
}
Respons aggregatesacrosstables
aggregatesacrosstables
Misalnya, jika Anda memiliki produsen berikut:
- Produsen A:
name: "Acme"
,products_on_manufacturer: 2
- Produsen B:
name: "Beta"
,products_on_manufacturer: 1
Hasilnya adalah:
{
"manufacturers": [
{ "name": "Acme", "products_on_manufacturer": { "_count": 2 } },
{ "name": "Beta", "products_on_manufacturer": { "_count": 1 } }
]
}
Menulis kueri lanjutan: menggunakan kolom query
untuk membaca data dalam operasi multi-langkah
Ada banyak situasi saat Anda mungkin ingin membaca database selama eksekusi mutasi untuk mencari dan memverifikasi data yang ada sebelum melakukan, misalnya, penyisipan atau pembaruan. Opsi ini menghemat operasi pulang pergi dan oleh karena itu, menghemat biaya.
Data Connect mendukung fungsi ini. Lihat operasi multi-langkah.
Langkah berikutnya
Anda mungkin tertarik dengan:
- Membuat kueri untuk aplikasi Anda menggunakan alat bantuan AI
- Memberi otorisasi kueri Anda sesuai dengan panduan otorisasi
- Memanggil kueri dari kode klien Anda untuk web, iOS, Android dan Flutter.