Beschreibung
Alle eindeutigen Kombinationen von Werten für eine Reihe von Ausdrücken finden.
Die Phase distinct(...) hat eine ähnliche Syntax wie select(...), da sie einen oder
mehr auswählbare Ausdrücke akzeptiert. Strings können verwendet werden, wenn der Ausdruck nur eine Feldreferenz ist:
Beispiele
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();
Go
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 }
Verhalten
Die distinct(...) Phase funktioniert ähnlich wie eine
aggregate(...) Phase ohne Gruppen. Weitere Informationen finden Sie unter
aggregate(...) und
select(...).
Eindeutige Feldwerte finden
Wenn Sie beispielsweise eine Liste aller Länder in der folgenden cities-Collection abrufen möchten:
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"});
Eindeutige Länder können mit folgender Abfrage gefunden werden:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct("country")
.execute();
Dadurch wird das folgende Ergebnis generiert:
{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }
Eindeutige Ausgabe von Ausdrücken
Sie können auch die eindeutigen Kombinationen mehrerer Felder oder komplizierterer Ausdrücke finden. Beispiel:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
Ergebnis:
{ country: "USA", normalized_state: "ca" }
{ country: "USA", normalized_state: "ny" }
{ country: "Canada", normalized_state: null }
{ country: "Mexico", normalized_state: null }
Verhalten bei Äquivalenz
Das Verhalten bei der Äquivalenz von eindeutigen Werten folgt derselben Semantik wie Gleichheitsvergleiche.
Das bedeutet, dass äquivalente Werte, z. B. mathematisch äquivalente numerische Werte, unabhängig von den ursprünglichen Typen (32-Bit-Ganzzahl, 64-Bit-Ganzzahl, Gleitkommazahlen, Dezimalzahlen usw.) als derselbe eindeutige Wert betrachtet werden.
In einer Collection numerics mit verschiedenen Dokumenten, die
foo Werte vom Typ 32-Bit-Ganzzahl 1, 64-Bit-Ganzzahl 1L und Gleitkommazahl 1.0
enthalten, gibt distinct(...) beispielsweise nur ein Ergebnis zurück.
In solchen Fällen, in denen verschiedene äquivalente Werte im Dataset vorhanden sind, kann der Ausgabewert der Gruppe jeder dieser äquivalenten Werte sein.
In diesem Beispiel kann der Wert von foo als 1, 1L oder 1.0 zurückgegeben werden.
Auch wenn es deterministisch erscheint, sollten Sie sich nicht darauf verlassen, dass ein bestimmter Wert ausgewählt wird.
Arbeitsspeichernutzung
Wie die Phase distinct(...) ausgeführt wird, hängt von den verfügbaren Indexen ab. Wenn der Abfrageoptimierer keinen geeigneten Index auswählt, müssen bei distinct(...) alle eindeutigen Werte im Arbeitsspeicher gepuffert werden.
Wenn eine sehr große Anzahl eindeutiger Werte vorhanden ist oder die Werte sehr groß sind (z.B. eindeutige Werte für sehr große Werte), kann für diese Phase ein Out of Memory-Fehler auftreten.
In solchen Fällen sollten Sie Filter anwenden, um das Dataset zu beschränken, auf das distinct(...) angewendet wird, oder Indexe wie empfohlen erstellen, um eine hohe Arbeitsspeichernutzung zu vermeiden.
Mit Query Explain erhalten Sie Informationen zum tatsächlichen Abfrageausführungsplan und Profiling-Daten, die bei der Fehlerbehebung helfen können.