Visão geral de consultas com filtros de intervalo e desigualdade em vários campos
O Firestore oferece suporte ao uso de filtros de intervalo e desigualdade em vários campos em uma única consulta. Agora é possível ter condições de intervalo e desigualdade em vários campos e simplificar o desenvolvimento do seu aplicativo delegando a implementação da lógica pós-filtragem ao Firestore.
Filtros de intervalo e desigualdade em vários campos
A consulta a seguir retorna todos os usuários com idade maior que 35 e altura entre 60 e 70, usando filtros de intervalo de idade e altura.
Modular da Web versão 9
const q = query(
collection(db, "users"),
where('age', '>', 35),
where('height', '>', 60),
where('height', '<', 70)
);
Swift
let query = db.collection("users")
.whereField("age", isGreaterThan: 35)
.whereField("height", isGreaterThan: 60)
.whereField("height", isLessThan: 70)
Objective-C
FIRQuery *query =
[[[[self.db collectionWithPath:@"users"]
queryWhereField:@"age" isGreaterThan:@35]
queryWhereField:@"height" isGreaterThan:@60]
queryWhereField:@"height" isLessThan:@70];
Java para Android
Query query = db.collection("users")
.whereGreaterThan("age", 35)
.whereGreaterThan("height", 60)
.whereLessThan("height", 70);
Kotlin + KTX para Android
val query = db.collection("users")
.whereGreaterThan("age", 35)
.whereGreaterThan("height", 60)
.whereLessThan("height", 70)
Java
db.collection("users")
.whereGreaterThan("age", 35)
.whereGreaterThan("height", 60)
.whereLessThan("height", 70);
Node.js
db.collection("users")
.where('age', '>', 35),
.where('height', '>', 60),
.where('height', '<', 70)
Considerações de indexação
Antes de começar a executar suas 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 fazer isso, verifique se o índice está ordenado da esquerda para a direita, de modo que a consulta seja refinada em um conjunto de dados que impeça a verificação de entradas de índice irrelevantes.
Suponha que você queira pesquisar em uma coleção de funcionários e encontrar aqueles com salário superior a 100.000 e número de anos de experiência superior a 0. Com base no seu entendimento 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 econômica ordenaria salary
antes de experience
e teria esta aparência:
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 í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 atender às
restrições de igualdade e 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 a definição de um índice perfeito.
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 ordene os campos em ordem decrescente de seletividade
de restrição de consulta. Uma seletividade maior corresponde a um subconjunto menor de
documentos, enquanto uma seleção menor corresponde a um subconjunto maior de documentos. Certifique-se de selecionar campos de intervalo ou desigualdade com maior seletividade no início da ordenação do índice do que os campos com menor seletividade.
Para minimizar o número de documentos que o Firestore verifica e retorna pela rede, sempre ordene os campos na ordem decrescente de seletividade de restrição de consulta. Se o conjunto de resultados não estiver na ordem necessária e for esperado que ele seja pequeno, implemente a lógica do lado do cliente para reordená-lo de acordo com suas expectativas de ordenação.
Por exemplo, suponha que você queira pesquisar em uma coleção de funcionários para encontrar aqueles com salário superior a 100.000 e ordenar os resultados por ano de experiência do funcionário. Se você espera que apenas um pequeno número de funcionários tenha um salário acima de 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`
A adição de uma ordenação em experience
à consulta produz o mesmo conjunto
de documentos e evita a reordenação dos resultados nos clientes, mas a consulta pode
ler muito mais entradas de índice irrelevantes do que a consulta anterior. Isso ocorre porque
o Firestore sempre prefere um índice com um prefixo de campos de índice que corresponda à
cláusula de ordenação da consulta. Se experience
tiver sido adicionado à ordem por cláusula,
o Firestore selecionará o índice (experience [...], salary [...])
para calcular os resultados da consulta. Como não há outras restrições em
experience
, o Firestore lerá todas as entradas de índice da
coleção employees
antes de aplicar o filtro salary
para encontrar o conjunto de resultados
final. Isso significa que as entradas de índice que não atendem ao filtro salary
ainda são lidas, aumentando 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 na leitura de documentos e entradas de índice lidas.
Para informações detalhadas, consulte a página Preços.
Limitações
Além das limitações da 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 em campos de documento e apenas restrições
de igualdade na chave
(__name__)
do documento não têm suporte. - O Firestore limita o número de campos de intervalo ou desigualdade a 10. Isso evita que as consultas se tornem muito caras para serem executadas.
A seguir
- Saiba mais sobre a otimização das consultas.
- Saiba mais sobre como executar consultas simples e compostas.
- Entenda como o Firestore usa índices.