Opis
Znajdź wszystkie różne kombinacje wartości dla serii wyrażeń.
Etap distinct(...) ma podobną składnię do etapu select(...), ponieważ przyjmuje co najmniej 1 wyrażenie, które można wybrać. Ciągów tekstowych można używać, gdy wyrażenie jest tylko odwołaniem do pola:
Przykłady
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 }
Zachowanie
Etap distinct(...) działa podobnie do etapu aggregate(...) bez grup. Zobacz też aggregate(...) i select(...).
Znajdowanie odrębnych wartości pól
Aby na przykład uzyskać listę wszystkich krajów w tej kolekcji: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"});
Poszczególne kraje można znaleźć za pomocą:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct("country")
.execute();
co daje ten wynik:
{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }
Różne dane wyjściowe wyrażeń
Możesz też znaleźć różne kombinacje wielu pól lub bardziej złożone wyrażenia. Przykład:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
aby uzyskać:
{ country: "USA", normalized_state: "ca" }
{ country: "USA", normalized_state: "ny" }
{ country: "Canada", normalized_state: null }
{ country: "Mexico", normalized_state: null }
Zachowania równoważne
Zachowanie równoważności w przypadku różnych wartości jest takie samo jak w przypadku równości.
Oznacza to, że równoważne wartości, np. matematycznie równoważne wartości numeryczne, niezależnie od pierwotnych typów (liczby całkowite 32-bitowe, liczby całkowite 64-bitowe, liczby zmiennoprzecinkowe, liczby dziesiętne itp.), są traktowane jako ta sama odrębna wartość.
Na przykład w kolekcji numerics z różnymi dokumentami zawierającymi wartości foo odpowiednio 32-bitowej liczby całkowitej 1, 64-bitowej liczby całkowitej 1L i liczby zmiennoprzecinkowej 1.0 funkcja distinct(...) zwróci tylko 1 wynik.
W takich przypadkach, gdy w zbiorze danych występują różne równoważne wartości, wartość wyjściowa grupy może być dowolną z nich.
W tym przykładzie wartość foo może zostać zwrócona jako 1, 1L lub 1.0.
Nawet jeśli wydaje się, że jest to deterministyczne, nie próbuj polegać na zachowaniu polegającym na wybraniu jednej konkretnej wartości.
Wykorzystanie pamięci
Sposób wykonania etapu distinct(...) zależy od dostępnych indeksów. Jeśli optymalizator zapytań nie wybierze odpowiedniego indeksu, funkcja distinct(...)
wymaga buforowania wszystkich odrębnych wartości w pamięci.
Jeśli masz bardzo dużą liczbę różnych wartości lub wartości są bardzo duże (np. różne wartości w przypadku bardzo dużych liczb), na tym etapie może zabraknąć pamięci.
W takich przypadkach należy zastosować filtry, aby ograniczyć zbiór danych, na którym ma być przeprowadzana operacja distinct(...), lub utworzyć indeksy zgodnie z zaleceniami, aby uniknąć dużego zużycia pamięci.
Funkcja Query Explain dostarczy informacji o rzeczywistym planie wykonywania zapytania i danych profilowania, które pomogą w debugowaniu.