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

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

מסנני טווח ואי-שוויון בכמה שדות

השאילתה הבאה משתמשת במסנני טווח על אוכלוסייה וצפיפות כדי להחזיר את כל הערים שבהן האוכלוסייה גדולה ממיליון איש וצפיפות האוכלוסייה קטנה מ-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 $ומספר שנות הניסיון שלהם גדול מ-0. על סמך ההבנה של מערך הנתונים, אתם יודעים שהאילוץ של השכר הוא סלקטיבי יותר מהאילוץ של הניסיון. האינדקס האידיאלי שיצמצם את מספר הסריקות של האינדקס יהיה (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 משתמש בשדות הימניים ביותר של אינדקס מורכב כדי לעמוד במגבלות השוויון ובמגבלות הטווח או אי-השוויון, אם יש כאלה, בשדה הראשון של שאילתת 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 נוסף לסעיף order by,‏ Cloud Firestore יבחר באינדקס (experience [...], salary [...]) לחישוב תוצאות השאילתה. מכיוון שאין אילוצים אחרים על experience, הפונקציה Cloud Firestore תקרא את כל הרשומות באינדקס של האוסף employees לפני החלת המסנן salary כדי למצוא את קבוצת התוצאות הסופית. המשמעות היא שרשומות באינדקס שלא עומדות בדרישות של המסנן salary עדיין נקראות, ולכן זמן האחזור והעלות של השאילתה גדלים.

תמחור

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

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

מגבלות

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

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

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