Consulta com filtros de intervalo e desigualdade na visão geral de vários campos

O Firestore é compatível com o 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 versão 9 para a Web

  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 sobre indexação

Antes de começar a 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 disponibilizar 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, garanta que o índice seja ordenado da esquerda para a direita, de modo que a consulta seja destilada para um conjunto de dados que impede a verificação de entradas de índice externas.

Suponha que você queira pesquisar em um conjunto de funcionários e encontrar funcionários com salário maior que 100.000 e número de anos de experiência maior que 0. Com base no seu entendimento do conjunto de dados, você sabe que a restrição salarial é mais seletiva que a restrição de experiência. O índice ideal para reduzir o número de verificações de índice é (salary [...], experience [...]). Assim, a consulta que seria rápida e econômica pediria salary antes de experience e seria 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 que o Firestore verifica. 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. Maior seletividade corresponde a um subconjunto menor de documentos, enquanto menor seletividade corresponde a um subconjunto maior de documentos. Selecione 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 na rede, sempre organize os campos em 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, é possível implementar a lógica do lado do cliente para reordená-lo conforme sua expectativa de ordenação.

Por exemplo, suponha que você queira pesquisar em um conjunto 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 terá um salário superior a 100.000, a maneira mais eficiente de escrever a consulta é esta:

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 adicionar 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 muito mais entradas de índice irrelevantes do que a consulta anterior. Isso ocorre porque o Firestore sempre prefere um índice com campos de índice que correspondam à ordem por cláusula da consulta. Se experience forem adicionados à 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 vai 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 nos documentos lidos e nas 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:

  • Não há suporte para consultas com filtros de intervalo ou desigualdade em campos de documentos e apenas restrições de igualdade na chave de documento (__name__).
  • O Firestore limita a 10 o número de campos de intervalo ou desigualdade. Isso evita que as consultas se tornem muito caras para serem executadas.

A seguir