پسزمینه
عملیات خط لوله میانای پُرسمان جدیدی برای Cloud Firestore ارائه میدهد که از عملکرد پُرسمان پیشرفته و عبارتهای پیچیده پشتیبانی میکند. این زبان توابع جدید بسیاری را معرفی میکند، ازجمله min(...)، max(...)،
substring(...)، regex_match(...)، و array_contains_all(...)، و مراحلی
برای انجام تبدیلهای پیچیده.
شروع به کار
برای نصب و مقداردهی اولیه کیتهای توسعه نرمافزار کارخواه، به دستورالعملهای راهنماهای زیر مراجعه کنید:
نحو
بخشهای زیر نمای کلی از نحو عملیات Pipeline ارائه میدهند.
مفاهیم
یک تفاوت قابلتوجه با عملیات Pipeline، معرفی ترتیب صریح «مرحله» است. این کار امکان بیان پُرسمانهای پیچیدهتر را فراهم میکند. بااینحال، این انحراف قابلتوجهی از میانای پُرسمان موجود بااستفاده از عملیاتهای Core است که در آن ترتیب مراحل ضمنی بود. نمونه عملیات 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);
پایتون
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) )
رفتن
pipeline := client.Pipeline(). Collection("cities"). Where(firestore.FieldOf("population").GreaterThan(100000)). Sort(firestore.Orders(firestore.Ascending(firestore.FieldOf("name")))). 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();
پایتون
firestore_client = firestore.client(default_app, "your-new-enterprise-database") pipeline = firestore_client.pipeline()
رفتن
client, err := firestore.NewClientWithDatabase(ctx, projectID, databaseID) if err != nil { fmt.Fprintf(w, "firestore.NewClientWithDatabase failed: %v", err) return err } defer client.Close() pipeline := client.Pipeline().Collection("books")
ساختار
هنگام ایجاد عملیات Pipeline، درک چند اصطلاح مهم است: مراحل، عبارتها، و توابع و پوشانندههای زیرپرسوجو.

مراحل: خط لوله ممکن است از یک یا چند مرحله تشکیل شده باشد. از نظر منطقی، اینها نشاندهنده مجموعه مراحلی (یا مراحلی) هستند که برای اجرای پُرسمان انجام شدهاند.
عبارتها: مراحل اغلب عبارتی را میپذیرند که به شما امکان میدهد پُرسمانهای پیچیدهتری را بیان کنید. عبارت ممکن است ساده باشد و از یک تابع تشکیل شده باشد
مثل eq("a", 1). همچنین میتوانید با تودرتو کردن عبارتهایی مثل and(eq("a", 1), eq("b", 2)).، عبارتهای پیچیدهتری را بیان کنید
پوشانندههای زیرپرسوجو: توابعی مانند array() و scalar() به شما امکان میدهند
یک خط لوله تودرتو را بهعنوان یک عبارت در یک مرحله جاسازی کنید.
فیلدها / ثابتها / متغیرها
عملیات خط لوله از عبارتهای پیچیده پشتیبانی میکند. به همین دلیل، مهم است که تشخیص دهید آیا مقدار نشاندهنده فیلد، ثابت، یا متغیر است.
درحالیکه فیلدها به دادههای درون اسناد اشاره میکنند و ثابتها امکان
مشخص کردن هر مقداری را بهعنوان آرگومان برای عبارت فراهم میکنند، متغیرها امکان
تعریف و استفاده از مقادیر موقتی را فراهم میکنند که بهجای اسناد درحال پردازش،
به اجرای پُرسمان محدود میشوند. در ادامه، نمای کلی این مفاهیم ارائه شده است، برای اطلاعات بیشتر درباره نحوه خواندن و نوشتن متغیرها درطول اجرای پُرسمان، به مرحله let(...) مراجعه کنید.
| فیلدها | ثابتها | متغیر | |
|---|---|---|---|
| هدف | دسترسی به فیلدها یا ذخیره کردن آنها در اسناد | مقدار ثابتی را مشخص کنید | استفاده از مقادیر موقت درطول اجرای خط لوله |
| استفاده از کیت توسعه نرمافزار | field("name") |
constant("val") |
variable("name") |
| Scope | محلی برای سند فعلی | جهانی | سراسری به خط لوله و خط لولههای فرعی |
| مرجع تعریفنشده | به absent ارزیابی میشود |
نامربوط | خطای زمان اجرا تولید میکند |
نمونه:
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")));
پایتون
from google.cloud.firestore_v1.pipeline_expressions import Field, Constant pipeline = ( client.pipeline() .collection("cities") .where(Field.of("name").equal(Constant.of("Toronto"))) )
رفتن
pipeline := client.Pipeline().Collection("cities"). Where(firestore.FieldOf("name").Equal(firestore.ConstantOf("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();
پایتون
# 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() )
رفتن
// Return all restaurants in San Francisco results1, err := client.Pipeline().Collection("cities/sf/restaurants").Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } // Return all restaurants results2, err := client.Pipeline().CollectionGroup("restaurants").Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } // Return all documents across all collections in the database (the entire database) results3, err := client.Pipeline().Database().Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } // Batch read of 3 documents results4, err := client.Pipeline(). Documents([]*firestore.DocumentRef{ client.Collection("cities").Doc("SF"), client.Collection("cities").Doc("DC"), client.Collection("cities").Doc("NY"), }). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err }
مانند همه مراحل دیگر، ترتیب نتایج حاصل از این مراحل ورودی پایدار نیست. اگر ترتیب خاصی لازم باشد،
همیشه باید عملگر 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();
پایتون
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() )
رفتن
results1, err := client.Pipeline(). Collection("books"). Where(firestore.FieldOf("rating").Equal(5)). Where(firestore.FieldOf("published").LessThan(1900)). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } results2, err := client.Pipeline(). Collection("books"). Where(firestore.And( firestore.FieldOf("rating").Equal(5), firestore.FieldOf("published").LessThan(1900), )). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err }
انتخاب / افزودن و برداشتن فیلدها
select(...)،
add_fields(...)، و
remove_fields(...) همگی به شما امکان میدهند
فیلدهای برگرداندهشده از مرحله قبلی را اصلاح کنید. این سه نوع معمولاً
بهعنوان مراحل سبک فرافکنی شناخته میشوند.
select(...) و
add_fields(...) به شما امکان میدهند نتیجه عبارت را برای نام فیلد ارائهشده توسط کاربر مشخص کنید. 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();
پایتون
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() )
رفتن
snapshot := client.Pipeline(). Collection("books"). Aggregate( firestore.Accumulators(firestore.Average("rating").As("avg_rating")), firestore.WithAggregateGroups("genre"), ). Execute(ctx)
وقتی 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();
پایتون
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .distinct(Field.of("author").to_upper().as_("author"), "genre") .execute() )
رفتن
snapshot := client.Pipeline(). Collection("books"). Distinct(firestore.Fields( firestore.ToUpper(firestore.FieldOf("author")).As("author"), firestore.FieldOf("genre"), )). Execute(ctx)
توابع
توابع واحد سازنده برای ایجاد عبارتها و پُرسمانهای پیچیده هستند. برای مشاهده فهرست کامل توابع بههمراه مثال، به مرجع توابع مراجعه کنید. بهعنوان یادآوری سریع، ساختار یک پُرسمان معمولی را درنظر بگیرید:

بسیاریاز مراحل عبارتهایی را میپذیرند که شامل یک یا چند تابع است. رایجترین کاربرد تابع در مراحل 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();
پایتون
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() )
رفتن
// Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results1, err := client.Pipeline(). Collection("books"). Select(firestore.Fields( firestore.LogicalMinimum(firestore.FieldOf("current"), firestore.FieldOf("updated")).As("price_min"), )). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results2, err := client.Pipeline(). Collection("books"). Aggregate(firestore.Accumulators( firestore.Minimum("price").As("min_price"), )). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err }
محدودیتها
در بیشتر موارد، نسخه Enterprise محدودیتی بر شکل پُرسمان اعمال نمیکند. بهعبارت دیگر، به تعداد کمی از مقادیر در پُرسمان IN یا OR محدود نیستید. درعوض، دو محدودیت اصلی وجود دارد که باید از آنها مطلع باشید:
- مهلت: ۶۰ ثانیه (مشابه نسخه Standard).
- استفاده از حافظه: محدودیت ۱۲۸ مبیبایت برای مقدار دادههای تحققیافته درطول اجرای پُرسمان.
خطاها
ممکن است به دلایل مختلفی با پُرسمانهای ناموفق مواجه شوید. در اینجا پیوندی به خطاهای رایج و اقدام مرتبطی که میتوانید انجام دهید آورده شده است:
| کد خطا | اکشن |
DEADLINE_EXCEEDED
|
پرسوجویی که اجرا میکنید از مهلت ۶۰ ثانیهای فراتر میرود و به بهینهسازی بیشتری نیاز دارد. برای نکتهها، بخش عملکرد را ببینید. اگر نمیتوانید علت ریشهای مشکل را پیدا کنید، با تیم تماس بگیرید. |
RESOURCE_EXHAUSTED
|
پُرسمانی که اجرا میکنید از حد مجاز حافظه فراتر میرود و به بهینهسازی بیشتری نیاز دارد. برای نکتهها، بخش عملکرد را ببینید. اگر نمیتوانید علت ریشهای مشکل را پیدا کنید، با تیم تماس بگیرید. |
INTERNAL
|
برای دریافت پشتیبانی، با تیم تماس بگیرید. |
عملکرد
پایگاههای داده نسخه Enterprise نیازی به وجود همیشگی نمایه ندارند.
این یعنی پُرسمان میتواند درمقایسه با پُرسمانهای موجود که بهدلیل خطای نمایه گمشده 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();
پایتون
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() )
رفتن
snapshot := client.Pipeline(). Collection("books"). Where(firestore.FieldOf("published").LessThan(1900)). Where(firestore.FieldOf("genre").Equal("Science Fiction")). Where(firestore.FieldOf("rating").GreaterThan(4.3)). Sort(firestore.Orders(firestore.Descending(firestore.FieldOf("published")))). Execute(ctx)
نمایه توصیهشده نمایه محدوده مجموعه در 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();
پایتون
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() )
رفتن
snapshot := client.Pipeline(). Collection("books"). Where(firestore.FieldOf("category").Like("%fantasy%")). Where(firestore.FieldOf("title").FieldExists()). Where(firestore.FieldOf("author").FieldExists()). Select(firestore.Fields("title", "author")). Execute(ctx)
اگر پایگاه داده ازقبل نمایه محدوده مجموعه در books برای
(category [...], title [...], author [...]) داشته باشد، میتواند از واکشی
هرچیزی از خود اسناد اصلی اجتناب کند. در این مورد، ترتیب در نمایه اهمیتی ندارد، [...] برای نشان دادن این موضوع استفاده میشود.
محدود کردن فیلدها برای برگرداندن
بهطور پیشفرض، پُرسمان Cloud Firestore همه فیلدهای سند را برمیگرداند،
مشابه SELECT * در سیستمهای رابطهای. اما اگر برنامه شما
فقط به زیرمجموعهای از فیلدها نیاز دارد، میتوان از مراحل select(...)
یا restrict(...) برای انتقال این فیلتر به سمت سرور استفاده کرد. این کار هم اندازه پاسخ را کاهش میدهد (کاهش هزینه خروج شبکه) و هم تأخیر را بهبود میبخشد.
ابزارهای عیبیابی
توضیح پُرسمان
Query Explain به شما امکان میدهد سنجههای اجرا و جزئیات نمایههای استفادهشده را مشاهده کنید.
سنجهها
عملیات خط لوله اگر کاملاً با سنجههای Cloud Firestore موجود ادغام شده باشد.
مشکلات شناختهشده / محدودیتها
شاخصهای تخصصی
عملیات خط لوله هنوز از array-contains و vector انواع نمایه موجود پشتیبانی نمیکند. بهجای رد کردن این پُرسمانها، Cloud Firestore تلاش میکند از نمایههای ascending و descending موجود دیگر استفاده کند. انتظار میرود که با چنین array_contains یا find_nearest، عبارتها بهدلیل این موضوع کندتر از معادلهای موجودشان باشند.
پشتیبانی همزمان و آفلاین
عملیات خط لوله قابلیتهای همزمان و آفلاین ندارد.
حالا چه میشود
- کاوش اسناد مرجع توابع و مراحل را شروع کنید.
- با نحوه انجام پیوستن با زیرپرسشها آشنا شوید.