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)
המשך
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
C#
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);
שיקולים בהוספה לאינדקס
לפני שמריצים את השאילתות, כדאי לקרוא על [שאילתות][1] ועל Cloud Firestore [מודל הנתונים][2].
ב-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 משתמש בשדות הכי שמאליים של אינדקס מורכב כדי לעמוד במגבלות השוויון ובמגבלות הטווח או אי-השוויון, אם יש כאלה, בשדה הראשון של שאילתת orderBy(). המגבלות האלה יכולות להפחית את מספר רשומות האינדקס ש-Cloud Firestore סורק. Cloud Firestore משתמש בשדות הנותרים של האינדקס כדי לעמוד במגבלות אחרות של טווח או אי-שוויון של השאילתה. המגבלות האלה לא מפחיתות את מספר רשומות האינדקס ש-Cloud Firestore סורק, אבל הן מסננות מסמכים לא תואמים כדי להפחית את מספר המסמכים שמוחזרים ללקוחות.
מידע נוסף על יצירת אינדקסים יעילים זמין במאמר [מאפייני אינדקס][4].
סידור השדות בסדר יורד של סלקטיביות אילוצי השאילתה
כדי לוודא ש-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המסנן עדיין נקראות, ולכן זמן האחזור והעלות של השאילתה גדלים.
תמחור
החיוב על שאילתות עם מסנני טווח ומסנני אי-שוויון בכמה שדות מבוסס על מספר המסמכים שנקראו ומספר רשומות האינדקס שנקראו.
מידע מפורט זמין בדף [תמחור][5].
מגבלות
בנוסף ל[מגבלות על שאילתות][6], חשוב לשים לב למגבלות הבאות לפני שמשתמשים בשאילתות עם מסנני טווח ומסנני אי-שוויון בכמה שדות:
- אין תמיכה בשאילתות עם מסנני טווח או מסנני אי-שוויון בשדות של מסמכים, ורק אילוצי שוויון במפתח המסמך
(__name__). - ב-Cloud Firestore מספר השדות של טווח או אי-שוויון מוגבל ל-10. המטרה היא למנוע מצב שבו עלות ההרצה של שאילתות תהיה גבוהה מדי.
המאמרים הבאים
- [מידע נוסף על אופטימיזציה של שאילתות][3]
- מידע נוסף על [ביצוע שאילתות פשוטות ומורכבות][8]
- הסבר על האופן שבו [Cloud Firestore משתמש באינדקסים][9].
[1]: /docs/firestore/query-data/get-data [2]: /docs/firestore/data-model [3]: /docs/firestore/query-data/multiple-range-optimize-indexes [4]: /docs/firestore/concepts/index-overview#index_properties [5]: /docs/firestore/pricing [6]: /docs/firestore/query-data/queries#query_limitations [7]: https://en.wikipedia.org/wiki/Disjunctive_normal_form [8]: /docs/firestore/query-data/queries [9]: /docs/firestore/concepts/index-overview [10]: /docs/firestore/query-data/multiple-range-optimize-indexes