Descripción general de consultas con filtros de rango y desigualdad en varios campos

Firestore admite el uso de filtros de rango y desigualdad en varios campos de una sola consulta. Ahora puedes tener condiciones de rango y desigualdad en varios campos y simplificar el desarrollo de tu aplicación mediante la delegación de la implementación de la lógica posterior al filtrado a Firestore.

Filtros de rango y desigualdad en varios campos

La siguiente consulta muestra todos los usuarios cuya edad es mayor que 35 y altura entre 60 y 70 años usando los filtros de rango de edad y altura.

Modular de la versión web 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];

Android de Java

 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)

Consideraciones sobre la indexación

Antes de comenzar a ejecutar consultas, asegúrate de leer sobre las consultas y el modelo de datos de Firestore.

En Firestore, la cláusula ORDER BY de una consulta determina qué índices se pueden usar para entregar la consulta. Por ejemplo, una consulta ORDER BY a ASC, b ASC requiere un índice compuesto en los campos a ASC, b ASC.

Para optimizar el rendimiento y el costo de las consultas de Firestore, debes optimizar el orden de los campos en el índice. Para ello, debes asegurarte de que tu índice esté ordenado de izquierda a derecha, de modo que la consulta se transfiera a un conjunto de datos que evite el análisis de entradas de índice irrelevantes.

Supongamos que deseas buscar en un grupo de empleados y encontrar aquellos cuyo salario sea superior a 100,000 y cuya cantidad de años de experiencia sea mayor que 0. Según tu comprensión del conjunto de datos, sabes que la restricción salarial es más selectiva que la restricción de experiencia. El índice ideal que reduciría la cantidad de análisis de índices sería el (salary [...], experience [...]). Por lo tanto, la consulta que sería rápida y rentable ordenaría salary antes que experience y se vería de la siguiente manera:

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ácticas recomendadas para optimizar índices

Cuando optimices índices, ten en cuenta las siguientes prácticas recomendadas.

Ordena los campos de índice por igualdades seguidas del rango más selectivo o el campo de desigualdad

Firestore usa los campos de la izquierda de un índice compuesto para cumplir con las restricciones de igualdad y la restricción de rango o desigualdad, si corresponde, en el primer campo de la consulta orderBy(). Estas restricciones pueden reducir la cantidad de entradas de índice que Firestore analiza. Firestore usa los campos restantes del índice para satisfacer otras restricciones de rango o desigualdad de la consulta. Estas restricciones no reducen la cantidad de entradas de índice que Firestore analiza, sino que filtran los documentos no coincidentes para que se reduzca la cantidad de documentos que se muestran a los clientes.

Para obtener más información sobre cómo crear índices eficientes, consulta la definición de un índice perfecto.

Ordena los campos en orden descendente de selectividad de la restricción de consulta

A fin de asegurarte de que Firestore seleccione el índice óptimo para tu consulta, especifica una cláusula orderBy() que ordene los campos en orden descendente de selectividad de la restricción de consulta. Una selectividad más alta coincide con un subconjunto más pequeño de documentos, mientras que una más baja coincide con un subconjunto más grande de documentos. Asegúrate de seleccionar campos de rango o de desigualdad con mayor selectividad antes en el orden de índice que campos con una selectividad más baja.

Para minimizar la cantidad de documentos que Firestore analiza y muestra en la red, siempre debes ordenar los campos en orden descendente de selectividad de la restricción de consulta. Si el conjunto de resultados no está en el orden requerido y se espera que el conjunto de resultados sea pequeño, puedes implementar la lógica del cliente para reordenarlo según tu expectativa de orden.

Por ejemplo, supongamos que deseas realizar una búsqueda en un grupo de empleados para encontrar aquellos cuyo salario sea superior a 100,000 y ordenar los resultados por año de experiencia del empleado. Si esperas que solo una pequeña cantidad de empleados tenga un salario superior a 100,000, entonces la forma más eficiente de escribir la consulta es la siguiente:

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`

Si bien agregar un orden en experience a la consulta generará el mismo conjunto de documentos y evitará el reordenamiento de los resultados en los clientes, la consulta puede leer muchas más entradas de índice extrañas que la consulta anterior. Esto se debe a que Firestore siempre prefiere un índice cuyo prefijo de campos de índice coincida con la cláusula ordenar por de la consulta. Si se agregó experience a la cláusula ordenar por, Firestore seleccionará el índice (experience [...], salary [...]) para calcular los resultados de las consultas. Debido a que no hay otras restricciones en experience, Firestore leerá todas las entradas de índice de la colección employees antes de aplicar el filtro salary para encontrar el conjunto de resultados final. Esto significa que las entradas de índice que no satisfacen el filtro salary se leen de todos modos, lo que aumenta la latencia y el costo de la consulta.

Precios

Las consultas con filtros de rango y desigualdad en varios campos se facturan según la lectura de documentos y las entradas de índice.

Para obtener información detallada, consulta la página de precios.

Limitaciones

Además de las limitaciones de las consultas, ten en cuenta las siguientes limitaciones antes de usar consultas con filtros de rango y desigualdad en varios campos:

  • No se admiten las consultas con filtros de rango o desigualdad en los campos de documentos y solo restricciones de igualdad en la clave del documento (__name__).
  • Firestore limita la cantidad de rangos o campos de desigualdad a 10. Esto sirve para evitar que las consultas sean demasiado costosas para ejecutarse.

Pasos siguientes