تعديل البيانات باستخدام عمليات Firestore Pipeline

استخدِم مرحلتَي لغة معالجة البيانات (DML) update(...) وdelete(...) لإنشاء مسارات بيانات يمكنها الاستعلام عن المستندات ثم حذف البيانات أو تعديلها.

متطلبات الإصدار

تتطلّب العمليات الموضّحة في هذه الصفحة إصدار Firestore Enterprise.

قبل البدء

يجب أن تكون على دراية بكيفية الاستعلام عن قاعدة بيانات باستخدام عمليات Pipeline.

تعديل المستندات

استخدِم مرحلة update(...) DML لإنشاء مسارات بيانات يمكنها طلب المستندات ثم إضافة البيانات أو تعديلها.

يجب أن تكون جميع مراحل DML في نهاية المسار. يجب أن تتضمّن المستندات التي تصل إلى هذه المرحلة الحقل __name__ لتحديد المستندات التي يجب تعديلها. وتفشل العملية إذا لم يكن أي من المستندات التي تحاول تعديلها موجودًا.

على سبيل المثال، تؤدي العملية التالية إلى إعادة تعبئة تغيير نموذج البيانات لجميع المستندات في مجموعة المجموعات. يضيف المسار حقل preferences.color إلى جميع المستندات في مجموعة users التي لا تتضمّن هذا الحقل.

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();
متابعة
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)

حذف المستندات

استخدِم مرحلة لغة معالجة البيانات (DML) في delete(...) لإنشاء مسارات بيانات يمكنها الاستعلام عن المستندات ثم حذف البيانات. لمنع عمليات الحذف المجمّعة غير المقصودة، يجب أن تتضمّن المسارات التي تنتهي بـ delete(...) مرحلة where(...) واحدة على الأقل. يجب أن تكون جميع مراحل DML في نهاية المسار.

على سبيل المثال، يحذف المسار التالي جميع مستندات users التي تم ضبط address.users فيها على USA والتي يقلّ فيها __create_time__ عن 10 أيام:

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();
متابعة
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)

أوضاع التنفيذ والاتساق

يمكن تنفيذ مراحل DML إما داخل معاملة صريحة أو خارج معاملة:

تنفيذ المعاملات

توفّر لغة DML الخاصة بالمعاملات اتساقًا ذريًا وشاملاً في جميع المستندات، وتتيح استخدام المجموعة الكاملة من مراحل طلبات المسارات. وهذا يجعلها مثالية لأعباء العمل التي تتطلب ضمانات صارمة للاتساق، حيث تكون التعديلات الجزئية غير مقبولة، أو التي تعتمد على مراحل طلبات بحث معقدة، بشرط أن تتناسب التعديلات مع حدود حجم المعاملة.

يؤدي تشغيل مسار DML داخل معاملة صريحة (باستخدام runTransaction / transaction.execute(pipeline) أو الخيار atomic: true) إلى السلوك التالي:

  • يتم تنفيذ جميع التغييرات معًا أو التراجع عنها بالكامل في حال حدوث خطأ.
  • تتوفّر جميع مراحل طلبات البحث في المسار قبل مرحلة لغة DML (بما في ذلك طلبات البحث الفرعية where وadd_fields وunion وfind_nearest وaggregate).
  • في أي معاملة، يجب تنفيذ جميع عمليات القراءة قبل أي عمليات كتابة. بما أنّ مسار DML ينفّذ عمليات كتابة، لا يمكنك تنفيذ عمليات قراءة بعد تشغيل مسار DML في المعاملة نفسها. على سبيل المثال، لا يمكنك استدعاء مسار DML عدة مرات في معاملة واحدة، ولا يمكنك قراءة المستندات بعد تنفيذ مسار DML. تؤدي محاولة تنفيذ عملية قراءة بعد تشغيل مسار DML إلى ظهور الخطأ FAILED_PRECONDITION: Cannot have reads after the first write in a Firestore transaction.
  • تخضع العملية لحدود المعاملات في إصدار Firestore Enterprise.

التنفيذ غير المرتبط بمعاملات

تم تصميم لغة معالجة البيانات غير المستندة إلى المعاملات لإجراء تعديلات مجمّعة على عدد كبير من المستندات بدون مواجهة قيود على حجم المعاملات. من خلال القفل على مستوى المستند بدلاً من العملية بأكملها، يسمح هذا الإجراء للعمليات المتزامنة الأخرى بالمتابعة أثناء تعديل المستندات على نطاق واسع.

عند تشغيل مراحل DML خارج معاملة صريحة:

  • التعديلات المستقلة والنجاح الجزئي: يتم تعديل كل مستند بشكل مستقل عن الآخر، ولا تكون العمليات موحّدة في جميع المستندات. يتوقف المسار عند حدوث الخطأ الأول، وتظل المستندات المعدَّلة سابقًا مكتوبة في قاعدة البيانات، ما يسمح بحدوث نجاح جزئي.
  • دعم المسرح:
    • لا تتوفّر المراحل المتقدّمة والمتعدّدة لطلبات البحث (مثل aggregate(...) وdistinct(...) وunnest(...) وfind_nearest(...) وunion(...) وعمليات الربط وطلبات البحث الفرعية) قبل لغة معالجة البيانات (DML) خارج المعاملة. استخدِم معاملة إذا كان مسار الإحالة الناجحة يتطلّب هذه المراحل.
  • حدّ البحث في قواعد الأمان البالغ 20: يتم تنفيذ كل دفعة من المستندات في معاملتها الخاصة وإعادة تقييم قواعد الأمان. إذا كانت قواعد الأمان تستخدم عمليات البحث get() أو exists()، تنفّذ كل دفعة عملية بحث، وتصل إلى الحد الأقصى لكل طلب وهو 20 عملية بحث بعد كتابة حوالي 200 مستند وتتعذّر باستخدام PERMISSION_DENIED. استخدِم المطالبات المخصّصة بدلاً من عمليات البحث في get() أو exists() لتجنُّب هذا الحدّ.

القيود

يُرجى ملاحظة القيود التالية لمراحل DML:

  • يجب أن تكون مراحل DML هي المرحلة الأخيرة في تعريف المسار قبل استدعاء .execute().
  • عند تشغيلها خارج معاملة، يتم تعديل كل مستند بشكل مستقل عن الآخر، ما يسمح بتحقيق نجاح جزئي.
  • إنّ عمليات لغة معالجة البيانات (DML) غير المستندة إلى المعاملات والتي تخضع لقواعد الأمان مع عمليات البحث get() أو exists() تقتصر على 200 مستند تقريبًا بسبب الحدّ الأقصى لعمليات البحث البالغ 20 عملية.
  • تتقيّد عمليات لغة معالجة البيانات (DML) الخاصة بالمعاملات بحدود المعاملات في إصدار Firestore Enterprise. بما أنّ معاملات Firestore لا تسمح بعمليات القراءة بعد عملية الكتابة الأولى، لا يمكنك استدعاء مسار DML عدة مرات ضمن معاملة واحدة، ولا يمكنك قراءة المستندات بعد تنفيذ مسار DML. تؤدي محاولة تنفيذ عملية قراءة بعد فشل عملية كتابة بلغة DML إلى ظهور الخطأ FAILED_PRECONDITION: Cannot have reads after the first write in a Firestore transaction.
  • إذا كانت المرحلة التي تسبق مرحلة DML تنتج مستندات متعددة باستخدام نفس __name__ أو يتم تقييمها إلى نفس معرّف المستند الوجهة، تتم معالجة كل طفرة بشكل تسلسلي:
    • بالنسبة إلى upsert(...) وupdate(...): تتبع التغييرات المتعددة التي تستهدف المستند نفسه دلالات "الأخير يفوز"، حيث يحدد آخر تغيير تمت معالجته الحالة النهائية للمستند.
    • بالنسبة إلى delete(...): تؤدي المحاولة الأولى إلى حذف المستند، وتكون المحاولات اللاحقة للمستند نفسه غير فعّالة.
    • بالنسبة إلى insert(...): تؤدي المحاولة الأولى إلى إنشاء المستند، وتفشل المحاولات اللاحقة التي تستهدف معرّف المستند نفسه مع ظهور الخطأ ALREADY_EXISTS.