Restrições em consultas

Nesta página, apresentamos as restrições em consultas no Datastore pelo Google App Engine. Na lista a seguir, estão as restrições comuns que você encontrará durante o desenvolvimento para o Datastore.

Entidades que não têm uma propriedade nomeada na consulta são ignoradas

Entidades do mesmo tipo não precisam ter as mesmas propriedades. Para ser elegível como resultado de consulta, uma entidade deve ter um valor (que pode ser nulo) para cada propriedade nomeada nos filtros da consulta e ordens de classificação. Caso contrário, ela é omitida dos índices usados para executar a consulta e, consequentemente, não será incluída nos resultados.

Filtragens de propriedades não indexadas não retornam resultados

Uma consulta não pode localizar valores de propriedade que não estão indexados e nem classificar essas propriedades. Consulte a página Índices do Datastore para uma discussão detalhada das propriedades não indexadas.

Os filtros de desigualdade são limitados a no máximo uma propriedade

Para evitar que o mecanismo de consulta verifique todo o índice, é necessário que os possíveis resultados de uma consulta estejam adjacentes um ao outro no índice. Para satisfazer essa restrição, uma única consulta pode não usar comparações de desigualdade (LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL, NOT_EQUAL) em mais de uma propriedade em todos os filtros dela. Por exemplo, a consulta a seguir é válida porque os dois filtros de desigualdade se aplicam à mesma propriedade:

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);

No entanto, a consulta a seguir não é válida, porque usa filtros de desigualdade em duas propriedades 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);

Uma consulta pode combinar filtros de igualdade (EQUAL) em propriedades diferentes com um ou mais filtros de desigualdade em uma única propriedade. Portanto, a consulta a seguir é 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);

A ordenação dos resultados da consulta é indefinida quando nenhuma ordem de classificação é especificada

Quando uma consulta não especifica uma ordem de classificação, os resultados são retornados na ordem em que são recuperados. À medida que a implementação do Datastore evolui (ou se os índices de um aplicativo são alterados), essa ordem pode mudar. Portanto, se o aplicativo exige que os resultados de consulta estejam em uma determinada ordem, certifique-se de especificar explicitamente essa ordem de classificação na consulta.

Pedidos de classificação são ignorados em propriedades com filtros de igualdade

As consultas que incluem um filtro de igualdade para uma determinada propriedade ignoram qualquer ordem de classificação especificada para essa propriedade. Essa é uma otimização simples para evitar o processamento desnecessário de propriedades de valor único, já que todos os resultados têm o mesmo valor para a propriedade e, portanto, nenhuma classificação adicional é necessária. As propriedades de valores múltiplos, no entanto, podem ter valores adicionais além do correspondente ao filtro de igualdade. Como esse caso de uso é raro, e aplicar a ordem de classificação sai caro e exige índices adicionais, o planejador de consultas do Datastore simplesmente ignora a ordem de classificação mesmo no caso de valores múltiplos. Dessa forma, os resultados da consulta podem ser retornados em uma ordem diferente daquela que a ordem de classificação parece indicar.

Propriedades utilizadas em filtros de desigualdade devem ser classificadas primeiro

Para recuperar todos os resultados que correspondem a um filtro de desigualdade, uma consulta verifica o índice da primeira linha correspondente ao filtro e, em seguida, segue verificando até encontrar uma linha não correspondente. Para que as linhas consecutivas incluam todo o conjunto de resultados, elas precisam ser ordenadas pela propriedade usada no filtro de desigualdade antes de qualquer outra. Assim, se uma consulta especifica um ou mais filtros de desigualdade com uma ou mais ordens de classificação, a primeira ordem de classificação precisa se referir à mesma propriedade nomeada nos filtros de desigualdade. Veja a seguir uma 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);

A consulta a seguir não é válida, porque não classifica a propriedade usada no filtro de desigualdade:

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);

Da mesma forma, a consulta a seguir não é válida porque a propriedade usada no filtro de desigualdade não é a primeira classificada:

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);

Propriedades com vários valores podem se comportar de maneiras inesperadas

Devido à maneira como elas são indexadas, entidades com vários valores para a mesma propriedade às vezes podem interagir com filtros de consulta e ordens de classificação de maneiras inesperadas.

Se uma consulta tiver vários filtros de desigualdade para determinada propriedade, uma entidade só corresponderá à consulta se pelo menos um dos valores individuais dela satisfizer a todos os filtros. Por exemplo, se uma entidade do tipo Widget tiver os valores 1 e 2 para a propriedade x, ela não corresponderá à consulta:

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

Cada um dos valores de x da entidade satisfaz a um dos filtros, mas nenhum dos dois valores satisfaz aos dois. Observe que isso não se aplica a filtros de igualdade. Por exemplo, a mesma entidade satisfará a consulta

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

mesmo que nenhum dos valores de x individuais da entidade satisfaça às duas condições de filtro.

O operador NOT_EQUAL funciona como um teste de "valor diferente de". Então, por exemplo, a consulta

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

combina qualquer entidade Widget com um valor x diferente de 1.

Em Java, você também pode usar uma consulta como

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

que age como

x < 1 OR (x > 1 AND x < 2) OR x > 2

então, uma entidade Widget com valoresx de 1, 2 e 3 gera correspondência, mas uma com valores 1 e 2 não.

Da mesma maneira, a ordem de classificação para propriedades de múltiplos valores é incomum. Como essas propriedades aparecem uma vez no índice para cada valor exclusivo, o primeiro valor exibido no índice determina a ordem de classificação de uma entidade:

  • Se os resultados da consulta forem ordenados em ordem crescente, o menor valor da propriedade é usado para ordenação.
  • Se os resultados forem classificados por ordem decrescente, o maior valor é usado para ordenação.
  • Outros valores não afetam a ordem de classificação, nem o número de valores.

A consequência incomum disso é que uma entidade com valores de propriedade 1 e 9 precede outra entidade com valores 4, 5, 6 e 7 na ordem crescente e decrescente.

Consultas dentro de transações precisam incluir filtros de ancestral

As transações do Datastore operam somente em entidades que pertencem ao mesmo grupo, ou seja, originadas de um ancestral comum. Para preservar essa restrição, todas as consultas executadas em uma transação precisam incluir um filtro ancestral que especifique um ancestral no mesmo grupo de entidades que as outras operações.