Descrição
Descubra os valores distintos de um campo ou uma expressão das etapas anteriores.
Sintaxe
A etapa distinct tem uma sintaxe semelhante à de select. É preciso uma ou mais expressões selecionáveis para selecionar e encontrar valores distintos. Strings podem ser usadas quando a expressão é apenas uma referência de campo:
Node.js
const cities = await db.pipeline()
.collection('/cities')
.distinct("country")
.execute();
const cities = await db.pipeline()
.collection('/cities')
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
Exemplos de clientes
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();
Comportamento
Em termos de comportamentos de projeção, distinct é semelhante a select com remoção de duplicação. Portanto, qualquer expressão selecionável disponível para select também pode ser usada para distinct.
A etapa distinct funciona de maneira semelhante a uma etapa de agregação sem grupos.
Consulte também Estágio de agregação e Estágio de seleção.
Encontrar valores de campo distintos
Por exemplo, para receber uma lista de todos os países na seguinte coleção 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'});
Para encontrar países distintos, use:
Node.js
const cities = await db.pipeline()
.collection('/cities')
.distinct("country")
.execute();
que gera o seguinte resultado:
{country: "USA"}
{country: "Canada"}
{country: "Mexico"}
Saída distinta de expressões
Você também pode encontrar as combinações distintas de vários campos ou expressões mais complicadas. Exemplo:
Node.js
const cities = await db.pipeline()
.collection('/cities')
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
para ter:
{country: "USA", normalized_state: "ca"}
{country: "USA", normalized_state: "ny"}
{country: "Canada", normalized_state: null}
{country: "Mexico", normalized_state: null}
Comportamentos de equivalência
O comportamento de equivalência em valores distintos segue a mesma semântica das igualdades.
Isso significa que valores equivalentes, por exemplo, valores numéricos matematicamente equivalentes, independentemente dos tipos originais (número inteiro de 32 bits, número inteiro de 64 bits, números de ponto flutuante, números decimais etc.), são considerados o mesmo valor distinto.
Por exemplo, em uma coleção numerics com diferentes documentos que contêm valores foo de números inteiros de 32 bits 1, 64 bits 1L e ponto flutuante 1.0, respectivamente, distinct vai retornar apenas um resultado.
Nesses casos, em que há valores equivalentes diferentes no conjunto de dados, o valor de saída do grupo pode ser qualquer um desses valores equivalentes.
Neste exemplo, o valor de foo pode ser retornado como 1, 1L ou 1.0.
Mesmo que pareça determinista, não tente confiar no comportamento de um valor específico sendo selecionado.
Uso da memória
A execução da etapa distinct depende dos índices disponíveis. Quando não há um índice adequado escolhido pelo otimizador de consultas, distinct exige o buffer de todos os valores distintos na memória.
Se houver um número muito grande de valores distintos ou valores muito grandes (por exemplo, distintos em valores enormes), essa etapa poderá ficar sem memória.
Nesses casos, aplique filtros para limitar o conjunto de dados a ser usado em distinct ou crie índices conforme recomendado para evitar o uso excessivo de memória.
A explicação da consulta fornece informações sobre o plano de execução real da consulta e dados de criação de perfil para ajudar na depuração.