Restricciones en las consultas

En esta página, se abordan las restricciones para realizar consultas en Datastore de Google App Engine. En la siguiente lista, se presentan las restricciones comunes con las que te encontrarás cuando desarrolles para Datastore.

Se ignoran las entidades que carecen de una propiedad nombrada en la consulta

No es necesario que las entidades del mismo tipo tengan las mismas propiedades. Para poder devolverse como resultado de una consulta, una entidad debe poseer un valor (posiblemente nulo) para cada propiedad nombrada en los filtros de consulta y los órdenes de clasificación. De lo contrario, se omitirá la entidad de los índices usados para ejecutar la consulta y, en consecuencia, no se incluirá en los resultados de la consulta.

Filtrar propiedades sin índice no muestra resultados

Una consulta no puede hallar valores de propiedad que no están indexados y tampoco puede ordenar las propiedades. Consulta la página Índices de Datastore para obtener un análisis detallado sobre las propiedades no indexadas.

Los filtros de desigualdad se limitan a una propiedad como máximo

Para no tener que explorar el índice completo, el mecanismo de consulta confía en que todos los resultados potenciales de una consulta sean adyacentes entre sí en el índice. Para satisfacer esta limitación, una sola consulta no puede usar comparaciones de desigualdad (LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL, NOT_EQUAL) en más de una propiedad en todos sus filtros. Por ejemplo, la siguiente consulta es válida porque los dos filtros de desigualdad se aplican a la misma propiedad:

Filter birthYearMinFilter =
    new FilterPredicate("birthYear", FilterOperator.GREATER_THAN_OR_EQUAL, minBirthYear);

Filter birthYearMaxFilter =
    new FilterPredicate("birthYear", FilterOperator.LESS_THAN_OR_EQUAL, maxBirthYear);

Filter birthYearRangeFilter =
    CompositeFilterOperator.and(birthYearMinFilter, birthYearMaxFilter);

Query q = new Query("Person").setFilter(birthYearRangeFilter);

Sin embargo, esta consulta no es válida porque usa filtros de desigualdad en dos propiedades diferentes:

Filter birthYearMinFilter =
    new FilterPredicate("birthYear", FilterOperator.GREATER_THAN_OR_EQUAL, minBirthYear);

Filter heightMaxFilter =
    new FilterPredicate("height", FilterOperator.LESS_THAN_OR_EQUAL, maxHeight);

Filter invalidFilter = CompositeFilterOperator.and(birthYearMinFilter, heightMaxFilter);

Query q = new Query("Person").setFilter(invalidFilter);

Recuerda que una consulta puede combinar filtros de igualdad (EQUAL) para propiedades diferentes, junto con uno o más filtros de desigualdad en una sola propiedad. Por lo tanto, la siguiente consulta es válida:

Filter lastNameFilter = new FilterPredicate("lastName", FilterOperator.EQUAL, targetLastName);

Filter cityFilter = new FilterPredicate("city", FilterOperator.EQUAL, targetCity);

Filter birthYearMinFilter =
    new FilterPredicate("birthYear", FilterOperator.GREATER_THAN_OR_EQUAL, minBirthYear);

Filter birthYearMaxFilter =
    new FilterPredicate("birthYear", FilterOperator.LESS_THAN_OR_EQUAL, maxBirthYear);

Filter validFilter =
    CompositeFilterOperator.and(
        lastNameFilter, cityFilter, birthYearMinFilter, birthYearMaxFilter);

Query q = new Query("Person").setFilter(validFilter);

Cuando no se especifica un orden de clasificación, no se define el orden de los resultados de la consulta

Cuando una consulta no especifica un orden de clasificación, los resultados se muestran en el orden en que se recuperan. Este orden puede cambiar a medida que evolucione la implementación de Datastore (o si cambian los índices de una aplicación). Por lo tanto, si tu aplicación requiere que los resultados de la consulta estén en un orden en particular, asegúrate de especificar este orden de clasificación en la consulta.

Se ignoran los órdenes de clasificación en las propiedades con filtros de igualdad

Las consultas que incluyen un filtro de igualdad para una propiedad determinada ignoran cualquier orden de clasificación especificado para esa propiedad. Esta es una optimización simple que permite evitar el procesamiento innecesario de propiedades con valores únicos, ya que todos los resultados tienen el mismo valor para la propiedad y, por ende, no se necesita mayor clasificación. Sin embargo, las propiedades con valores múltiples pueden tener valores adicionales además del que coincide con el filtro de igualdad. Dado que este caso de uso es inusual y aplicar el orden de clasificación sería costoso y requeriría índices adicionales, el planificador de consultas del modo Datastore simplemente ignora el orden de clasificación, incluso en el caso de valores múltiples. Esto puede hacer que los resultados de la consulta se muestren en un orden diferente al que parece implicar el orden de clasificación.

Primero deben clasificarse las propiedades que se usan en los filtros de desigualdad

Para recuperar todos los resultados que coinciden con un filtro de desigualdad, una consulta analiza el índice hasta encontrar la primera fila que coincide con el filtro y, luego, explora hacia delante hasta que encuentra una fila que no coincide. Para que las filas consecutivas abarquen el conjunto completo de resultados, deben estar ordenadas por la propiedad que se usa en el filtro de desigualdad antes de cualquier otra propiedad. Por lo tanto, si una consulta especifica uno o más filtros de desigualdad junto con uno o más órdenes de clasificación, el primer orden de clasificación debe referirse a la misma propiedad nombrada en los filtros de desigualdad. La siguiente es una consulta válida:

Filter birthYearMinFilter =
    new FilterPredicate("birthYear", FilterOperator.GREATER_THAN_OR_EQUAL, minBirthYear);

Query q =
    new Query("Person")
        .setFilter(birthYearMinFilter)
        .addSort("birthYear", SortDirection.ASCENDING)
        .addSort("lastName", SortDirection.ASCENDING);

Esta consulta no es válida, ya que no ordena en función de la propiedad que se usa en el filtro de desigualdad:

Filter birthYearMinFilter =
    new FilterPredicate("birthYear", FilterOperator.GREATER_THAN_OR_EQUAL, minBirthYear);

// Not valid. Missing sort on birthYear.
Query q =
    new Query("Person")
        .setFilter(birthYearMinFilter)
        .addSort("lastName", SortDirection.ASCENDING);

Del mismo modo, esta consulta no es válida porque la propiedad que se usa en el filtro de desigualdad no es la primera que se usa para ordenar:

Filter birthYearMinFilter =
    new FilterPredicate("birthYear", FilterOperator.GREATER_THAN_OR_EQUAL, minBirthYear);

// Not valid. Sort on birthYear needs to be first.
Query q =
    new Query("Person")
        .setFilter(birthYearMinFilter)
        .addSort("lastName", SortDirection.ASCENDING)
        .addSort("birthYear", SortDirection.ASCENDING);

Las propiedades con múltiples valores pueden comportarse de maneras sorprendentes

Debido a la forma en que se indexan, las entidades con múltiples valores para la misma propiedad pueden interactuar con los filtros de consulta y los órdenes de clasificación de maneras inesperadas y sorprendentes.

Si una consulta tiene varios filtros de desigualdad para una propiedad determinada, una entidad coincidirá con la consulta solo si al menos uno de sus valores individuales para esa propiedad satisface todos los filtros. Por ejemplo, si una entidad del tipo Widget tiene los valores 12 para la propiedad x, no coincidirá con la consulta:

Query q =
    new Query("Widget")
        .setFilter(
            CompositeFilterOperator.and(
                new FilterPredicate("x", FilterOperator.GREATER_THAN, 1),
                new FilterPredicate("x", FilterOperator.LESS_THAN, 2)));

Cada uno de los valores x de la entidad cumple con la condición de uno de los filtros, pero ningún valor individual cumple con ambos. Esto no se aplica a los filtros de igualdad. Por ejemplo, la misma entidad cumple con la siguiente consulta:

Query q =
    new Query("Widget")
        .setFilter(
            CompositeFilterOperator.and(
                new FilterPredicate("x", FilterOperator.EQUAL, 1),
                new FilterPredicate("x", FilterOperator.EQUAL, 2)));

Sin embargo, ninguno de los valores x individuales de la entidad cumple con ambas condiciones del filtro.

El operador NOT_EQUAL funciona como una prueba “el valor es distinto de”. Observa la siguiente consulta:

Query q = new Query("Widget").setFilter(new FilterPredicate("x", FilterOperator.NOT_EQUAL, 1));

coincide con cualquier entidad Widget con un valor x distinto de 1.

En Java, también puedes usar una consulta como

Query q =
    new Query("Widget")
        .setFilter(
            CompositeFilterOperator.and(
                new FilterPredicate("x", FilterOperator.NOT_EQUAL, 1),
                new FilterPredicate("x", FilterOperator.NOT_EQUAL, 2)));

Esta consulta actúa como

x < 1 O (x > 1 Y x < 2) O x > 2

Por esta razón, una entidad Widget con x valores 1, 2 y 3 coincide, pero una con valores 12 no lo hace.

Del mismo modo, el orden de clasificación para las propiedades con valores múltiples es inusual. Debido a que estas propiedades aparecen una vez en el índice por cada valor único, el primer valor que se observa en el índice determina el orden de clasificación de una entidad:

  • Si los resultados de la consulta se ordenan de forma ascendente, se usará el valor más pequeño de la propiedad para la clasificación.
  • Si los resultados de la consulta se ordenan de forma descendente, se usará el valor más elevado para la clasificación.
  • Otros valores no afectan el orden de clasificación ni la cantidad de valores.

Esto tiene la consecuencia inusual de que la entidad con los valores de propiedad 19 antecede a una entidad con los valores 4567 en orden ascendente y descendente.

Las consultas dentro de las transacciones deben incluir filtros principales

Las transacciones de Datastore operan solo en entidades que pertenecen al mismo grupo de entidades (que descienden de un mismo principal). Para preservar esta restricción, todas las consultas realizadas dentro de una transacción deben incluir un filtro principal que especifique una entidad principal en el mismo grupo de entidades que las otras operaciones en la transacción.