Opis
Znajdź wszystkie unikalne kombinacje wartości dla serii wyrażeń.
Etap distinct(...) ma podobną składnię jak select(...), ponieważ przyjmuje co najmniej 1
wyrażenie, które można wybrać. Ciągi znaków można stosować, 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();
Zachowanie
Etap distinct(...) działa podobnie do etapu
aggregate(...) bez grup. Zobacz też
aggregate(...) i
select(...).
Znajdowanie unikalnych wartości pól
Aby na przykład uzyskać listę wszystkich krajów w 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"});
Unikalne kraje można znaleźć za pomocą:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct("country")
.execute();
co generuje ten wynik:
{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }
Unikalne dane wyjściowe wyrażeń
Możesz też znaleźć unikalne kombinacje wielu pól lub bardziej złożonych wyrażeń. 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żności
Zachowanie równoważności w przypadku unikalnych wartości jest zgodne z semantyką równości.
Oznacza to, że równoważne wartości, np. równoważne matematycznie wartości liczbowe, niezależnie od oryginalnych typów (liczba całkowita 32-bitowa, liczba całkowita 64-bitowa, liczby zmiennoprzecinkowe, liczby dziesiętne itp.), są traktowane jako ta sama unikalna wartość.
Na przykład w kolekcji numerics z różnymi dokumentami zawierającymi
foo wartości liczby całkowitej 32-bitowej 1, liczby całkowitej 64-bitowej 1L i liczby zmiennoprzecinkowej 1.0
odpowiednio, 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 tych równoważnych wartości.
W tym przykładzie wartość foo może zostać zwrócona jako 1, 1L lub 1.0.
Nawet jeśli wydaje się to deterministyczne, nie należy polegać na zachowaniu polegającym na wybraniu jednej konkretnej wartości.
Wykorzystanie pamięci
Sposób wykonywania etapu distinct(...) zależy od dostępnych indeksów. Gdy optymalizator zapytań nie wybierze odpowiedniego indeksu, distinct(...) wymaga buforowania wszystkich unikalnych wartości w pamięci.
W przypadku bardzo dużej liczby unikalnych wartości lub bardzo dużych wartości (np. unikalnych wartości) ten etap może spowodować wyczerpanie pamięci.
W takich przypadkach należy zastosować filtry, aby ograniczyć zbiór danych, na którym ma być wykonywana funkcja distinct(...), lub utworzyć indeksy zgodnie z zaleceniami, aby uniknąć dużego zużycia pamięci.
Funkcja Query Explain zawiera informacje o rzeczywistym planie wykonania zapytania i dane profilowania, które pomagają w debugowaniu.