Distinct (étape de transformation)

Description

Trouvez toutes les combinaisons distinctes de valeurs pour une série d'expressions.

L'étape distinct(...) a une syntaxe similaire à select(...), car elle accepte une ou plusieurs expressions sélectionnables. Les chaînes peuvent être utilisées lorsque l'expression n'est qu'une référence de champ :

Exemples

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();

Comportement

L'étape distinct(...) fonctionne de la même manière qu'une étape aggregate(...) sans groupes. Voir aussi aggregate(...) et select(...).

Trouver des valeurs de champ distinctes

Par exemple, pour obtenir la liste de tous les pays de la collection cities suivante :

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"});

Vous pouvez trouver les pays distincts à l'aide des méthodes suivantes :

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .distinct("country")
  .execute();

qui génère le résultat suivant :

{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }

Sortie distincte des expressions

Vous pouvez également trouver les combinaisons distinctes de plusieurs champs ou des expressions plus complexes. Exemple :

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .distinct(
    field("state").toLower().as("normalized_state"),
    field("country"))
  .execute();

pour obtenir :

{ country: "USA", normalized_state: "ca" }
{ country: "USA", normalized_state: "ny" }
{ country: "Canada", normalized_state: null }
{ country: "Mexico", normalized_state: null }

Comportements d'équivalence

Le comportement d'équivalence sur des valeurs distinctes suit la même sémantique que les égalités.

Cela signifie que les valeurs équivalentes, par exemple les valeurs numériques mathématiquement équivalentes, sont considérées comme la même valeur distincte, quels que soient les types d'origine (entiers 32 bits, entiers 64 bits, nombres à virgule flottante, nombres décimaux, etc.).

Par exemple, dans une collection numerics avec différents documents contenant des valeurs foo d'entier 32 bits 1, d'entier 64 bits 1L et de virgule flottante 1.0 respectivement, distinct(...) ne renverra qu'un seul résultat.

Dans ce cas, la valeur de sortie du groupe peut être n'importe laquelle de ces valeurs équivalentes. Dans cet exemple, cette valeur de foo peut être renvoyée sous la forme 1, 1L ou 1.0.

Même si cela semble déterministe, vous ne devez pas essayer de vous fier au comportement d'une valeur spécifique sélectionnée.

Utilisation de la mémoire

La façon dont l'étape distinct(...) est exécutée dépend des index disponibles. Lorsque l'optimiseur de requêtes ne choisit pas d'index approprié, distinct(...) nécessite de mettre en mémoire tampon toutes les valeurs distinctes.

Si le nombre de valeurs distinctes est très élevé ou si les valeurs sont très grandes (par exemple, distinctes sur des valeurs énormes), cette étape peut manquer de mémoire.

Dans ce cas, vous devez appliquer des filtres pour limiter l'ensemble de données sur lequel effectuer distinct(...) ou créer des index comme recommandé pour éviter une utilisation importante de la mémoire.

L'explication de la requête fournit des informations sur le plan d'exécution de la requête et des données de profilage pour faciliter le débogage.