סקירה כללית של שאילתה עם מסנני טווח ואי-שוויון בכמה שדות

ב-Cloud Firestore יש תמיכה בשימוש במסנני טווחים ובמסנני אי-שוויון במספר שדות בשאילתה אחת. אפשר להשתמש בתנאי טווח ובתנאי אי-שוויון בכמה שדות, ולפשט את פיתוח האפליקציה על ידי הענקת גישה ל-Cloud Firestore להטמעת הלוגיקה שלאחר הסינון.

מסננים של טווח ואי-שוויון בשדות מרובים

השאילתה הבאה משתמשת במסנני טווח של אוכלוסייה וצפיפות כדי להחזיר את כל הערים שבהן האוכלוסייה גדולה מ-1,000,000 אנשים, וצפיפות האוכלוסייה קטנה מ-10,000 אנשים ליחידת שטח.

גרסת אינטרנט 9 מודולרית

const q = query(
    collection(db, "cities"),
    where('population', '>', 1000000),
    where('density', '<', 10000),
  );

Swift

let query = db.collection("cities")
  .whereField("population", isGreaterThan: 1000000)
  .whereField("density", isLessThan: 10000)

Objective-C

FIRQuery *query =
 [[[[self.db collectionWithPath:@"cities"]
queryWhereField:@"population" isGreaterThan:@1000000]
   queryWhereField:@"density" isLessThan:@10000];

Java ב-Android

Query query = db.collection("cities")
 .whereGreaterThan("population", 1000000)
 .whereLessThan("density", 10000);

Kotlin+KTX Android

val query = db.collection("cities")
 .whereGreaterThan("population", 1000000)
 .whereLessThan("density", 10000)

Go

   query := client.Collection("cities").
      Where("population", ">", 1000000).
      Where("density", "<", 10000)

Java

db.collection("cities")
  .whereGreaterThan("population", 1000000)
  .whereLessThan("density", 10000);

Node.js

db.collection("cities")
  .where('population', '>', 1000000),
  .where('density', '<', 10000)

Python

from google.cloud import firestore

db = firestore.Client()
query = db.collection("cities")
.where("population", ">", 1000000)
.where("density", "<", 10000)

PHP

$collection = $db->collection('samples/php/cities');
$chainedQuery = $collection
    ->where('population', '>', 1000000)
    ->where('density', '<', 10000);

C#‎

CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef
    .WhereGreaterThan("Population", 1000000)
    .WhereLessThan("Density", 10000);
QuerySnapshot querySnapshot = await query.GetSnapshotAsync();
foreach (DocumentSnapshot documentSnapshot in querySnapshot)
{
    var name = documentSnapshot.GetValue<string>("Name");
    var population = documentSnapshot.GetValue<int>("Population");
    var density = documentSnapshot.GetValue<int>("Density");
    Console.WriteLine($"City '{name}' returned by query. Population={population}; Density={density}");
}

Ruby

query = cities_ref.where("population", ">", "1000000")
                  .where("density", "<", 10000)

C++‎

CollectionReference cities_ref = db->Collection("cities");
Query query = cities_ref.WhereGreaterThan("population", FieldValue::Integer(1000000))
                       .WhereLessThan("density", FieldValue::Integer(10000));

Unity

CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef.WhereGreaterThan("population", 1000000)
                      .WhereLessThan("density", 10000);

Dart

final citiesRef = FirebaseFirestore.instance.collection('cities')
final query = citiesRef.where("population", isGreaterThan: 1000000)
                  .where("density", isLessThan: 10000);

שיקולים לגבי הוספה לאינדקס

לפני שמריצים את השאילתות, כדאי לקרוא על שאילתות ועל מודל הנתונים של Cloud Firestore.

ב-Cloud Firestore, הסעיף ORDER BY של השאילתה קובע באילו אינדקסים אפשר להשתמש כדי להציג את השאילתה. לדוגמה, לשאילתה ORDER BY a ASC, b ASC נדרש אינדקס מורכב בשדות a ASC, b ASC.

כדי לשפר את הביצועים והעלות של שאילתות Cloud Firestore, צריך לבצע אופטימיזציה של סדר השדות באינדקס. כדי לעשות זאת, צריך לוודא שהאינדקס מסודר משמאל לימין, כך שהשאילתה תתמצת למערך נתונים שימנע סריקת רשומות אינדקס מיותרות.

נניח שאתם רוצים לחפש באוסף של עובדים ולמצוא עובדים בארצות הברית שהמשכורת שלהם גבוהה מ-100,000$ ומספר שנות הניסיון שלהם גדול מאפס. על סמך ההבנה שלכם של מערך הנתונים, אתם יודעים שהאילוץ על השכר סלקטיבי יותר מהאילוץ על ניסיון העבודה. האינדקס האידיאלי שיצמצם את מספר סריקות האינדקס הוא (salary [...], experience [...]). לכן, השאילתה שתהיה מהירה ומשתלמת תסדר את salary לפני experience ותיראה כך:

Java

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .whereGreaterThan("experience", 0)
  .orderBy("salary")
  .orderBy("experience");

Node.js

db.collection("employees")
  .where("salary", ">", 100000)
  .where("experience", ">", 0)
  .orderBy("salary")
  .orderBy("experience");

Python

db.collection("employees")
  .where("salary", ">", 100000)
  .where("experience", ">", 0)
  .order_by("salary")
  .order_by("experience");

שיטות מומלצות לאופטימיזציה של מדדים

כשמבצעים אופטימיזציה של אינדקסים, כדאי לזכור את השיטות המומלצות הבאות.

סדר שדות האינדקס לפי שוויות, ואחריהם השדה עם הטווח או אי-השוויון הסלקטיבי ביותר

Cloud Firestore משתמש בשדות הכי שמאליים של אינדקס מורכב כדי לעמוד במגבלות השוויון ובאילוץ הטווח או אי השוויון, אם יש, בשדה הראשון של השאילתה orderBy(). האילוצים האלה יכולים לצמצם את מספר רשומות האינדקס ש-Cloud Firestore סורק. Cloud Firestore משתמש בשדות הנותרים באינדקס כדי לעמוד במגבלות אחרות של טווח או אי-שוויון של השאילתה. האילוצים האלה לא מפחיתים את מספר הרשומות באינדקס ש-Cloud Firestore סורק, אבל הם מסננים מסמכים שלא תואמים, כך שמספר המסמכים שמוחזרים ללקוחות מצטמצם.

מידע נוסף על יצירת אינדקסים יעילים זמין במאמר מאפייני אינדקס.

סידור שדות בסדר יורד של סלקטיביות של אילוצי שאילתות

כדי לוודא ש-Cloud Firestore יבחר את האינדקס האופטימלי לשאילתה, צריך לציין תנאי orderBy() שמסדר את השדות בסדר יורד של סלקטיביות האילוצים של השאילתה. ככל שהסלקטיביות גבוהה יותר, כך מתבצעות התאמות לקבוצת משנה קטנה יותר של מסמכים, וככל שהסלקטיביות נמוכה יותר, כך מתבצעות התאמות לקבוצת משנה גדולה יותר של מסמכים. חשוב לבחור שדות טווח או אי-שוויון עם סלקטיביות גבוהה יותר בשלב מוקדם יותר ברשימת האינדקסים מאשר שדות עם סלקטיביות נמוכה יותר.

כדי לצמצם את מספר המסמכים ש-Cloud Firestore סורק ומחזיר ברשת, צריך תמיד לסדר את השדות בסדר יורד של סלקטיביות של מגבלות השאילתה. אם התוצאה לא מופיעה בסדר הנדרש והתוצאה צפויה להיות קטנה, אפשר להטמיע לוגיקה בצד הלקוח כדי לשנות את הסדר לפי הציפיות שלכם.

לדוגמה, נניח שאתם רוצים לחפש באוסף עובדים כדי למצוא עובדים שהשכר שלהם גבוה מ-100,000$, ולסדר את התוצאות לפי שנת הניסיון של העובד. אם אתם מצפים שרק למספר קטן של עובדים יהיו משכורות גבוהות מ-100,000$, הדרך היעילה ביותר לכתוב את השאילתה היא:

Java

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .orderBy("salary")
  .get()
  .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
        @Override
        public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
          // Order results by `experience`
        }
    });;

Node.js

const querySnapshot = await db.collection('employees')
                              .where("salary", ">", 100000)
                              .orderBy("salary")
                              .get();

// Order results by `experience`

Python

results = db.collection("employees")
            .where("salary", ">", 100000)
            .order_by("salary")
            .stream()

// Order results by `experience`

הוספת סדר של experience לשאילתה תניב את אותה קבוצה של מסמכים ותבטל את הצורך בסדר מחדש של התוצאות בלקוחות, אבל השאילתה עשויה לקרוא הרבה יותר רשומות מיותרות באינדקס בהשוואה לשאילתה הקודמת. הסיבה לכך היא ש-Cloud Firestore תמיד מעדיף אינדקס שהתחילית של שדות האינדקס שלו תואמת לתנאי order by בשאילתה. אם מוסיפים את experience להזמנה לפי סעיף, Cloud Firestore יבחר את האינדקס (experience [...], salary [...]) לחישוב תוצאות של שאילתות. מכיוון שאין אילוצים אחרים על experience, Cloud Firestore יקרא את כל רשומות האינדקס של האוסף employees לפני החלת המסנן salary כדי למצוא את התוצאה הסופית. המשמעות היא שעדיין מתבצעת קריאה של רשומות אינדקס שלא עומדות בקריטריונים של המסנן salary, וכך משך האחזור והעלות של השאילתה עולים.

תמחור

שאילתות עם מסנני טווח ואי-שוויון בכמה שדות יחויבו על סמך מסמכים שנקראו ורשומות שנוספו לאינדקס שנקראו.

מידע מפורט זמין בדף Pricing.

מגבלות

מלבד מגבלות השאילתות, שימו לב למגבלות הבאות לפני שמשתמשים בשאילתות עם מסננים של טווח ואי-שוויון בשדות מרובים:

  • אין תמיכה בשאילתות עם מסנני טווח או אי-שוויון בשדות המסמך, ורק באילוצים של שוויון במפתח המסמך (__name__).
  • הפונקציה Cloud Firestore מגבילה את מספר שדות הטווח או אי השוויון ל-10. המטרה היא למנוע הוצאות יקרות מדי על הרצת שאילתות.

המאמרים הבאים