Modifica i dati con le operazioni della pipeline
Utilizza le fasi del linguaggio di manipolazione dei dati (DML) update(...) e delete(...) per creare pipeline di dati che possono eseguire query sui documenti ed eliminare o modificare i dati.
Requisiti relativi alla versione
Le operazioni descritte in questa pagina richiedono la versione Firestore Enterprise.
Prima di iniziare
Dovresti sapere come eseguire query su un database con operazioni di pipeline.
Aggiorna i documenti
Utilizza la fase DML update(...) per creare pipeline di dati che possono eseguire query sui documenti e poi aggiungere o modificare i dati.
Tutte le fasi DML devono essere posizionate alla fine della pipeline.
I documenti che entrano in questa fase devono includere il campo __name__ per identificare i documenti da aggiornare. L'operazione non riesce se uno dei documenti che tenti di aggiornare non esiste.
Ad esempio, la seguente operazione esegue il backfill di una modifica del modello di dati in tutti i documenti di un gruppo di raccolte. La pipeline aggiunge un campo preferences.color a tutti i documenti nel gruppo di raccolte users in cui manca questo campo.
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();
Vai
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)
Elimina documenti
Utilizza la fase DML delete(...) per creare pipeline di dati che possono eseguire query sui documenti ed eliminare i dati.
Per evitare eliminazioni collettive accidentali, le pipeline che terminano con delete(...)
devono includere almeno una fase where(...).
Tutte le fasi DML devono essere posizionate alla fine della pipeline.
Ad esempio, la seguente pipeline elimina tutti i documenti users con
address.users impostato su USA e con __create_time__ inferiore a 10 giorni:
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();
Vai
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)
Modalità di esecuzione e coerenza
Le fasi DML possono essere eseguite all'interno di una transazione esplicita o all'esterno di una transazione:
Esecuzione transazionale
Il DML transazionale fornisce una coerenza atomica, tutto o niente, tra i documenti e supporta l'insieme completo delle fasi di query della pipeline. Questo lo rende ideale per i workload che richiedono garanzie di coerenza rigorose, in cui gli aggiornamenti parziali non sono accettabili, o che si basano su fasi di query complesse, a condizione che le modifiche rientrino nei limiti di dimensione delle transazioni.
L'esecuzione di una pipeline DML all'interno di una transazione esplicita (utilizzando runTransaction/transaction.execute(pipeline) o l'opzione atomic: true) ha il seguente comportamento:
- In caso di errore, viene eseguito il commit di tutte le mutazioni insieme o il rollback completo.
- Tutte le fasi di query della pipeline sono supportate prima di una fase DML (incluse le sottoquery
where,add_fields,union,find_nearesteaggregate). - In una transazione, tutte le operazioni di lettura devono essere eseguite prima di qualsiasi operazione di scrittura. Poiché una pipeline DML esegue scritture, non puoi eseguire letture dopo aver eseguito una pipeline DML nella stessa transazione. Ad esempio, non puoi chiamare una pipeline DML più volte in una singola transazione, né puoi leggere i documenti dopo aver eseguito una pipeline DML. Il tentativo di eseguire una lettura dopo l'esecuzione di una pipeline DML non riesce con un errore
FAILED_PRECONDITION:Cannot have reads after the first write in a Firestore transaction. - L'operazione è soggetta ai limiti delle transazioni della versione Firestore Enterprise.
Esecuzione non transazionale
Il DML non transazionale è progettato per modifiche collettive su un numero elevato di documenti senza incorrere in limitazioni delle dimensioni delle transazioni. Il blocco a livello di documento, anziché sull'intera operazione, consente di procedere con altre operazioni simultanee durante l'aggiornamento dei documenti su larga scala.
Quando le fasi DML vengono eseguite al di fuori di una transazione esplicita:
- Aggiornamenti indipendenti e successo parziale: ogni documento viene aggiornato indipendentemente dagli altri e le operazioni non sono atomiche tra i documenti. La pipeline si interrompe al primo errore e i documenti modificati in precedenza rimangono scritti nel database, il che consente un successo parziale.
- Supporto per i palchi:
- Le fasi avanzate e con più query (come
aggregate(...),distinct(...),unnest(...),find_nearest(...),union(...), join e subquery) non sono supportate prima di DML al di fuori di una transazione. Utilizza una transazione se la pipeline richiede queste fasi.
- Le fasi avanzate e con più query (come
- Limite di 20 ricerche delle regole di sicurezza: ogni gruppo di documenti viene eseguito nella propria transazione e rivaluta le regole di sicurezza. Se le regole di sicurezza utilizzano ricerche
get()oexists(), ogni batch esegue una ricerca, raggiungendo il limite per richiesta di 20 ricerche dopo aver scritto circa 200 documenti e non riuscendo conPERMISSION_DENIED. Utilizza le rivendicazioni personalizzate anziché le ricercheget()oexists()per evitare questo limite.
Limitazioni
Tieni presenti le seguenti limitazioni per le fasi DML:
- Le fasi DML devono essere l'ultima fase di una definizione di pipeline prima di chiamare
.execute(). - Se eseguito al di fuori di una transazione, ogni documento viene aggiornato indipendentemente dagli altri e consente un successo parziale.
- Le operazioni DML non transazionali soggette a regole di sicurezza con ricerche
get()oexists()sono limitate a circa 200 documenti a causa del limite di 20 ricerche. - Le operazioni DML transazionali sono limitate dai limiti delle transazioni di Firestore Enterprise. Poiché le transazioni Firestore non consentono letture dopo la prima scrittura, non puoi chiamare una pipeline DML più volte all'interno di una singola transazione, né puoi leggere i documenti dopo l'esecuzione di una pipeline DML.
Il tentativo di eseguire una lettura dopo una scrittura DML non riesce con un errore
FAILED_PRECONDITION:Cannot have reads after the first write in a Firestore transaction. - Se la fase precedente alla fase DML produce più documenti con lo stesso
__name__o restituisce lo stesso ID documento di destinazione, ogni mutazione viene elaborata in sequenza:- Per
upsert(...)eupdate(...): più mutazioni che hanno come target lo stesso documento seguono la semantica "vince l'ultima", in cui l'ultima mutazione elaborata determina lo stato finale del documento. - Per
delete(...): il primo tentativo elimina il documento, mentre i tentativi successivi per lo stesso documento non hanno effetto. - Per
insert(...): il primo tentativo crea il documento, mentre i tentativi successivi che hanno come target lo stesso ID documento non vanno a buon fine e generano un erroreALREADY_EXISTS.
- Per