Consultas de projeção

Na maioria das consultas do 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 que você consulte no Datastore apenas as propriedades específicas de uma entidade que você realmente precisa, com menor latência e custo do que a recuperação de entidades inteiras.

As consultas de projeção são semelhantes às de 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 resultados resumidos apenas com as propriedades especificadas (name, email e phone, no exemplo) preenchidas com valores. Todas as outras propriedades não têm dados.

Como usar consultas de projeção no Go 1.11

Ao preparar um Query, especifique uma projeção usando o método Project:

q := datastore.NewQuery("People").Project("FirstName", "LastName")

A forma de tratar os resultados dessas consultas é a mesma para a consulta de entidade padrão. Por exemplo, iterando os resultados.

O exemplo a seguir consulta as propriedades Title, ReadPath e DateWritten de todas as entradas EventLog, classificadas em ordem crescente em DateWritten e grava o valor de cada propriedade no registro do aplicativo:

q := datastore.NewQuery("EventLog").
	Project("Title", "ReadPath", "DateWritten").
	Order("DateWritten")
t := q.Run(ctx)
for {
	var l EventLog
	_, err := t.Next(&l)
	if err == datastore.Done {
		break
	}
	if err != nil {
		log.Errorf(ctx, "Running query: %v", err)
		break
	}
	log.Infof(ctx, "Log record: %v, %v, %v", l.Title, l.ReadPath, l.DateWritten)
}

Agrupamento(experimental)

As consultas de projeção podem usar o método Distinct para garantir que apenas 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.

q := datastore.NewQuery("Person").
	Project("LastName", "Height").Distinct().
	Filter("Height >", 20).
	Order("-Height").Order("LastName")

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. As strings com mais de 1.500 bytes e matrizes de bytes com mais de 1.500 elementos não são indexadas.

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

  • Propriedades referenciadas em um filtro de igualdade (=) 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
    

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

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

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

Projeções e propriedades de vários valores

A projeção de uma propriedade de 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, suponha que você tenha uma entidade do tipo Foo com duas propriedades de múltiplos valores, A e B:

entity := Foo{A: []int{1, 1, 2, 3}, B: []string{"x", "y", "x"}}

Neste caso, a consulta de projeção

q := datastore.NewQuery("Foo").Project("A", "B").Filter("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 que inclua essa propriedade.

Índices de projeções

Consultas de projeção exigem que todas as propriedades especificadas estejam incluídas em um índice do Datastore. O servidor de desenvolvimento do App Engine gera automaticamente os índices necessários no arquivo de configuração do índice, index.yaml, que é carregado com o aplicativo.

Uma forma de reduzir o número de índices necessários é projetar as mesmas propriedades consistentemente, 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)

A conversão 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

introduz uma nova propriedade (C), sendo, portanto, necessário criar 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 exigido, uma vez que as propriedades projetadas A e B já foram incluídas na consulta existente.