Consulta com filtros de intervalo e desigualdade na visão geral de vários campos
O Firestore oferece suporte ao uso de filtros de intervalo e desigualdade em vários campos em uma única consulta. É possível ter condições de intervalo e desigualdade em vários campos e simplificar o desenvolvimento de aplicativos delegando a implementação da lógica pós-filtragem para o Firestore.
Filtros de intervalo e desigualdade em vários campos
A consulta a seguir usa filtros de intervalo de população e densidade para retornar todas as cidades em que a população é maior que 1.000.000 e a densidade populacional é menor que 10.000 pessoas por unidade de área.
Modular versão 9 para a Web
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 indexação
Antes de executar as consultas, leia sobre consultas e o modelo de dados do Firestore.
No Firestore, a cláusula ORDER BY
de uma consulta determina quais índices
podem ser usados para exibir 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 isso, você deve garantir que seu índice seja ordenado da esquerda para a direita para que a consulta extraia um conjunto de dados que impede a verificação de entradas de índice irrelevantes.
Suponha que você queira pesquisar em um grupo de funcionários e encontrar funcionários dos Estados Unidos com salário superior a US$ 100.000 e número de anos de experiência maior do que zero. Com base em sua compreensão do conjunto de dados, você sabe que
a restrição salarial é 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
mais econômica pediria salary
antes de experience
e ficaria assim:
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 índices
Ao otimizar os índices, observe as seguintes práticas recomendadas.
Ordenar campos de índice por igualdades seguidas pelo intervalo mais seletivo ou campo de desigualdade
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 houver, no primeiro campo
da consulta orderBy()
. Essas restrições podem reduzir o número de entradas de índice
verificadas pelo Firestore. O Firestore usa os campos restantes
do índice para satisfazer outras restrições de intervalo ou desigualdade da consulta. Essas
restrições não reduzem o número de entradas de índice que o Firestore verifica,
mas filtram documentos sem correspondência para que o número de documentos
retornados aos clientes seja reduzido.
Para mais informações sobre como criar índices eficientes, consulte Propriedades de índice.
Ordenar campos em ordem decrescente de seletividade de restrição de consulta
Para garantir que o Firestore selecione o índice ideal para sua consulta,
especifique uma cláusula orderBy()
que ordena os campos em ordem decrescente de
seletividade de restrição. Maior seletividade corresponde a um subconjunto menor de
documentos, enquanto a menor seletividade corresponde a um subconjunto maior de documentos. Verifique se
você selecionou campos de intervalo ou desigualdade com maior seletividade no início do índice
do que campos com menor seletividade.
Para minimizar o número de documentos verificados e retornados pelo Firestore na rede, você sempre deve ordenar os campos na ordem decrescente de consulta de seletividade de restrição. Se o conjunto de resultados não estiver na ordem exigida e o resultado for pequeno, você pode implementar a lógica do lado do cliente para reordená-lo de acordo com sua expectativa de ordem.
Por exemplo, suponha que você queira pesquisar um conjunto de funcionários para encontrar funcionários dos Estados Unidos com salário superior a US$ 100.000 e ordenar os resultados pelo tempo de experiência do funcionário. Se você espera que apenas um pequeno número de funcionários tenha salários superiores a US$ 100.000, a maneira 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`
Adicionar uma ordenação em experience
à consulta produzirá o mesmo conjunto
de documentos e evita a reordenação dos resultados nos clientes, a consulta poderá
ler muito mais entradas de índice irrelevantes do que a consulta anterior. Isso acontece porque
o Firestore sempre prefere um índice cujo prefixo de campos de índice corresponda à
ordem por cláusula da consulta. Se experience
forem adicionados à ordem por uma cláusula,
o Firestore vai selecionar o índice (experience [...], salary [...])
para calcular os resultados da consulta. Como não há outras restrições em
experience
, o Firestore vai ler todas as entradas de índice da
coleção employees
antes de aplicar o filtro salary
para encontrar o resultado final
de conjunto de resultados. Isso significa que as entradas de índice que não atendem aos critérios salary
são lidos, aumentando assim 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 em documentos lidos e entradas de índice lidas.
Para informações detalhadas, consulte a página Preços.
Limitações
Além das limitações de consulta, observe as seguintes limitações antes de usar consultas com filtros de intervalo e desigualdade em vários campos:
- Consultas com filtros de intervalo ou desigualdade nos campos do documento e apenas restrições de igualdade na chave de documento no
(__name__)
não têm suporte. - O Firestore limita a 10 o número de campos de intervalo ou desigualdade. Isso é para evitar que as consultas fiquem muito caras para execução.
A seguir
- Saiba mais sobre como otimizar suas consultas.
- Saiba mais sobre como realizar consultas simples e compostas.
- Entenda como o Firestore usa índices.