Mengubah data dengan operasi Pipeline
Gunakan tahap Bahasa pengolahan data (DML) update(...) dan delete(...) untuk membuat pipeline data yang dapat mengkueri dokumen, lalu menghapus atau mengubah data.
Persyaratan Edisi
Operasi yang dijelaskan di halaman ini memerlukan edisi Firestore Enterprise.
Sebelum memulai
Anda harus memahami cara membuat kueri database dengan operasi Pipeline.
Memperbarui dokumen
Gunakan tahap DML update(...) untuk membuat pipeline data yang dapat mengkueri dokumen, lalu menambahkan atau mengubah data.
Semua tahap DML harus berada di akhir pipeline.
Dokumen yang masuk ke tahap ini harus menyertakan kolom __name__ untuk
mengidentifikasi dokumen yang akan diperbarui. Operasi akan gagal jika ada dokumen yang Anda coba update, tetapi tidak ada.
Misalnya, operasi berikut mengisi ulang perubahan model data ke semua dokumen dalam grup koleksi. Pipeline menambahkan kolom preferences.color ke semua dokumen dalam kelompok koleksi users yang tidak memiliki kolom tersebut.
Node.js
const snapshot = await db.pipeline() .collectionGroup("users") .where(not(exists(field("preferences.color")))) .addFields(constant(null).as("preferences.color")) .removeFields("color") .update() .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Constant, Field, Not snapshot = ( client.pipeline() .collection_group("users") .where(Not(Field.of("preferences.color").exists())) .add_fields(Constant.of(None).as_("preferences.color")) .remove_fields("color") .update() .execute() )
Java
Pipeline.Snapshot snapshot = firestore.pipeline() .collectionGroup("users") .where(not(exists(field("preferences.color")))) .addFields(constant((String) null).as("preferences.color")) .removeFields("color") .update() .execute().get();
Go
snapshot := client.Pipeline(). CollectionGroup("users"). Where(firestore.Not(firestore.FieldExists(firestore.FieldOf("preferences.color")))). AddFields(firestore.Selectables( firestore.ConstantOfNull().As("preferences.color"), )). RemoveFields(firestore.Fields("color")). Update(). Execute(ctx)
Menghapus dokumen
Gunakan tahap DML delete(...) untuk membuat pipeline data yang dapat mengkueri dokumen, lalu menghapus data.
Untuk mencegah penghapusan massal yang tidak disengaja, pipeline yang diakhiri dengan delete(...)
harus menyertakan setidaknya satu tahap where(...).
Semua tahap DML harus berada di akhir pipeline.
Misalnya, pipeline berikut menghapus semua dokumen users dengan
address.users yang ditetapkan ke USA dan dengan __create_time__ kurang dari 10 hari:
Node.js
const pipeline = db.pipeline() .collectionGroup("users") .where(field("address.country").equal("USA")) .where(field("__create_time__").timestampAdd("day", 10).lessThan(currentTimestamp())) .delete(); await pipeline.execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import CurrentTimestamp, Field snapshot = ( client.pipeline() .collection_group("users") .where(Field.of("address.country").equal("USA")) .where( Field.of("__create_time__") .timestamp_add("day", 10) .less_than(CurrentTimestamp()) ) .delete() .execute() )
Java
Pipeline.Snapshot deleteResults = firestore.pipeline() .collectionGroup("users") .where(field("address.country").equal("USA")) .where(field("__create_time__").add(constant(10)).lessThan(currentTimestamp())) .delete() .execute().get();
Go
snapshot := client.Pipeline(). CollectionGroup("users"). Where(firestore.FieldOf("address.country").Equal("USA")). Where(firestore.FieldOf("__create_time__").Add(firestore.ConstantOf(10)).LessThan(firestore.CurrentTimestamp())). Delete(). Execute(ctx)
Mode Eksekusi dan Konsistensi
Tahapan DML dapat dijalankan di dalam transaksi eksplisit atau di luar transaksi:
Eksekusi transaksional
DML transaksional memberikan konsistensi atomik, semua atau tidak sama sekali di seluruh dokumen dan mendukung kumpulan lengkap tahap kueri pipeline. Hal ini membuatnya ideal untuk workload yang memerlukan jaminan konsistensi yang ketat—di mana update parsial tidak dapat diterima—atau yang mengandalkan tahap kueri yang kompleks, asalkan modifikasi sesuai dengan batas ukuran transaksi.
Menjalankan pipeline DML di dalam transaksi eksplisit (menggunakan runTransaction /
transaction.execute(pipeline) atau opsi atomic: true) memiliki perilaku
berikut:
- Semua mutasi di-commit bersama atau di-roll back sepenuhnya jika terjadi kegagalan.
- Semua tahap kueri pipeline didukung sebelum tahap DML (termasuk subkueri
where,add_fields,union,find_nearest, danaggregate). - Dalam transaksi, semua operasi baca harus dijalankan sebelum operasi tulis. Karena pipeline DML melakukan penulisan, Anda tidak dapat menjalankan pembacaan setelah menjalankan pipeline DML dalam transaksi yang sama. Misalnya, Anda tidak dapat memanggil pipeline DML beberapa kali dalam satu transaksi, dan Anda juga tidak dapat membaca dokumen setelah menjalankan pipeline DML. Upaya untuk menjalankan pembacaan setelah pipeline DML berjalan akan gagal dengan error
FAILED_PRECONDITION:Cannot have reads after the first write in a Firestore transaction. - Operasi ini tunduk pada batas transaksi edisi Firestore Enterprise.
Eksekusi non-transaksional
DML non-transaksional dirancang untuk modifikasi massal di sejumlah besar dokumen tanpa mengalami batasan ukuran transaksi. Dengan mengunci di tingkat dokumen, bukan di seluruh operasi, hal ini memungkinkan operasi serentak lainnya dilanjutkan saat mengupdate dokumen dalam skala besar.
Saat tahap DML berjalan di luar transaksi eksplisit:
- Update independen dan keberhasilan parsial: Setiap dokumen diupdate secara independen satu sama lain, dan operasi tidak bersifat atomik di seluruh dokumen. Pipeline berhenti pada error pertama, dan dokumen yang diubah sebelumnya tetap ditulis ke database, sehingga memungkinkan keberhasilan parsial terjadi.
- Dukungan tahap:
- Tahap lanjutan dan multi-kueri (seperti
aggregate(...),distinct(...),unnest(...),find_nearest(...),union(...), join, dan subkueri) tidak didukung sebelum DML di luar transaksi. Gunakan transaksi jika pipeline Anda memerlukan tahap ini.
- Tahap lanjutan dan multi-kueri (seperti
- Batas 20 pencarian Aturan Keamanan: Setiap batch dokumen dijalankan dalam transaksinya sendiri dan mengevaluasi ulang aturan keamanan. Jika aturan keamanan Anda menggunakan pencarian
get()atauexists(), setiap batch akan menjalankan pencarian, mencapai batas per permintaan sebanyak 20 pencarian setelah menulis sekitar 200 dokumen, dan gagal denganPERMISSION_DENIED. Gunakan Klaim Kustom, bukan pencarianget()atauexists()untuk menghindari batas ini.
Batasan
Perhatikan batasan berikut untuk tahap DML:
- Tahap DML harus menjadi tahap terakhir dalam definisi pipeline sebelum memanggil
.execute(). - Saat dijalankan di luar transaksi, setiap dokumen diperbarui secara independen satu sama lain dan memungkinkan terjadinya keberhasilan parsial.
- Operasi DML non-transaksional yang tunduk pada Aturan Keamanan dengan pencarian
get()atauexists()dibatasi hingga sekitar 200 dokumen karena batas 20 pencarian. - Operasi DML transaksional dibatasi oleh batas transaksi edisi Firestore Enterprise. Karena transaksi Firestore tidak mengizinkan pembacaan setelah penulisan pertama, Anda tidak dapat memanggil pipeline DML beberapa kali dalam satu transaksi, dan Anda juga tidak dapat membaca dokumen setelah menjalankan pipeline DML.
Upaya untuk menjalankan pembacaan setelah penulisan DML gagal dengan error
FAILED_PRECONDITION:Cannot have reads after the first write in a Firestore transaction. - Jika tahap sebelum tahap DML menghasilkan beberapa dokumen dengan
__name__yang sama atau menghasilkan ID dokumen tujuan yang sama, setiap mutasi akan diproses secara berurutan:- Untuk
upsert(...)danupdate(...): Beberapa mutasi yang menargetkan dokumen yang sama mengikuti semantik "yang terakhir menang", dengan mutasi terakhir yang diproses menentukan status akhir dokumen. - Untuk
delete(...): Upaya pertama akan menghapus dokumen, dan upaya berikutnya untuk dokumen yang sama tidak akan melakukan apa pun. - Untuk
insert(...): Upaya pertama akan membuat dokumen, dan upaya berikutnya yang menargetkan ID dokumen yang sama akan gagal dengan errorALREADY_EXISTS.
- Untuk