Firestore ardışık düzeni işlemleriyle verileri değiştirme

Belgeleri sorgulayabilen ve ardından verileri silebilen veya değiştirebilen Data Pipelines oluşturmak için update(...) ve delete(...) Veri manipülasyon dili (DML) aşamalarını kullanın.

Sürüm şartları

Bu sayfada açıklanan işlemler için Firestore Enterprise sürümü gerekir.

Başlamadan önce

Ardışık düzen işlemleriyle veritabanı sorgulama hakkında bilgi sahibi olmanız gerekir.

Dokümanları güncelleme

Belgeleri sorgulayabilen ve ardından veri ekleyebilen veya değiştirebilen Data Pipelines oluşturmak için update(...) DML aşamasını kullanın.

Tüm DML aşamaları, ardışık düzenin sonunda yer almalıdır. Bu aşamaya gelen belgeler, güncellenecek belgeleri tanımlamak için __name__ alanını içermelidir. Güncellemeye çalıştığınız belgelerden herhangi biri mevcut değilse işlem başarısız olur.

Örneğin, aşağıdaki işlem, bir koleksiyon grubundaki tüm dokümanlara veri modeli değişikliğini geriye dönük olarak uygular. Ardışık düzen, users koleksiyon grubunda preferences.color alanı eksik olan tüm dokümanlara bu alanı ekler.

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)

Dokümanları silme

Belgeleri sorgulayabilen ve ardından verileri silebilen Data Pipelines oluşturmak için delete(...) DML aşamasını kullanın. Yanlışlıkla toplu silme işlemlerini önlemek için delete(...) ile biten ardışık düzenler en az bir where(...) aşaması içermelidir. Tüm DML aşamaları, ardışık düzenin sonunda yer almalıdır.

Örneğin, aşağıdaki ardışık düzen, address.users değeri USA olarak ayarlanmış ve __create_time__ değeri 10 günden az olan tüm users belgelerini siler:

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)

Yürütme Modları ve Tutarlılık

DML aşamaları, açık bir işlem içinde veya bir işlem dışında yürütülebilir:

İşlem yürütme

İşlemsel DML, belgeler arasında atomik, ya hep ya hiç tutarlılığı sağlar ve tüm ardışık düzen sorgu aşamalarını destekler. Bu sayede, katı tutarlılık garantileri gerektiren (kısmi güncellemelerin kabul edilemez olduğu) veya karmaşık sorgu aşamalarına dayanan iş yükleri için idealdir. Ancak değişikliklerin işlem boyutu sınırlarına uyması gerekir.

Açık bir işlemde (runTransaction / transaction.execute(pipeline) veya atomic: true seçeneği kullanılarak) DML ardışık düzeni çalıştırmanın davranışı aşağıdaki gibidir:

  • Tüm mutasyonlar birlikte uygulanır veya hata durumunda tamamen geri alınır.
  • DML aşamasından önce tüm ardışık düzen sorgu aşamaları (where, add_fields, union, find_nearest ve aggregate alt sorguları dahil) desteklenir.
  • Bir işlemde, tüm okuma işlemleri yazma işlemlerinden önce yürütülmelidir. DML ardışık düzeni yazma işlemleri gerçekleştirdiğinden, aynı işlemde bir DML ardışık düzeni çalıştırdıktan sonra okuma işlemleri yürütemezsiniz. Örneğin, tek bir işlemde DML ardışık düzenini birden çok kez çağıramaz ve DML ardışık düzenini yürüttükten sonra belgeleri okuyamazsınız. DML ardışık düzeni çalıştırıldıktan sonra okuma işlemi yapmaya çalışmak FAILED_PRECONDITION hatasıyla başarısız olur: Cannot have reads after the first write in a Firestore transaction.
  • İşlem, Firestore Enterprise sürümü işlem sınırlarına tabidir.

İşlemsel olmayan yürütme

İşlemsel olmayan DML, işlem boyutu sınırlamalarıyla karşılaşmadan çok sayıda dokümanda toplu değişiklikler yapmak için tasarlanmıştır. Kilitleme işlemi tüm işlem yerine doküman düzeyinde yapıldığından, dokümanlar geniş ölçekte güncellenirken diğer eşzamanlı işlemler devam edebilir.

DML aşamaları açık bir işlem dışında çalıştırıldığında:

  • Bağımsız güncellemeler ve kısmi başarı: Her doküman birbirinden bağımsız olarak güncellenir ve işlemler dokümanlar arasında atomik değildir. İşlem hattı ilk hatada durur ve daha önce değiştirilen belgeler veritabanına yazılmış olarak kalır. Bu da kısmi başarıya olanak tanır.
  • Sahne desteği:
    • İleri düzey ve çoklu sorgu aşamaları (ör. aggregate(...), distinct(...), unnest(...), find_nearest(...), union(...), birleştirmeler ve alt sorgular), bir işlemin dışında DML'den önce desteklenmez. Ardışık düzeniniz bu aşamaları gerektiriyorsa işlem kullanın.
  • Güvenlik kuralları 20 arama sınırı: Her belge grubu kendi işleminde yürütülür ve güvenlik kurallarını yeniden değerlendirir. Güvenlik kurallarınız get() veya exists() aramalarını kullanıyorsa her grup bir arama yürütür. Yaklaşık 200 belge yazıldıktan sonra istek başına 20 arama sınırına ulaşılır ve PERMISSION_DENIED hatasıyla başarısız olur. Bu sınırdan kaçınmak için get() veya exists() aramaları yerine Özel Talepler'i kullanın.

Sınırlamalar

DML aşamalarıyla ilgili aşağıdaki sınırlamalara dikkat edin:

  • DML aşamaları, .execute() çağrılmadan önce ardışık düzen tanımındaki son aşama olmalıdır.
  • İşlem dışında çalıştırıldığında her doküman birbirinden bağımsız olarak güncellenir ve kısmi başarı elde edilebilir.
  • get() veya exists() aramaları içeren güvenlik kurallarına tabi olan işlem dışı DML işlemleri, 20 arama sınırı nedeniyle yaklaşık 200 belgeyle sınırlıdır.
  • İşlemsel DML işlemleri, Firestore Enterprise sürümünün işlem sınırlarıyla sınırlıdır. Firestore işlemleri ilk yazma işleminden sonra okuma işlemlerine izin vermediğinden tek bir işlemde DML ardışık düzenini birden çok kez çağıramaz ve DML ardışık düzenini yürüttükten sonra dokümanları okuyamazsınız. DML yazma işleminden sonra okuma işlemi yürütmeye çalışıldığında şu hata alınır: FAILED_PRECONDITION: Cannot have reads after the first write in a Firestore transaction.
  • DML aşamasından önceki aşama aynı __name__ değerine sahip birden fazla doküman oluşturuyorsa veya aynı hedef doküman kimliğiyle değerlendiriliyorsa her mutasyon sırayla işlenir:
    • upsert(...) ve update(...) için: Aynı dokümanı hedefleyen birden fazla mutasyon, "son gelen kazanır" semantiğini izler. Bu semantikte, işlenen son mutasyon dokümanın nihai durumunu belirler.
    • delete(...) için: İlk denemede doküman silinir ve aynı doküman için sonraki denemeler işlem yapmaz.
    • insert(...) için: İlk denemede doküman oluşturulur ve aynı doküman kimliğini hedefleyen sonraki denemeler ALREADY_EXISTS hatasıyla başarısız olur.