الخلفية
عمليات خطوط الإنتاج هي واجهة طلب بحث جديدة لـ Cloud Firestore.
توفّر هذه الواجهة وظائف طلب بحث متقدّمة تتضمّن عبارات معقّدة. ويضيف أيضًا دعمًا للعديد من الدوال الجديدة، مثل min, max, substring, regex_match وarray_contains_all.
باستخدام عمليات Pipeline، يصبح إنشاء الفهرس اختياريًا تمامًا، ما يؤدي إلى تبسيط عملية تطوير الاستعلامات الجديدة. تزيل عمليات سلسلة المعالجة أيضًا العديد من القيود المفروضة على شكل الاستعلام، ما يتيح لك تحديد استعلامات in أو or كبيرة.
البدء
لتثبيت حِزم SDK الخاصة بالعميل وإعدادها، يُرجى الرجوع إلى التعليمات الواردة في الأدلة التالية:
البنية
تقدّم الأقسام التالية نظرة عامة على بنية عمليات Pipeline.
المفاهيم
أحد الاختلافات الملحوظة في عمليات مسار المعالجة هو تقديم ترتيب "المرحلة" الصريح. ويتيح ذلك إمكانية التعبير عن طلبات بحث أكثر تعقيدًا. ومع ذلك، يمثّل ذلك انحرافًا ملحوظًا عن واجهة طلب البحث الحالية (العمليات الأساسية) التي كان ترتيب المراحل فيها ضمنيًا. إليك مثالاً على عملية Pipeline:
Web
const pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort(field("name").ascending()) // Step 4: Return the top 10. Note applying the limit earlier in the // pipeline would have unintentional results. .limit(10);
Swift
let pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(Field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort([Field("name").ascending()]) // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have // unintentional results. .limit(10)
Kotlin
val pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort(field("name").ascending()) // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have // unintentional results. .limit(10)
Java
Pipeline pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort(field("name").ascending()) // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have // unintentional results. .limit(10);
Python
from google.cloud.firestore_v1.pipeline_expressions import Field pipeline = ( client.pipeline() .collection("cities") .where(Field.of("population").greater_than(100_000)) .sort(Field.of("name").ascending()) .limit(10) )
الإعداد
تتضمّن عمليات خطوط الأنابيب بنية مألوفة جدًا مستمدة من طلبات البحث Cloud Firestore الحالية. للبدء، عليك تهيئة طلب بحث من خلال كتابة ما يلي:
Web
const { getFirestore } = require("firebase/firestore"); const { execute } = require("firebase/firestore/pipelines"); const database = getFirestore(app, "enterprise"); const pipeline = database.pipeline();
Swift
let firestore = Firestore.firestore(database: "enterprise") let pipeline = firestore.pipeline()
Kotlin
val firestore = Firebase.firestore("enterprise") val pipeline = firestore.pipeline()
Java
FirebaseFirestore firestore = FirebaseFirestore.getInstance("enterprise"); PipelineSource pipeline = firestore.pipeline();
Python
firestore_client = firestore.client(default_app, "your-new-enterprise-database") pipeline = firestore_client.pipeline()
البنية
هناك بعض المصطلحات المهمة التي يجب فهمها عند إنشاء عمليات Pipeline، وهي: المراحل والعبارات والدوال.

المراحل: قد تتألف عملية البيع من مرحلة واحدة أو أكثر. من الناحية المنطقية، تمثّل هذه المراحل سلسلة الخطوات التي يتم اتّخاذها لتنفيذ طلب البحث. ملاحظة: من الناحية العملية، قد يتم تنفيذ المراحل بترتيب مختلف لتحسين الأداء. ومع ذلك، لا يؤدي ذلك إلى تعديل الغرض من الطلب أو صحته.
التعبيرات: غالبًا ما تقبل المراحل تعبيرًا يتيح لك التعبير عن طلبات بحث أكثر تعقيدًا. قد تكون الصيغة بسيطة وتتألف من دالة واحدة مثل eq("a", 1). يمكنك أيضًا التعبير عن صيغ أكثر تعقيدًا من خلال تضمين صيغ مثل and(eq("a", 1), eq("b", 2)).
المراجع إلى الحقول مقابل المراجع إلى الثوابت
تتيح عمليات خطوط النقل استخدام تعبيرات معقّدة. وبالتالي، قد يكون من الضروري التمييز بين ما إذا كانت القيمة تمثّل حقل أو ثابت. راجع المثال التالي:
Web
const pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")));
Swift
let pipeline = db.pipeline() .collection("cities") .where(Field("name").equal(Constant("Toronto")))
Kotlin
val pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")))
Java
Pipeline pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")));
Python
from google.cloud.firestore_v1.pipeline_expressions import Field, Constant pipeline = ( client.pipeline() .collection("cities") .where(Field.of("name").equal(Constant.of("Toronto"))) )
المسارح
مراحل الإدخال
تمثّل مرحلة الإدخال المرحلة الأولى من طلب البحث. تحدّد هذه السمة المجموعة الأولية من المستندات التي تبحث فيها. بالنسبة إلى عمليات Pipeline، يشبه ذلك إلى حد كبير الاستعلامات الحالية، حيث تبدأ معظم الاستعلامات إما بمرحلة collection(...) أو collection_group(...). مرحلتا الإدخال الجديدتان هما database() وdocuments(...)، حيث تتيح database() عرض جميع المستندات في قاعدة البيانات، بينما تعمل documents(...) بشكل مطابق للقراءة المجمّعة.
Web
let results; // Return all restaurants in San Francisco results = await execute(db.pipeline().collection("cities/sf/restaurants")); // Return all restaurants results = await execute(db.pipeline().collectionGroup("restaurants")); // Return all documents across all collections in the database (the entire database) results = await execute(db.pipeline().database()); // Batch read of 3 documents results = await execute(db.pipeline().documents([ doc(db, "cities", "SF"), doc(db, "cities", "DC"), doc(db, "cities", "NY") ]));
Swift
var results: Pipeline.Snapshot // Return all restaurants in San Francisco results = try await db.pipeline().collection("cities/sf/restaurants").execute() // Return all restaurants results = try await db.pipeline().collectionGroup("restaurants").execute() // Return all documents across all collections in the database (the entire database) results = try await db.pipeline().database().execute() // Batch read of 3 documents results = try await db.pipeline().documents([ db.collection("cities").document("SF"), db.collection("cities").document("DC"), db.collection("cities").document("NY") ]).execute()
Kotlin
var results: Task<Pipeline.Snapshot> // Return all restaurants in San Francisco results = db.pipeline().collection("cities/sf/restaurants").execute() // Return all restaurants results = db.pipeline().collectionGroup("restaurants").execute() // Return all documents across all collections in the database (the entire database) results = db.pipeline().database().execute() // Batch read of 3 documents results = db.pipeline().documents( db.collection("cities").document("SF"), db.collection("cities").document("DC"), db.collection("cities").document("NY") ).execute()
Java
Task<Pipeline.Snapshot> results; // Return all restaurants in San Francisco results = db.pipeline().collection("cities/sf/restaurants").execute(); // Return all restaurants results = db.pipeline().collectionGroup("restaurants").execute(); // Return all documents across all collections in the database (the entire database) results = db.pipeline().database().execute(); // Batch read of 3 documents results = db.pipeline().documents( db.collection("cities").document("SF"), db.collection("cities").document("DC"), db.collection("cities").document("NY") ).execute();
Python
# Return all restaurants in San Francisco results = client.pipeline().collection("cities/sf/restaurants").execute() # Return all restaurants results = client.pipeline().collection_group("restaurants").execute() # Return all documents across all collections in the database (the entire database) results = client.pipeline().database().execute() # Batch read of 3 documents results = ( client.pipeline() .documents( client.collection("cities").document("SF"), client.collection("cities").document("DC"), client.collection("cities").document("NY"), ) .execute() )
كما هو الحال مع جميع المراحل الأخرى، لا يكون ترتيب النتائج من مراحل الإدخال هذه ثابتًا. يجب دائمًا إضافة عامل التشغيل sort(...) إذا كان الترتيب محدّدًا مطلوبًا.
المكان
تعمل المرحلة where(...) كعملية فلترة تقليدية على المستندات التي تم إنشاؤها من المرحلة السابقة، وهي تشبه إلى حد كبير بنية "where" الحالية للاستعلامات الحالية. يتم استبعاد أي مستند لا يتم فيه تقييم تعبير معيّن إلى قيمة غير true من المستندات التي يتم عرضها.
يمكن ربط عدّة عبارات where(...) معًا، ويمكن أن تعمل كعبارة and(...). على سبيل المثال، طلبَا البحث التاليان متكافئان منطقيًا ويمكن استخدامهما بالتبادل.
Web
let results; results = await execute(db.pipeline().collection("books") .where(field("rating").equal(5)) .where(field("published").lessThan(1900)) ); results = await execute(db.pipeline().collection("books") .where(and(field("rating").equal(5), field("published").lessThan(1900))) );
Swift
var results: Pipeline.Snapshot results = try await db.pipeline().collection("books") .where(Field("rating").equal(5)) .where(Field("published").lessThan(1900)) .execute() results = try await db.pipeline().collection("books") .where(Field("rating").equal(5) && Field("published").lessThan(1900)) .execute()
Kotlin
var results: Task<Pipeline.Snapshot> results = db.pipeline().collection("books") .where(field("rating").equal(5)) .where(field("published").lessThan(1900)) .execute() results = db.pipeline().collection("books") .where(Expression.and(field("rating").equal(5), field("published").lessThan(1900))) .execute()
Java
Task<Pipeline.Snapshot> results; results = db.pipeline().collection("books") .where(field("rating").equal(5)) .where(field("published").lessThan(1900)) .execute(); results = db.pipeline().collection("books") .where(Expression.and( field("rating").equal(5), field("published").lessThan(1900) )) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import And, Field results = ( client.pipeline() .collection("books") .where(Field.of("rating").equal(5)) .where(Field.of("published").less_than(1900)) .execute() ) results = ( client.pipeline() .collection("books") .where(And(Field.of("rating").equal(5), Field.of("published").less_than(1900))) .execute() )
اختيار الحقول أو إضافتها أو إزالتها
تتيح لك select(...) وadd_fields(...) وremove_fields(...) تعديل الحقول التي يتم عرضها من مرحلة سابقة. ويُشار إلى هذه المراحل الثلاث بشكل عام باسم مراحل العرض.
يتيح لك select(...) وadd_fields(...) تحديد نتيجة تعبير لاسم حقل يوفّره المستخدم. سيؤدي التعبير الذي ينتج عنه خطأ إلى ظهور القيمة null. لن تعرض select(...) سوى المستندات التي تتضمّن أسماء الحقول المحدّدة، بينما توسّع add_fields(...) مخطط المرحلة السابقة (ما قد يؤدي إلى استبدال القيم بأسماء حقول متطابقة).
تسمح السمة remove_fields(...) بتحديد مجموعة من الحقول المطلوب إزالتها من المرحلة السابقة. تحديد أسماء حقول غير متوفّرة هو عملية غير فعّالة.
راجِع القسم تقييد الحقول التي سيتم عرضها أدناه، ولكن بشكل عام، يكون استخدام مرحلة كهذه لتقييد النتيجة بالحقول المطلوبة فقط في العميل مفيدًا في تقليل التكلفة ووقت الاستجابة لمعظم طلبات البحث.
التجميع / التمييز
تتيح لك المرحلة aggregate(...) إجراء سلسلة من عمليات التجميع على مستندات الإدخال. يتم تجميع جميع المستندات معًا تلقائيًا، ولكن يمكن تقديم وسيطة grouping اختيارية، ما يسمح بتجميع المستندات المُدخَلة في حِزم مختلفة.
Web
const results = await execute(db.pipeline() .collection("books") .aggregate( field("rating").average().as("avg_rating") ) .distinct(field("genre")) );
Swift
let results = try await db.pipeline() .collection("books") .aggregate([ Field("rating").average().as("avg_rating") ], groups: [ Field("genre") ]) .execute()
Kotlin
val results = db.pipeline() .collection("books") .aggregate( AggregateStage .withAccumulators(AggregateFunction.average("rating").alias("avg_rating")) .withGroups(field("genre")) ) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .aggregate(AggregateStage .withAccumulators( AggregateFunction.average("rating").alias("avg_rating")) .withGroups(field("genre"))) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .aggregate( Field.of("rating").average().as_("avg_rating"), groups=[Field.of("genre")] ) .execute() )
عندما لا يتم تحديد groupings، ستنتج هذه المرحلة مستندًا واحدًا فقط، وإلا سيتم إنشاء مستند لكل مجموعة فريدة من قيم groupings.
distinct(...) هي مرحلة بسيطة لتجميع البيانات تتيح إنشاء groupings الفريد فقط بدون أي أدوات تجميع. ويتشابه سلوكه تمامًا مع سلوك aggregate(...) في جميع الجوانب الأخرى. في ما يلي مثال:
Web
const results = await execute(db.pipeline() .collection("books") .distinct( field("author").toUpper().as("author"), field("genre") ) );
Swift
let results = try await db.pipeline() .collection("books") .distinct([ Field("author").toUpper().as("author"), Field("genre") ]) .execute()
Kotlin
val results = db.pipeline() .collection("books") .distinct( field("author").toUpper().alias("author"), field("genre") ) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .distinct( field("author").toUpper().alias("author"), field("genre") ) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .distinct(Field.of("author").to_upper().as_("author"), "genre") .execute() )
الدوال
الدوال هي لبنة أساسية لإنشاء التعبيرات وطلبات البحث المعقّدة. للحصول على قائمة كاملة بالدوال مع أمثلة، يُرجى الرجوع إلى مرجع الدوال. كتذكير سريع، إليك بنية طلب البحث العادي:

تقبل العديد من المراحل عبارات تحتوي على دالة واحدة أو أكثر. يمكن العثور على الاستخدام الأكثر شيوعًا للدالة في مرحلتَي where(...) وselect(...). هناك نوعان رئيسيان من الدوال يجب أن تكون على دراية بهما:
Web
let results; // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = await execute(db.pipeline().collection("books") .select(field("current").logicalMinimum(field("updated")).as("price_min")) ); // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = await execute(db.pipeline().collection("books") .aggregate(field("price").minimum().as("min_price")) );
Swift
var results: Pipeline.Snapshot // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = try await db.pipeline().collection("books") .select([ Field("current").logicalMinimum(["updated"]).as("price_min") ]) .execute() // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = try await db.pipeline().collection("books") .aggregate([Field("price").minimum().as("min_price")]) .execute()
Kotlin
var results: Task<Pipeline.Snapshot> // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = db.pipeline().collection("books") .select( field("current").logicalMinimum("updated").alias("price_min") ) .execute() // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = db.pipeline().collection("books") .aggregate(AggregateFunction.minimum("price").alias("min_price")) .execute()
Java
Task<Pipeline.Snapshot> results; // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = db.pipeline().collection("books") .select( field("current").logicalMinimum("updated").alias("price_min") ) .execute(); // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = db.pipeline().collection("books") .aggregate(AggregateFunction.minimum("price").alias("min_price")) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field # Type 1: Scalar (for use in non-aggregation stages) # Example: Return the min store price for each book. results = ( client.pipeline() .collection("books") .select( Field.of("current").logical_minimum(Field.of("updated")).as_("price_min") ) .execute() ) # Type 2: Aggregation (for use in aggregate stages) # Example: Return the min price of all books. results = ( client.pipeline() .collection("books") .aggregate(Field.of("price").minimum().as_("min_price")) .execute() )
الحدود
في معظم الحالات، لا يفرض إصدار Enterprise قيودًا على شكل طلب البحث. بعبارة أخرى، لا يقتصر الأمر على عدد صغير من القيم في طلب بحث IN أو OR. بدلاً من ذلك، هناك حدّان أساسيان يجب أن تكون على دراية بهما:
- الموعد النهائي: 60 ثانية (كما هو الحال في الإصدار Standard).
- استخدام الذاكرة: حدّ يبلغ 128 ميغابايت على كمية البيانات المادية أثناء تنفيذ طلب البحث
الأخطاء
قد تواجه طلبات بحث غير ناجحة لعدة أسباب. إليك رابط يؤدي إلى الأخطاء الشائعة والإجراءات المرتبطة التي يمكنك اتّخاذها:
| رمز الخطأ | الإجراء |
DEADLINE_EXCEEDED
|
يتجاوز طلب البحث الذي تنفّذه مهلة 60 ثانية ويتطلّب تحسينًا إضافيًا. يُرجى الاطّلاع على قسم "الأداء" للحصول على نصائح. إذا لم تتمكّن من تحديد السبب الجذري للمشكلة، تواصَل مع الفريق. |
RESOURCE_EXHAUSTED
|
يتجاوز طلب البحث الذي تنفّذه حدود الذاكرة ويتطلّب تحسينًا إضافيًا. يُرجى الاطّلاع على قسم "الأداء" للحصول على نصائح. إذا لم تتمكّن من تحديد السبب الجذري للمشكلة، تواصَل مع الفريق. |
INTERNAL
|
التواصل مع الفريق للحصول على الدعم |
الأداء
على عكس طلبات البحث الحالية، لا تتطلّب عمليات Pipeline توفّر فهرس دائمًا. وهذا يعني أنّ طلب البحث يمكن أن يستغرق وقتًا أطول مقارنةً بطلبات البحث الحالية التي كانت ستتعذّر على الفور بسبب خطأ FAILED_PRECONDITION في الفهرس غير المتوفّر. لتحسين أداء عمليات Pipeline، يمكنك اتّخاذ بعض الخطوات.
إنشاء الفهارس
الفهرس المستخدَم
تتيح لك ميزة "شرح طلب البحث" تحديد ما إذا كان طلب البحث يتم عرضه من خلال فهرس أو الرجوع إلى عملية أقل كفاءة، مثل فحص الجدول. إذا لم يتم عرض طلب البحث بالكامل من فهرس، يمكنك إنشاء فهرس باتّباع التعليمات.
إنشاء الفهارس
يمكنك اتّباع مستندات إدارة الفهرس الحالية لإنشاء الفهارس. قبل إنشاء فهرس، يُرجى الاطّلاع على أفضل الممارسات العامة المتعلّقة بالفهارس في Cloud Firestore. لضمان إمكانية استخدام الفهارس في طلب البحث، اتّبِع أفضل الممارسات لإنشاء فهارس تتضمّن حقولاً بالترتيب التالي:
- جميع الحقول التي سيتم استخدامها في فلاتر المساواة (بأي ترتيب)
- جميع الحقول التي سيتم ترتيبها (بالترتيب نفسه)
- الحقول التي سيتم استخدامها في فلاتر النطاق أو عدم المساواة بترتيب تنازلي حسب اختيارية قيود الطلب
على سبيل المثال، بالنسبة إلى طلب البحث التالي،
Web
const results = await execute(db.pipeline() .collection("books") .where(field("published").lessThan(1900)) .where(field("genre").equal("Science Fiction")) .where(field("rating").greaterThan(4.3)) .sort(field("published").descending()) );
Swift
let results = try await db.pipeline() .collection("books") .where(Field("published").lessThan(1900)) .where(Field("genre").equal("Science Fiction")) .where(Field("rating").greaterThan(4.3)) .sort([Field("published").descending()]) .execute()
Kotlin
val results = db.pipeline() .collection("books") .where(field("published").lessThan(1900)) .where(field("genre").equal("Science Fiction")) .where(field("rating").greaterThan(4.3)) .sort(field("published").descending()) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .where(field("published").lessThan(1900)) .where(field("genre").equal("Science Fiction")) .where(field("rating").greaterThan(4.3)) .sort(field("published").descending()) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .where(Field.of("published").less_than(1900)) .where(Field.of("genre").equal("Science Fiction")) .where(Field.of("rating").greater_than(4.3)) .sort(Field.of("published").descending()) .execute() )
الفهرس المقترَح هو فهرس نطاق مجموعة على books لـ (genre [...], published DESC, avg_rating DESC).
كثافة الفهرس
تتيح Cloud Firestore استخدام فهارس متفرقة وغير متفرقة. لمزيد من المعلومات، اطّلِع على كثافة الفهرسة.
طلبات البحث المغطّاة والفهارس الثانوية
يمكن لـ Cloud Firestore تخطّي جلب المستند الكامل وعرض النتائج من الفهرس فقط إذا كانت جميع الحقول التي يتم عرضها متوفرة في فهرس ثانوي. يؤدي ذلك عادةً إلى تحسين كبير في وقت الاستجابة (والتكلفة). باستخدام نموذج الاستعلام أدناه:
Web
const results = await execute(db.pipeline() .collection("books") .where(field("category").like("%fantasy%")) .where(field("title").exists()) .where(field("author").exists()) .select(field("title"), field("author")) );
Swift
let results = try await db.pipeline() .collection("books") .where(Field("category").like("%fantasy%")) .where(Field("title").exists()) .where(Field("author").exists()) .select([Field("title"), Field("author")]) .execute()
Kotlin
val results = db.pipeline() .collection("books") .where(field("category").like("%fantasy%")) .where(field("title").exists()) .where(field("author").exists()) .select(field("title"), field("author")) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .where(field("category").like("%fantasy%")) .where(field("title").exists()) .where(field("author").exists()) .select(field("title"), field("author")) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .where(Field.of("category").like("%fantasy%")) .where(Field.of("title").exists()) .where(Field.of("author").exists()) .select("title", "author") .execute() )
إذا كانت قاعدة البيانات تتضمّن فهرس نطاق مجموعة على books لـ (category [...], title [...], author [...])، يمكنها تجنُّب جلب أي بيانات من المستندات الرئيسية نفسها. في هذه الحالة، لا يهم الترتيب في الفهرس، ويتم استخدام [...] للإشارة إلى ذلك.
تقييد الحقول المطلوب عرضها
يعرض طلب البحث Cloud Firestore تلقائيًا جميع الحقول في المستند، وهو ما يشبه SELECT * في الأنظمة التقليدية. إذا كان تطبيقك يحتاج فقط إلى مجموعة فرعية من الحقول، يمكن استخدام مرحلتَي select(...) أو restrict(...) لإجراء هذه الفلترة من جهة الخادم. سيؤدي ذلك إلى تقليل حجم الاستجابة (ما يؤدي إلى خفض تكلفة نقل البيانات خارج الشبكة) بالإضافة إلى تحسين وقت الاستجابة.
أدوات تحرّي الخلل وإصلاحه
شرح الطلب
تتيح لك ميزة "شرح طلب البحث" إمكانية الاطّلاع على مقاييس التنفيذ وتفاصيل حول الفهارس المستخدَمة.
المقاييس
عمليات خط الإنتاج إذا كانت مدمجة بالكامل مع مقاييس Cloud Firestore الحالية
المشاكل والقيود المعروفة
الفهارس المتخصّصة
لا تتيح عمليات خطوط الإنتاج بعد array-contains وvector أنواع الفهرس الحالية. بدلاً من رفض هذه الطلبات فقط، سيحاول Cloud Firestore استخدام فهارس ascending وdescending أخرى حالية. من المتوقّع أن تكون عمليات "مسار البيانات" التي تتضمّن تعبيرات array_contains أو find_nearest أبطأ من العمليات المشابهة الحالية خلال المعاينة الخاصة بسبب ذلك.
الحدود الفاصلة للصفحات
لا تتوفّر إمكانية تقسيم مجموعة النتائج إلى صفحات بسهولة أثناء المعاينة الخاصة. يمكن حلّ هذه المشكلة من خلال ربط مراحل where(...) وsort(...) المكافئة كما هو موضّح أدناه.
Web
// Existing pagination via `startAt()` const q = query(collection(db, "cities"), orderBy("population"), startAt(1000000)); // Private preview workaround using pipelines const pageSize = 2; const pipeline = db.pipeline() .collection("cities") .select("name", "population", "__name__") .sort(field("population").descending(), field("__name__").ascending()); // Page 1 results let snapshot = await execute(pipeline.limit(pageSize)); // End of page marker const lastDoc = snapshot.results[snapshot.results.length - 1]; // Page 2 results snapshot = await execute( pipeline .where( or( and( field("population").equal(lastDoc.get("population")), field("__name__").greaterThan(lastDoc.ref) ), field("population").lessThan(lastDoc.get("population")) ) ) .limit(pageSize) );
Swift
// Existing pagination via `start(at:)` let query = db.collection("cities").order(by: "population").start(at: [1000000]) // Private preview workaround using pipelines let pipeline = db.pipeline() .collection("cities") .where(Field("population").greaterThanOrEqual(1000000)) .sort([Field("population").descending()])
Kotlin
// Existing pagination via `startAt()` val query = db.collection("cities").orderBy("population").startAt(1000000) // Private preview workaround using pipelines val pipeline = db.pipeline() .collection("cities") .where(field("population").greaterThanOrEqual(1000000)) .sort(field("population").descending())
Java
// Existing pagination via `startAt()` Query query = db.collection("cities").orderBy("population").startAt(1000000); // Private preview workaround using pipelines Pipeline pipeline = db.pipeline() .collection("cities") .where(field("population").greaterThanOrEqual(1000000)) .sort(field("population").descending());
Python
from google.cloud.firestore_v1.pipeline_expressions import Field # Existing pagination via `start_at()` query = ( client.collection("cities") .order_by("population") .start_at({"population": 1_000_000}) ) # Private preview workaround using pipelines pipeline = ( client.pipeline() .collection("cities") .where(Field.of("population").greater_than_or_equal(1_000_000)) .sort(Field.of("population").descending()) )
التوافق مع المحاكي
لا يتيح المحاكي عمليات Pipeline بعد.
التوافق مع ميزة "في الوقت الفعلي" وبلا إنترنت
لا تتوفّر بعد إمكانات الوقت الفعلي وبلا إنترنت لعمليات خطوط الإنتاج.
الخطوات التالية
- ابدأ باستكشاف المستندات المرجعية الخاصة بالدوال والمراحل.