Consultar com filtros de intervalo e desigualdade em vários campos: vista geral
O Firestore suporta a utilização de filtros de intervalo e de desigualdade em vários campos numa única consulta. Pode ter condições de intervalo e desigualdade em vários campos e simplificar o desenvolvimento de aplicações delegando a implementação da lógica de pós-filtragem no Firestore.
Filtros de intervalo e desigualdade em vários campos
A seguinte consulta usa filtros de intervalo na população e na densidade para devolver todas as cidades onde a população é superior a 1 000 000 de pessoas e a densidade populacional é inferior a 10 000 pessoas por unidade de área.
Versão Web 9 modular
const q = query(
collection(db, "cities"),
where('population', '>', 1000000),
where('density', '<', 10000),
);
Swift
let query = db.collection("cities")
.whereField("population", isGreaterThan: 1000000)
.whereField("density", isLessThan: 10000)
Objective-C
FIRQuery *query =
[[[[self.db collectionWithPath:@"cities"]
queryWhereField:@"population" isGreaterThan:@1000000]
queryWhereField:@"density" isLessThan:@10000];
Java Android
Query query = db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000);
Kotlin+KTX Android
val query = db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000)
Go
query := client.Collection("cities").
Where("population", ">", 1000000).
Where("density", "<", 10000)
Java
db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000);
Node.js
db.collection("cities")
.where('population', '>', 1000000),
.where('density', '<', 10000)
Python
from google.cloud import firestore
db = firestore.Client()
query = db.collection("cities")
.where("population", ">", 1000000)
.where("density", "<", 10000)
PHP
C#
Ruby
query = cities_ref.where("population", ">", "1000000")
.where("density", "<", 10000)
C++
CollectionReference cities_ref = db->Collection("cities");
Query query = cities_ref.WhereGreaterThan("population", FieldValue::Integer(1000000))
.WhereLessThan("density", FieldValue::Integer(10000));
Unity
CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef.WhereGreaterThan("population", 1000000)
.WhereLessThan("density", 10000);
Dart
final citiesRef = FirebaseFirestore.instance.collection('cities')
final query = citiesRef.where("population", isGreaterThan: 1000000)
.where("density", isLessThan: 10000);
Considerações sobre a indexação
Antes de executar as consultas, leia acerca das consultas e do modelo de dados do Firestore.
No Firestore, a cláusula ORDER BY de uma consulta determina que índices podem ser usados para publicar a consulta. Por exemplo, uma consulta ORDER BY a ASC, b ASC requer um índice composto nos campos a ASC, b ASC.
Para otimizar o desempenho e o custo das consultas do Firestore, otimize a ordem dos campos no índice. Para o fazer, certifique-se de que o índice está ordenado da esquerda para a direita de modo que a consulta destile para um conjunto de dados que impeça a análise de entradas de índice desnecessárias.
Suponhamos que quer pesquisar numa coleção de funcionários e encontrar funcionários dos Estados Unidos cujo salário seja superior a 100 000 € e cujo número de anos de experiência seja superior a 0. Com base na sua compreensão do conjunto de dados, sabe que a restrição de salário é mais seletiva do que a restrição de experiência. O índice ideal que reduziria o número de verificações de índice seria o (salary [...], experience [...]). Assim, a consulta que seria rápida e
rentável ordenaria salary antes de experience e teria o seguinte aspeto:
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.whereGreaterThan("experience", 0)
.orderBy("salary")
.orderBy("experience");
Node.js
db.collection("employees")
.where("salary", ">", 100000)
.where("experience", ">", 0)
.orderBy("salary")
.orderBy("experience");
Python
db.collection("employees")
.where("salary", ">", 100000)
.where("experience", ">", 0)
.order_by("salary")
.order_by("experience");
Práticas recomendadas para otimizar os índices
Quando otimizar os índices, tenha em atenção as seguintes práticas recomendadas.
Ordene os campos de índice por igualdades, seguidos do campo de intervalo ou desigualdade mais seletivo
O Firestore usa os campos mais à esquerda de um índice composto para satisfazer as restrições de igualdade e a restrição de intervalo ou desigualdade, se existir, no primeiro campo da consulta orderBy(). Estas restrições podem reduzir o número de entradas de índice que o Firestore analisa. O Firestore usa os campos restantes do índice para satisfazer outras restrições de intervalo ou desigualdade da consulta. Estas restrições não reduzem o número de entradas de índice que o Firestore analisa, mas filtram os documentos que não correspondem, para que o número de documentos devolvidos aos clientes seja reduzido.
Para mais informações sobre como criar índices eficientes, consulte as propriedades de índice.
Ordene os campos por ordem decrescente de seletividade da restrição de consulta
Para garantir que o Firestore seleciona o índice ideal para a sua consulta,
especifique uma cláusula orderBy() que ordene os campos por ordem decrescente de seletividade da restrição de consulta. Uma seletividade mais elevada corresponde a um subconjunto mais pequeno de documentos, enquanto uma seletividade mais baixa corresponde a um subconjunto maior de documentos. Certifique-se de que seleciona campos de intervalo ou de desigualdade com maior seletividade mais cedo na ordenação do índice do que os campos com menor seletividade.
Para minimizar o número de documentos que o Firestore analisa e devolve através da rede, deve ordenar sempre os campos por ordem decrescente da seletividade da restrição da consulta. Se o conjunto de resultados não estiver na ordem necessária e o conjunto de resultados for pequeno, pode implementar uma lógica do lado do cliente para reordená-lo de acordo com a sua expetativa de ordenação.
Por exemplo, suponha que quer pesquisar numa coleção de funcionários para encontrar funcionários dos Estados Unidos cujo salário seja superior a 100 000 $e ordenar os resultados pelo ano de experiência do funcionário. Se esperar que apenas um pequeno número de funcionários tenha salários superiores a 100 000 USD, a forma mais eficiente de escrever a consulta é a seguinte:
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.orderBy("salary")
.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
// Order results by `experience`
}
});;
Node.js
const querySnapshot = await db.collection('employees')
.where("salary", ">", 100000)
.orderBy("salary")
.get();
// Order results by `experience`
Python
results = db.collection("employees")
.where("salary", ">", 100000)
.order_by("salary")
.stream()
// Order results by `experience`
Embora a adição de uma ordenação em experience à consulta produza o mesmo conjunto de documentos e evite a reordenação dos resultados nos clientes, a consulta pode ler muitas mais entradas de índice estranhas do que a consulta anterior. Isto acontece porque o Firestore prefere sempre um índice cujos campos de índice correspondam ao prefixo da cláusula order by da consulta. Se experience tiver sido adicionado à cláusula ORDER BY, o Firestore seleciona o índice (experience [...], salary [...]) para calcular os resultados da consulta. Uma vez que não existem outras restrições em experience, o Firestore lê todas as entradas de índice da coleção employees antes de aplicar o filtro salary para encontrar o conjunto de resultados final. Isto significa que as entradas de índice que não satisfazem o filtro salary
são lidas na mesma, o que aumenta a latência e o custo da consulta.
Preços
As consultas com filtros de intervalo e desigualdade em vários campos são faturadas com base nos documentos lidos e nas entradas de índice lidas.
Para obter informações detalhadas, consulte a página Preços.
Limitações
Além das limitações de consultas, tenha em atenção as seguintes limitações antes de usar consultas com filtros de intervalo e desigualdade em vários campos:
- As consultas com filtros de intervalo ou de desigualdade em campos de documentos e apenas restrições de igualdade na chave do documento
(__name__)não são suportadas. - O Firestore limita o número de campos de intervalo ou de desigualdade a 10. Isto serve para evitar que as consultas se tornem demasiado caras para executar.
O que se segue?
- Saiba como otimizar as suas consultas.
- Saiba mais sobre como fazer consultas simples e compostas.
- Compreenda como o Firestore usa os índices.