O Python 2 não é mais compatível com a comunidade. Recomendamos que você migre aplicativos do Python 2 para o Python 3.

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 apenas as propriedades específicas de uma entidade que você realmente precisa no Datastore, 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

Você pode usar todos os recursos de filtragem e classificação disponíveis para consultas de entidade padrão, sujeito à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 em Python 2

Pense no seguinte modelo:

class Article(ndb.Model):
    title = ndb.StringProperty()
    author = ndb.StringProperty()
    tags = ndb.StringProperty(repeated=True)

Especifique uma projeção desta forma:

def print_author_tags():
    query = Article.query()
    articles = query.fetch(20, projection=[Article.author, Article.tags])
    for article in articles:
        print(article.author)
        print(article.tags)
        # article.title will raise a ndb.UnprojectedPropertyError

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

for article in articles:
        print(article.author)
        print(article.tags)
        # article.title will raise a ndb.UnprojectedPropertyError

É possível projetar sub-propriedades indexadas a partir de uma propriedade estruturada. Para conseguir apenas a propriedade city da propriedade estruturada address de um contato, use uma projeção como:

class Address(ndb.Model):
    type = ndb.StringProperty()  # E.g., 'home', 'work'
    street = ndb.StringProperty()
    city = ndb.StringProperty()
...
class Contact(ndb.Model):
    name = ndb.StringProperty()
    addresses = ndb.StructuredProperty(Address, repeated=True)
...
    Contact.query().fetch(projection=["name", "addresses.city"])
    Contact.query().fetch(projection=[Contact.name, Contact.addresses.city])

Agrupamento(experimental)

As consultas de projeção podem usar a palavra-chave 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.

    Article.query(projection=[Article.author], group_by=[Article.author])
    Article.query(projection=[Article.author], distinct=True)

Ambas as consultas são equivalentes e produzirão o nome de cada autor apenas uma vez.

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.

  • Propriedades referenciadas em um filtro de igualdade (=) ou de associação (IN) não são 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 retornados por uma consulta de projeção não podem ser salvos no Datastore.

    Como a consulta retorna resultados parcialmente preenchidos, não é possível gravá-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=[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 que inclua essa propriedade.

Índices de projeções

As consultas de projeção requerem a inclusão de todas as propriedades especificadas na projeção em um índice do Datastore. O servidor de desenvolvimento do App Engine gera automaticamente os índices necessários para você 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) e, portanto, será 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.