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

Cloud Firestore admite el uso de filtros de rango y desigualdad en varios campos en una sola consulta. Ahora puedes tener condiciones de rango y desigualdad en varios campos y simplificar el desarrollo de tu aplicación delegando la implementación de la lógica de posfiltrado a Cloud Firestore.

Filtros de rango y desigualdad en varios campos

La siguiente consulta muestra todos los usuarios cuya edad es mayor que 35 y esta altura está entre 60 y 70 con filtros de rango de edad y altura.

Modular de la versión 9 de la 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)

Consideraciones de indexación

Antes de comenzar a ejecutar tus consultas, asegúrate de que leíste la información sobre las consultas y el modelo de datos de Cloud Firestore.

En Cloud Firestore, la cláusula ORDER BY de una consulta determina qué índices se pueden usar para entregarla. 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 Cloud 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 extraiga en un conjunto de datos que evite el análisis de entradas de índice irrelevantes.

Supongamos que deseas buscar en una colección de empleados y encontrar empleados cuyo salario es superior a 100,000 y cuya cantidad de años de experiencia es superior a 0. Según tu comprensión del conjunto de datos, sabes que la restricción de salario es más selectiva que la de experiencia. El índice ideal que reduciría la cantidad de análisis de índices sería (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 los índices

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

Ordenar los campos de índice según las igualdades seguidas del rango más selectivo o el campo de desigualdad

Cloud Firestore usa los campos que se encuentran más a la izquierda de un índice compuesto para satisfacer 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 Cloud Firestore analiza. Cloud 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 Cloud Firestore analiza, sino que filtran los documentos no coincidentes para reducir 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 las restricciones de consulta

Para asegurarte de que Cloud 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 menor selectividad coincide con un subconjunto más grande de documentos. Asegúrate de seleccionar campos de rango o desigualdad con mayor selectividad antes en el orden de índice que los campos con una selectividad más baja.

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

Por ejemplo, supongamos que deseas buscar en una colección de empleados para encontrar empleados cuyo salario es 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, 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 producirá 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 irrelevantes que la consulta anterior. Esto se debe a que Cloud Firestore siempre prefiere un índice cuyo prefijo de campos de índice coincida con la cláusula de orden por de la consulta. Si se agregaron experience a la cláusula order by, Cloud Firestore seleccionará el índice (experience [...], salary [...]) para calcular los resultados de las consultas. Dado que no hay otras restricciones en experience, Cloud 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 cumplen con 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 leídas.

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 campos del documento y solo restricciones de igualdad en la clave del documento (__name__).
  • Cloud Firestore limita la cantidad de campos de rango o desigualdad a 10. Esto es para evitar que las consultas sean demasiado costosas para ejecutarlas.

Pasos siguientes