Consultas de projeção

Na maioria das consultas do Cloud Datastore, entidades inteiras são retornadas como resultados, mas, normalmente, apenas algumas propriedades delas são relevantes para o aplicativo. As consultas de projeção permitem consultar o Cloud Datastore somente para aquelas propriedades específicas de uma entidade da qual você realmente precisa, a uma latência e a um custo menores do que se a recuperasse inteira.

As consultas de projeção são semelhantes às do SQL do formulário:

SELECT name, email, phone FROM CUSTOMER

É possível usar todos os recursos de filtragem e classificação disponíveis para consultas de entidade padrão, sujeitos às limitações descritas abaixo. A consulta retorna um resumo dos resultados, apenas com as propriedades especificadas, name, email e phone no exemplo, preenchidas com valores. As demais propriedades não têm dados.

Como usar consultas de projeção no Java 8

Para gerar uma consulta de projeção, é preciso criar um objeto Query e adicionar propriedades a ele usando o método addProjection():

Java 8

private void addGuestbookProjections(Query query) {
  query.addProjection(new PropertyProjection("content", String.class));
  query.addProjection(new PropertyProjection("date", Date.class));
}

Java 7

private void addGuestbookProjections(Query query) {
  query.addProjection(new PropertyProjection("content", String.class));
  query.addProjection(new PropertyProjection("date", Date.class));
}

O tipo especificado para cada propriedade precisa corresponder àquele usado quando você definiu a propriedade com Entity.setProperty() pela primeira vez. O exemplo a seguir mostra como processar os resultados da consulta iterando a lista de entidades retornadas e fazendo o cast de todos os valores de propriedade para o tipo esperado:

Java 8

private void printGuestbookEntries(DatastoreService datastore, Query query, PrintWriter out) {
  List<Entity> guests = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(5));
  for (Entity guest : guests) {
    String content = (String) guest.getProperty("content");
    Date stamp = (Date) guest.getProperty("date");
    out.printf("Message %s posted on %s.\n", content, stamp.toString());
  }
}

Java 7

private void printGuestbookEntries(DatastoreService datastore, Query query, PrintWriter out) {
  List<Entity> guests = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(5));
  for (Entity guest : guests) {
    String content = (String) guest.getProperty("content");
    Date stamp = (Date) guest.getProperty("date");
    out.printf("Message %s posted on %s.\n", content, stamp.toString());
  }
}

Agrupamento (experimental)

Nas consultas de projeção, é possível usar o método setDistinct() para garantir que somente resultados totalmente exclusivos sejam retornados em um conjunto de resultados. Isso retornará apenas o primeiro resultado de entidades com os mesmos valores das propriedades projetadas.

Java 8

Query q = new Query("TestKind");
q.addProjection(new PropertyProjection("A", String.class));
q.addProjection(new PropertyProjection("B", Long.class));
q.setDistinct(true);
q.setFilter(Query.FilterOperator.LESS_THAN.of("B", 1L));
q.addSort("B", Query.SortDirection.DESCENDING);
q.addSort("A");

Java 7

Query q = new Query("TestKind");
q.addProjection(new PropertyProjection("A", String.class));
q.addProjection(new PropertyProjection("B", Long.class));
q.setDistinct(true);
q.setFilter(Query.FilterOperator.LESS_THAN.of("B", 1L));
q.addSort("B", Query.SortDirection.DESCENDING);
q.addSort("A");

Limitações nas projeções

As consultas de projeção estão sujeitas às seguintes limitações:

  • Somente propriedades indexadas podem ser projetadas.

    A projeção não é compatível com propriedades não indexadas, seja de maneira explícita ou implícita. Strings de texto longas (Text) e strings de bytes longas (Blob) não são indexadas.

  • A mesma propriedade não pode ser projetada mais de uma vez.

  • As propriedades referenciadas em um filtro de igualdade (EQUAL) ou de assinatura (IN) não podem ser projetadas.

    Por exemplo,

    SELECT A FROM kind WHERE B = 1
    

    é uma consulta válida (a propriedade projetada não é usada no filtro de igualdade), assim como a consulta

    SELECT A FROM kind WHERE A > 1
    

    (não é um filtro de igualdade), mas

    SELECT A FROM kind WHERE A = 1
    

    (a propriedade projetada é usada no filtro de igualdade) não é.

  • Os resultados mostrados em uma consulta de projeção não devem ser salvos no Cloud Datastore.

    Como a consulta retorna resultados apenas parcialmente preenchidos, você não precisa regravá-los no Cloud Datastore.

Projeções e propriedades com vários valores

A projeção de uma propriedade com vários valores não preencherá todos os valores dessa propriedade. Em vez disso, uma entidade separada será retornada para cada combinação exclusiva de valores projetados correspondentes à consulta. Por exemplo, suponhamos que você tenha uma entidade do tipo Foo com duas propriedades de vários valores, A e B:

entity = Foo(A=[1, 1, 2, 3], B=['x', 'y', 'x'])

Neste caso, a consulta de projeção

SELECT A, B FROM Foo WHERE A < 3

retornará quatro entidades com as seguintes combinações de valores:

A = 1, B = 'x'
A = 1, B = 'y'
A = 2, B = 'x'
A = 2, B = 'y'

Observe que, se uma entidade tiver uma propriedade de vários valores sem valores, nenhuma entrada será incluída no índice, e nenhum resultado para essa entidade será retornado de uma consulta de projeção, incluindo essa propriedade.

Índices de projeções

As consultas de projeção exigem a inclusão de todas as propriedades especificadas na projeção em um índice do Cloud Datastore. O servidor de desenvolvimento do App Engine gera automaticamente os índices necessários para você no arquivo de configuração do índice, datastore-indexes-auto.xml, enviado com o aplicativo.

Uma maneira de reduzir o número de índices obrigatórios é projetar as mesmas propriedades de maneira consistente, mesmo quando nem todas são necessárias. Por exemplo, essas consultas exigem dois índices separados:

SELECT A, B FROM Kind
SELECT A, B, C FROM Kind

No entanto, se você projetar sempre as propriedades A, B e C, mesmo se C não for obrigatória, apenas um índice será necessário.

A conversão de uma consulta em uma projeção talvez exija a criação de um novo índice caso as propriedades dessa projeção não estejam em outra parte da consulta. Por exemplo, suponhamos que você tenha uma consulta como:

SELECT * FROM Kind WHERE A > 1 ORDER BY A, B

que exija o índice

Index(Kind, A, B)

Convertendo-a em uma das consultas de projeção

SELECT C FROM Kind WHERE A > 1 ORDER BY A, B
SELECT A, B, C FROM Kind WHERE A > 1 ORDER BY A, B

apresenta uma nova propriedade (C) e, portanto, exigirá a criação de um novo índice Index(Kind, A, B, C). A consulta de projeção

SELECT A, B FROM Kind WHERE A > 1 ORDER BY A, B

não altera o índice obrigatório, uma vez que as propriedades projetadas A e B já foram incluídas na consulta atual.

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Ambiente padrão do App Engine para Java