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 mutasi.
- Mutasi yang dapat di-deploy adalah mutasi yang Anda terapkan untuk dipanggil dari aplikasi klien di konektor, dengan endpoint API yang Anda tentukan. Data Connect mengintegrasikan autentikasi dan otorisasi ke dalam mutasi ini, serta membuat SDK klien berdasarkan API Anda.
- Mutasi administratif ad hoc dijalankan dari lingkungan yang memiliki hak istimewa untuk mengisi dan mengelola tabel. Anda dapat membuat dan mengeksekusinya di konsol Firebase, dari lingkungan dengan hak istimewa menggunakan Firebase Admin SDK, dan di lingkungan pengembangan lokal menggunakan ekstensi VS Code Data Connect kami.
Panduan ini membahas lebih dalam mutasi yang dapat di-deploy.
Fitur mutasi Data Connect
Data Connect memungkinkan Anda melakukan mutasi dasar dengan semua cara yang Anda harapkan mengingat database PostgreSQL:
- Melakukan operasi CRUD
- Mengelola operasi multi-langkah dengan transaksi
Namun, dengan ekstensi Data Connect ke GraphQL, Anda dapat menerapkan mutasi lanjutan untuk aplikasi yang lebih cepat dan efisien:
- Gunakan skalar kunci yang ditampilkan oleh banyak operasi untuk menyederhanakan operasi berulang pada kumpulan data
- Gunakan nilai server untuk mengisi data dengan operasi yang disediakan oleh server
- 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 menerapkan mutasi
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 mutasi, mulai dari membuat, memperbarui, dan menghapus masing-masing data dalam satu tabel, hingga pembaruan multi-tabel yang lebih kompleks.Asumsikan skema Anda berisi jenis Movie
dan jenis Actor
terkait.
Data Connect menghasilkan kolom movie_insert
,
movie_update
, movie_delete
, dan lainnya.
Mutasi dengan kolom
movie_insert
Kolom |
Gunakan kolom ini untuk membuat satu film. mutation CreateMovie($data: Movie_Data!) { movie_insert(data: $data) { key } } |
Mutasi dengan kolom
movie_update
Kolom |
Gunakan kolom ini untuk memperbarui satu film berdasarkan kuncinya. mutation UpdateMovie($myKey: Movie_Key!, $data: Movie_Data!) { movie_update(key: $myKey, data: $data) { key } } |
Mutasi dengan kolom
movie_delete
Kolom |
Gunakan kolom ini untuk menghapus satu film berdasarkan kuncinya. mutation DeleteMovie($myKey: Movie_Key!) { movie_delete(key: $myKey) { key } } |
Elemen penting mutasi
Mutasi Data Connect adalah mutasi GraphQL dengan ekstensi Data Connect. Sama seperti mutasi GraphQL biasa, Anda dapat menentukan nama operasi dan daftar variabel GraphQL.
Data Connect memperluas kueri GraphQL dengan direktif yang disesuaikan seperti
@auth
dan @transaction
.
Jadi mutasi berikut memiliki:
- Definisi jenis
mutation
- Nama operasi
SignUp
(mutasi) - Argumen operasi
$username
variabel tunggal - Satu arahan,
@auth
- Satu kolom
user_insert
.
mutation SignUp($username: String!) @auth(level: USER) {
user_insert(data: {
id_expr: "auth.uid"
username: $username
})
}
Setiap argumen mutasi memerlukan deklarasi jenis, bawaan seperti String
,
atau jenis yang ditentukan skema kustom seperti Movie
.
Menulis mutasi dasar
Anda dapat mulai menulis mutasi untuk membuat, memperbarui, dan menghapus setiap catatan dari database Anda.
Buat
Mari kita lakukan pembuatan dasar.
# 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
})
}
Atau 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"
})
}
Melakukan update
Berikut info terbarunya. Produser dan sutradara tentu berharap rating rata-rata tersebut sesuai tren.
Kolom movie_update
berisi argumen id
yang diharapkan untuk mengidentifikasi record
dan kolom data
yang dapat Anda gunakan untuk menetapkan nilai dalam pembaruan ini.
mutation UpdateMovie(
$id: UUID!,
$genre: String!,
$rating: Int!,
$description: String!
) {
movie_update(id: $id,
data: {
genre: $genre
rating: $rating
description: $description
})
}
Untuk melakukan beberapa pembaruan, gunakan kolom movie_updateMany
.
# Multiple updates (increase all ratings of a genre)
mutation IncreaseRatingForGenre($genre: String!, $rating: Int!) {
movie_updateMany(
where: { genre: { eq: $genre } },
data:
{
rating: $rating
})
}
Menggunakan operasi penambahan, pengurangan, penambahan di akhir, dan penambahan di awal dengan _update
Saat mutasi _update
dan _updateMany
, Anda dapat menetapkan nilai secara eksplisit di
data:
, tetapi sering kali lebih masuk akal untuk menerapkan operator seperti kenaikan untuk memperbarui
nilai.
Untuk mengubah contoh pembaruan sebelumnya, asumsikan Anda ingin menaikkan rating
film tertentu. Anda dapat menggunakan sintaksis rating_update
dengan operator inc
.
mutation UpdateMovie(
$id: UUID!,
$ratingIncrement: Int!
) {
movie_update(id: $id, data: {
rating_update: {
inc: $ratingIncrement
}
})
}
Data Connect mendukung operator berikut untuk update kolom:
inc
untuk menambahkan jenis dataInt
,Int64
,Float
,Date
, danTimestamp
dec
untuk mengurangi jenis dataInt
,Int64
,Float
,Date
, danTimestamp
Untuk daftar, Anda juga dapat memperbarui dengan nilai individual atau daftar nilai menggunakan:
add
untuk menambahkan item jika belum ada ke jenis daftar, kecuali daftar Vektorremove
untuk menghapus semua item, jika ada, dari jenis daftar, kecuali daftar Vektorappend
untuk menambahkan item ke jenis daftar, kecuali daftar Vektorprepend
untuk menambahkan item di awal jenis daftar, kecuali daftar Vektor
Melakukan penghapusan
Tentu saja Anda dapat menghapus data film. Pelestari film tentu ingin film fisik dipertahankan selama mungkin.
# Delete by key
mutation DeleteMovie($id: UUID!) {
movie_delete(id: $id)
}
Di sini, Anda dapat menggunakan _deleteMany
.
# Multiple deletes
mutation DeleteUnpopularMovies($minRating: Int!) {
movie_deleteMany(where: { rating: { le: $minRating } })
}
Menulis mutasi pada relasi
Amati cara menggunakan mutasi _upsert
implisit pada relasi.
# Create or update a one to one relation
mutation MovieMetadataUpsert($movieId: UUID!, $director: String!) {
movieMetadata_upsert(
data: { movie: { id: $movieId }, director: $director }
)
}
Mendesain skema untuk mutasi yang efisien
Data Connect menyediakan dua fitur penting yang memungkinkan Anda menulis mutasi yang lebih efisien dan menghemat operasi pulang pergi.
Skalar utama adalah ID objek ringkas yang Data Connect dirakit secara otomatis dari kolom utama dalam skema Anda. Skalar kunci berkaitan dengan efisiensi, yang memungkinkan Anda menemukan informasi tentang identitas dan struktur data dalam satu panggilan. Parameter ini sangat berguna saat Anda ingin melakukan tindakan berurutan pada rekaman baru dan memerlukan ID unik untuk diteruskan ke operasi mendatang, dan juga saat Anda ingin mengakses kunci relasional untuk melakukan operasi tambahan yang lebih kompleks.
Dengan nilai server, Anda dapat secara efektif membiarkan server mengisi kolom dalam tabel Anda secara dinamis menggunakan nilai yang disimpan atau mudah dihitung sesuai dengan ekspresi CEL sisi server tertentu dalam argumen expr
. Misalnya, Anda dapat menentukan kolom dengan stempel waktu yang diterapkan saat kolom diakses menggunakan waktu yang disimpan dalam permintaan operasi, updatedAt: Timestamp!
@default(expr: "request.time")
.
Menulis mutasi lanjutan: biarkan Data Connect memberikan nilai menggunakan sintaksis field_expr
Seperti yang dibahas dalam skalar utama dan nilai server,
Anda dapat mendesain skema sehingga server mengisi nilai untuk kolom umum seperti id
dan tanggal sebagai respons terhadap permintaan klien.
Selain itu, Anda dapat memanfaatkan data, seperti ID pengguna, yang dikirim dalam objek Data Connect request
dari aplikasi klien.
Saat menerapkan mutasi, gunakan sintaksis field_expr
untuk memicu
pembaruan yang dihasilkan server atau mengakses data dari permintaan. Misalnya, untuk meneruskan
otorisasi uid
yang disimpan dalam permintaan ke operasi _upsert
, teruskan
"auth.uid"
di kolom userId_expr
.
# Add a movie to the user's favorites list
mutation AddFavoritedMovie($movieId: UUID!) @auth(level: USER) {
favorite_movie_upsert(data: { userId_expr: "auth.uid", movieId: $movieId })
}
# Remove a movie from the user's favorites list
mutation DeleteFavoritedMovie($movieId: UUID!) @auth(level: USER) {
favorite_movie_delete(key: { userId_expr: "auth.uid", movieId: $movieId })
}
Atau, di aplikasi daftar tugas yang sudah dikenal, saat membuat daftar tugas baru, Anda dapat meneruskan id_expr
untuk menginstruksikan server agar membuat UUID untuk daftar secara otomatis.
mutation CreateTodoListWithFirstItem(
$listName: String!
) @transaction {
# Step 1
todoList_insert(data: {
id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
name: $listName,
})
}
Untuk mengetahui informasi selengkapnya, lihat skalar _Expr
dalam
referensi skalar.
Menulis mutasi lanjutan: operasi multi-langkah
Ada banyak situasi ketika Anda mungkin ingin menyertakan beberapa kolom penulisan (seperti penyisipan) dalam satu mutasi. Anda mungkin juga 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 memungkinkan Anda melakukan logika multi-langkah dalam mutasi dengan mendukung:
Beberapa kolom penulisan
Beberapa kolom baca dalam mutasi Anda (menggunakan kata kunci kolom
query
).Direktif
@transaction
, yang menyediakan dukungan transaksi yang sudah dikenal dari database relasional.Direktif
@check
, yang memungkinkan Anda mengevaluasi isi bacaan menggunakan ekspresi CEL, dan berdasarkan hasil evaluasi tersebut:- Melanjutkan pembuatan, pembaruan, dan penghapusan yang ditentukan oleh mutasi
- Lanjutkan untuk menampilkan hasil kolom kueri
- Gunakan pesan yang ditampilkan untuk melakukan logika yang sesuai dalam kode klien Anda
Direktif
@redact
, yang memungkinkan Anda menghilangkan hasil kolom kueri dari hasil protokol transfer data.Binding CEL
response
, yang menyimpan hasil terakumulasi dari semua mutasi dan kueri yang dilakukan dalam operasi multi-langkah yang kompleks. Anda dapat mengakses bindingresponse
:- Dalam perintah
@check
, melalui argumenexpr:
- Dengan nilai server, menggunakan sintaksis
field_expr
- Dalam perintah
Perintah @transaction
Dukungan untuk mutasi multi-langkah mencakup penanganan error menggunakan transaksi.
Direktif @transaction
memastikan bahwa mutasi - dengan satu kolom tulis (misalnya, _insert
atau _update
) atau dengan beberapa kolom tulis - selalu berjalan dalam transaksi database.
Mutasi tanpa
@transaction
menjalankan setiap kolom root satu demi satu secara berurutan. Operasi ini memunculkan error sebagai error kolom parsial, tetapi tidak dampak dari eksekusi berikutnya.Mutasi dengan
@transaction
dijamin akan berhasil sepenuhnya atau gagal sepenuhnya. Jika salah satu kolom dalam transaksi gagal, seluruh transaksi akan di-roll back.
Petunjuk @check
dan @redact
Perintah @check
memverifikasi bahwa kolom yang ditentukan ada dalam hasil
kueri. Ekspresi Common Expression Language (CEL) digunakan untuk menguji nilai kolom. Perilaku default direktif adalah memeriksa dan menolak
node yang nilainya null
atau []
(daftar kosong).
Direktif @redact
menyamarkan sebagian respons dari klien. Kolom yang disamarkan masih dievaluasi untuk efek samping (termasuk perubahan data dan @check
) dan hasilnya masih tersedia untuk langkah-langkah selanjutnya dalam ekspresi CEL.
Gunakan @check
, @check(message:)
, dan @redact
Penggunaan utama @check
dan @redact
adalah mencari data terkait untuk memutuskan apakah operasi tertentu harus diizinkan, menggunakan pencarian dalam logika, tetapi menyembunyikannya dari klien. Kueri Anda dapat menampilkan pesan yang berguna untuk penanganan
yang benar dalam kode klien.
Sebagai ilustrasi, kolom kueri berikut memeriksa apakah pemohon memiliki peran "admin" yang sesuai untuk melihat pengguna yang dapat mengedit film.
query GetMovieEditors($movieId: UUID!) @auth(level: USER) {
moviePermission(key: { movieId: $movieId, userId_expr: "auth.uid" }) @redact {
role @check(expr: "this == 'admin'", message: "You must be an admin to view all editors of a movie.")
}
moviePermissions(where: { movieId: { eq: $movieId }, role: { eq: "editor" } }) {
user {
id
username
}
}
}
Untuk mempelajari lebih lanjut direktif @check
dan @redact
dalam pemeriksaan otorisasi,
lihat pembahasan pencarian data otorisasi.
Menggunakan @check
untuk memvalidasi kunci
Beberapa kolom mutasi, seperti _update
, mungkin tidak beroperasi jika tidak ada data dengan kunci yang ditentukan. Demikian pula, pencarian dapat menampilkan nilai null atau daftar kosong. Hal ini tidak dianggap sebagai error sehingga tidak akan memicu rollback.
Untuk mencegah hasil ini, uji apakah kunci dapat ditemukan menggunakan direktif @check
.
# Delete by key, error if not found
mutation MustDeleteMovie($id: UUID!) @transaction {
movie_delete(id: $id) @check(expr: "this != null", message: "Movie not found, therefore nothing is deleted")
}
Menggunakan binding response
untuk merangkai mutasi multi-langkah
Pendekatan dasar untuk membuat record terkait, misalnya Movie
baru dan
entri MovieMetadata
terkait, adalah:
- Panggil mutasi
_insert
untukMovie
- Simpan kunci yang ditampilkan dari film yang dibuat
- Kemudian, panggil mutasi
_insert
kedua untuk membuat catatanMovieMetadata
.
Namun, dengan Data Connect, Anda dapat menangani kasus umum ini dalam satu
operasi multi-langkah dengan mengakses hasil _insert
pertama dalam
_insert
kedua.
Membuat aplikasi ulasan film yang sukses membutuhkan banyak pekerjaan. Mari kita lacak daftar tugas dengan contoh baru.
Menggunakan response
untuk menetapkan kolom dengan nilai server
Dalam mutasi daftar tugas berikut:
- Binding
response
merepresentasikan objek respons parsial sejauh ini, yang mencakup semua kolom mutasi tingkat teratas sebelum kolom saat ini. - Hasil operasi
todoList_insert
awal, yang menampilkan kolomid
(kunci), diakses nanti diresponse.todoList_insert.id
sehingga kita dapat langsung menyisipkan item tugas baru.
mutation CreateTodoListWithFirstItem(
$listName: String!,
$itemContent: String!
) @transaction {
# Sub-step 1:
todoList_insert(data: {
id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
name: $listName,
})
# Sub-step 2:
todo_insert(data: {
listId_expr: "response.todoList_insert.id" # <-- Grab the newly generated ID from the partial response so far.
content: $itemContent,
})
}
Gunakan response
untuk memvalidasi kolom menggunakan @check
response
juga tersedia di @check(expr: "...")
, sehingga Anda dapat menggunakannya untuk
membangun logika sisi server yang lebih rumit. Jika digabungkan dengan query { … }
langkah
dalam mutasi, Anda dapat mencapai lebih banyak hal tanpa perjalanan pulang pergi klien-server
tambahan.
Pada contoh berikut, perhatikan bahwa @check
sudah memiliki akses ke response.query
karena @check
selalu berjalan setelah langkah yang dikaitkan dengannya.
mutation CreateTodoInNamedList(
$listName: String!,
$itemContent: String!
) @transaction {
# Sub-step 1: Look up List.id by its name
query
@check(expr: "response.query.todoLists.size() > 0", message: "No such TodoList with the name!")
@check(expr: "response.query.todoLists.size() < 2", message: "Ambiguous listName!") {
todoLists(where: { name: $listName }) {
id
}
}
# Sub-step 2:
todo_insert(data: {
listId_expr: "response.todoLists[0].id" # <-- Now we have the parent list ID to insert to
content: $itemContent,
})
}
Untuk mengetahui informasi selengkapnya tentang pengikatan response
, lihat
referensi CEL.
Memahami operasi yang terganggu dengan @transaction
dan query @check
Mutasi multi-langkah dapat mengalami error:
- Operasi database mungkin gagal.
- Logika kueri
@check
dapat menghentikan operasi.
Data Connect merekomendasikan agar Anda menggunakan direktif @transaction
dengan mutasi multi-langkah. Hal ini menghasilkan database yang lebih konsisten dan hasil mutasi yang lebih mudah ditangani dalam kode klien:
- Pada error atau
@check
yang gagal pertama, operasi akan dihentikan, sehingga tidak perlu mengelola eksekusi kolom berikutnya atau evaluasi CEL. - Rollback dilakukan sebagai respons terhadap error database atau logika
@check
, sehingga menghasilkan status database yang konsisten. - Error rollback selalu ditampilkan ke kode klien.
Mungkin ada beberapa kasus penggunaan saat Anda memilih untuk tidak menggunakan @transaction
: Anda dapat memilih konsistensi pada akhirnya jika, misalnya, Anda memerlukan throughput, skalabilitas, atau ketersediaan yang lebih tinggi. Namun, Anda perlu mengelola database dan kode klien untuk memungkinkan hasil:
- Jika satu kolom gagal karena operasi database, kolom berikutnya akan terus
dieksekusi. Namun,
@check
yang gagal tetap akan menghentikan seluruh operasi. - Rollback tidak dilakukan, yang berarti status database campuran dengan beberapa pembaruan berhasil dan beberapa pembaruan gagal.
- Operasi Anda dengan
@check
dapat memberikan hasil yang lebih tidak konsisten jika logika@check
Anda menggunakan hasil pembacaan dan/atau penulisan pada langkah sebelumnya. - Hasil yang ditampilkan ke kode klien akan berisi campuran respons berhasil dan gagal yang lebih kompleks untuk ditangani.
Petunjuk untuk mutasi Data Connect
Selain direktif yang Anda gunakan dalam menentukan jenis dan tabel, Data Connect menyediakan direktif @auth
, @check
, @redact
, dan @transaction
untuk meningkatkan perilaku operasi.
Perintah | Berlaku untuk | Deskripsi |
---|---|---|
@auth |
Kueri dan mutasi | Menentukan kebijakan otorisasi untuk kueri atau mutasi. Lihat panduan otorisasi dan pengesahan. |
@check |
Kolom query dalam operasi multi-langkah |
Memverifikasi bahwa kolom yang ditentukan ada dalam hasil kueri. Ekspresi Common Expression Language (CEL) digunakan untuk menguji nilai kolom. Lihat Operasi multi-langkah. |
@redact |
Kueri | Menyembunyikan bagian respons dari klien. Lihat Operasi multi-langkah. |
@transaction |
Mutasi | Memastikan bahwa mutasi selalu berjalan dalam transaksi database. Lihat Operasi multi-langkah. |
Langkah berikutnya
Anda mungkin tertarik dengan:
- Membuat mutasi untuk aplikasi Anda menggunakan alat bantuan AI
- Mengizinkan mutasi Anda sesuai dengan panduan otorisasi
- Memanggil mutasi dari kode klien Anda untuk web, iOS, Android dan Flutter.
- Melakukan operasi data massal dengan mutasi