Distinct (fase di trasformazione)
Descrizione
Trova tutte le combinazioni di valori distinti per una serie di espressioni.
La fase distinct(...) ha una sintassi simile a select(...), in quanto accetta una o
più espressioni selezionabili. Le stringhe possono essere utilizzate quando l'espressione è solo un riferimento a un campo:
Esempi
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
Android
var cities = db.pipeline() .collection("cities") .distinct("country") .execute() cities = db.pipeline() .collection("cities") .distinct( field("state").toLower().alias("normalizedState"), field("country") ) .execute()
Java
Android
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();
Comportamento
La fase distinct(...) funziona in modo simile a una
aggregate(...) fase senza gruppi. Vedi anche
aggregate(...) e
select(...).
Trovare valori di campo distinti
Ad esempio, per ottenere un elenco di tutti i paesi nella seguente raccolta 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"});
I paesi distinti possono essere trovati utilizzando:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct("country")
.execute();
che genera il seguente risultato:
{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }
Output distinto delle espressioni
Puoi anche trovare le combinazioni distinte di più campi o espressioni più complicate. Ad esempio:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
per ottenere:
{ country: "USA", normalized_state: "ca" }
{ country: "USA", normalized_state: "ny" }
{ country: "Canada", normalized_state: null }
{ country: "Mexico", normalized_state: null }
Comportamenti di equivalenza
Il comportamento di equivalenza sui valori distinti segue la stessa semantica delle uguaglianze.
Ciò significa che i valori equivalenti, ad esempio i valori numerici matematicamente equivalenti, indipendentemente dai tipi originali (interi a 32 bit, interi a 64 bit, numeri in virgola mobile, numeri decimali e così via), sono considerati lo stesso valore distinto.
Ad esempio, in una raccolta numerics con documenti diversi contenenti
foo valori di interi a 32 bit 1, interi a 64 bit 1L e virgola mobile 1.0
rispettivamente, distinct(...) restituirà un solo risultato.
In questi casi di presenza di valori equivalenti diversi nel set di dati, il valore di output del gruppo può essere uno qualsiasi di questi valori equivalenti.
In questo esempio, questo valore di foo potrebbe essere restituito come 1, 1L o 1.0.
Anche se sembra deterministico, non devi tentare di fare affidamento sul comportamento di un valore specifico selezionato.
Utilizzo memoria
La modalità di esecuzione della fase distinct(...) dipende dagli indici disponibili. Quando l'ottimizzatore di query non sceglie un indice appropriato, distinct(...) richiede il buffering di tutti i valori distinti in memoria.
Nel caso in cui sia presente un numero molto elevato di valori distinti o valori molto grandi (ad es. distinti su valori enormi), questa fase potrebbe esaurire la memoria.
In questi casi, devi applicare filtri per limitare il set di dati su cui eseguire distinct(...) o creare indici come consigliato per evitare un utilizzo elevato della memoria.
Query Explain fornirà informazioni sul piano di esecuzione della query effettivo e sui dati di profilazione per facilitare il debug.