תיאור
איתור כל השילובים השונים של ערכים בסדרת ביטויים.
לשלב distinct(...) יש תחביר דומה לזה של select(...), כי הוא מקבל ביטוי אחד או יותר שאפשר לבחור. אפשר להשתמש במחרוזות כשהביטוי הוא רק הפניה לשדה:
דוגמאות
Node.js
let cities = await db.pipeline() .collection("cities") .distinct("country") .execute(); cities = await db.pipeline() .collection("cities") .distinct( field("state").toLower().as("normalizedState"), field("country")) .execute();
Web
let cities = await execute(db.pipeline() .collection("cities") .distinct("country")); cities = await execute(db.pipeline() .collection("cities") .distinct( field("state").toLower().as("normalizedState"), field("country")));
Swift
let results = try await db.pipeline() .collection("books") .distinct([ Field("author").toUpper().as("author"), Field("genre") ]) .execute()
Kotlin
var cities = db.pipeline() .collection("cities") .distinct("country") .execute() cities = db.pipeline() .collection("cities") .distinct( field("state").toLower().alias("normalizedState"), field("country") ) .execute()
Java
Task<Pipeline.Snapshot> cities; cities = db.pipeline() .collection("cities") .distinct("country") .execute(); cities = db.pipeline() .collection("cities") .distinct( field("state").toLower().alias("normalizedState"), field("country")) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field cities = client.pipeline().collection("cities").distinct("country").execute() cities = ( client.pipeline() .collection("cities") .distinct(Field.of("state").to_lower().as_("normalizedState"), "country") .execute() )
Java
Pipeline.Snapshot cities1 = firestore.pipeline().collection("cities").distinct("country").execute().get(); Pipeline.Snapshot cities2 = firestore .pipeline() .collection("cities") .distinct(toLower(field("state")).as("normalizedState"), field("country")) .execute() .get();
המשך
cities1, err := client.Pipeline().Collection("cities").Distinct(firestore.Fields("country")).Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } cities2, err := client.Pipeline().Collection("cities"). Distinct(firestore.Fields( firestore.ToLower(firestore.FieldOf("state")).As("normalizedState"), firestore.FieldOf("country"), )). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err }
התנהגות
השלב distinct(...) פועל באופן דומה לשלב aggregate(...) ללא קבוצות. מידע נוסף זמין במאמרים בנושא aggregate(...) וselect(...).
חיפוש ערכים ייחודיים בשדה
לדוגמה, כדי לקבל רשימה של כל המדינות באוסף הבא cities
Node.js
await db.collection("cities").doc("SF").set({name: "San Francisco", state: "CA", country: "USA"});
await db.collection("cities").doc("LA").set({name: "Los Angeles", state: "CA", country: "USA"});
await db.collection("cities").doc("NY").set({name: "New York", state: "NY", country: "USA"});
await db.collection("cities").doc("TOR").set({name: "Toronto", state: null, country: "Canada"});
await db.collection("cities").doc("MEX").set({name: "Mexico City", state: null, country: "Mexico"});
אפשר למצוא מדינות שונות באמצעות:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct("country")
.execute();
שיוצרת את התוצאה הבאה:
{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }
פלט ייחודי של ביטויים
אפשר גם למצוא את השילובים הייחודיים של כמה שדות, או ביטויים מורכבים יותר. לדוגמה:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
כדי לקבל:
{ country: "USA", normalized_state: "ca" }
{ country: "USA", normalized_state: "ny" }
{ country: "Canada", normalized_state: null }
{ country: "Mexico", normalized_state: null }
התנהגויות שקולות
ההתנהגות של השוואה בין ערכים שונים זהה לזו של השוואה בין ערכים זהים.
כלומר, ערכים שווים, למשל ערכים מספריים שווים מבחינה מתמטית, נחשבים לאותו ערך ייחודי, ללא קשר לסוגים המקוריים שלהם (מספרים שלמים של 32 ביט, מספרים שלמים של 64 ביט, מספרים עם נקודה עשרונית, מספרים עשרוניים וכו').
לדוגמה, באוסף numerics עם מסמכים שונים שמכילים ערכים של מספר שלם 1 עם 32 ביט, מספר שלם 1L עם 64 ביט ומספר נקודה צפה 1.0, הפונקציה distinct(...) תחזיר רק תוצאה אחת.foo
במקרים כאלה שבהם יש בערכת הנתונים ערכים שונים ששווים זה לזה, ערך הפלט של הקבוצה יכול להיות כל אחד מהערכים האלה.
בדוגמה הזו, הערך foo יכול להיות מוחזר כ-1, כ-1L או כ-1.0.
גם אם נראה שהבחירה היא דטרמיניסטית, לא כדאי להסתמך על ההתנהגות של בחירת ערך ספציפי.
שימוש בזיכרון
אופן ההפעלה של שלב distinct(...) תלוי באינדקסים הזמינים. אם האופטימיזציה של השאילתה לא בוחרת אינדקס מתאים, הפונקציה distinct(...) דורשת אחסון בזיכרון של כל הערכים השונים.
אם יש מספר גדול מאוד של ערכים ייחודיים, או ערכים גדולים מאוד (למשל, ערכים ייחודיים גדולים), יכול להיות שהשלב הזה ייגמר ב<b>אין זיכרון פנוי (OOM)</b>.
במקרים כאלה, כדאי להחיל מסננים כדי להגביל את מערך הנתונים שעליו מתבצעת הפעולה distinct(...), או ליצור אינדקסים כמומלץ כדי למנוע שימוש רב בזיכרון.
התכונה Query Explain תספק מידע על תוכנית ההפעלה של השאילתה ונתוני פרופילים שיעזרו לכם לבצע ניפוי באגים.