Beschreibung
Alle eindeutigen Kombinationen von Werten für eine Reihe von Ausdrücken ermitteln.
Die distinct(...)-Phase hat eine ähnliche Syntax wie select(...), da sie einen oder mehrere auswählbare Ausdrücke akzeptiert. Strings können verwendet werden, wenn der Ausdruck nur ein Feldverweis 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();
Verhalten
Die Phase distinct(...) funktioniert ähnlich wie eine aggregate(...)-Phase ohne Gruppen. Siehe auch aggregate(...) und select(...).
Eindeutige Feldwerte finden
Wenn Sie beispielsweise eine Liste aller Länder in der folgenden cities-Sammlung 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"});
So finden Sie verschiedene Länder:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct("country")
.execute();
Dadurch wird das folgende Ergebnis generiert:
{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }
Unterschiedliche Ausgabe von Ausdrücken
Sie können auch die eindeutigen Kombinationen mehrerer Felder oder komplexere Ausdrücke ermitteln. Beispiel:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
Sie erhalten:
{ country: "USA", normalized_state: "ca" }
{ country: "USA", normalized_state: "ny" }
{ country: "Canada", normalized_state: null }
{ country: "Mexico", normalized_state: null }
Verhaltensweisen der Äquivalenz
Das Äquivalenzverhalten bei unterschiedlichen 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.
Beispiel: In einer Sammlung numerics mit verschiedenen Dokumenten, die foo-Werte vom Typ 32-Bit-Ganzzahl 1, 64-Bit-Ganzzahl 1L und Gleitkommazahl 1.0 enthalten, gibt distinct(...) nur ein Ergebnis zurück.
Wenn im Dataset unterschiedliche äquivalente Werte vorhanden sind, kann der Ausgabewert der Gruppe beliebiger dieser äquivalenten Werte sein.
In diesem Beispiel könnte dieser Wert von foo als 1, 1L oder 1.0 zurückgegeben werden.
Auch wenn es deterministisch erscheint, sollten Sie nicht versuchen, sich auf das Verhalten zu verlassen, dass ein bestimmter Wert ausgewählt wird.
Arbeitsspeichernutzung
Wie die distinct(...)-Phase ausgeführt wird, hängt von den verfügbaren Indexen ab. Wenn der Abfrageoptimierer keinen geeigneten Index auswählt, müssen für distinct(...) alle eindeutigen Werte im Arbeitsspeicher gepuffert werden.
Wenn eine sehr große Anzahl von eindeutigen Werten oder sehr große Werte vorhanden sind (z.B. eindeutige riesige Werte), kann es in dieser Phase zu einem Speichermangel kommen.
In solchen Fällen sollten Sie Filter anwenden, um den Datensatz einzugrenzen, für den distinct(...) ausgeführt werden soll, oder Indexe wie empfohlen erstellen, um eine hohe Speicherauslastung zu vermeiden.
Query Explain liefert Informationen zum tatsächlichen Abfrageausführungsplan und Profiling-Daten, die beim Debuggen helfen.