Referência sobre GQL para NDB/DB do Python

GQL é uma linguagem semelhante à SQL para recuperar entidades e chaves. A sintaxe das consultas GQL é parecida com a das SQL. Esta página é uma referência sobre o uso de GQL com as bibliotecas de cliente NDB e DB do Python.

O GQL mapeia aproximadamente para SQL: considere um kind do GQL como uma tabela SQL, um entity do GQL como uma linha SQL e um property do GQL como uma coluna SQL. No entanto, uma pesquisa de coluna/linha SQL é um valor único, e em GQL um valor de propriedade pode ser uma lista.

Versões de GQL

Você precisa de versões diferentes de GQL, dependendo de onde executa consultas. Há duas referências de GQL:

Sintaxe

A sintaxe GQL para NDB/DB do Python pode ser resumida assim:

SELECT [DISTINCT] [* | <property list> | __key__]
  [FROM <kind>]
  [WHERE <condition> [AND <condition> ...]]
  [ORDER BY <property> [ASC | DESC] [, <property> [ASC | DESC] ...]]
  [LIMIT [<offset>,]<count>]
  [OFFSET <offset>]

  <property list> := <property> [, <property> ...]
  <condition> := <property> {< | <= | > | >= | = | != } <value>
  <condition> := <property> IN <list>
  <condition> := ANCESTOR IS <entity or key>
  <list> := (<value> [, <value> ...]])

Assim como acontece com SQL, as palavras-chave GQL são indiferentes a maiúsculas. Os nomes de propriedade e tipo diferenciam maiúsculas e minúsculas.

O GQL aceita apenas instruções SELECT.

Uma consulta GQL retorna zero ou mais entidades inteiras, entidades projetadas ou chaves do tipo solicitado. Toda consulta GQL sempre começa com SELECT *, SELECT __key__ ou SELECT <property list>, em que property é uma lista delimitada por vírgulas de uma ou mais propriedades de entidade a serem retornadas da consulta. Uma consulta GQL não executa uma consulta "join" semelhante às de SQL.

Dica: as consultas SELECT __key__ or SELECT <property list> são mais rápidas e usam menos tempo de CPU do que as consultas SELECT *.

A cláusula DISTINCT(experimental) opcional especifica que apenas resultados totalmente exclusivos serão retornados em um conjunto de resultados. Ela só retornará o primeiro resultado de entidades com os mesmos valores das propriedades sendo projetadas.

A cláusula FROM opcional limita o conjunto de resultados às entidades do tipo indicado. Uma consulta sem uma cláusula FROM é chamada de consulta sem tipo e tem apenas um WHERE que especifica uma propriedade __key__.

A cláusula WHERE opcional limita o conjunto de resultados às entidades que atendam a uma ou mais condições. Cada condição compara uma propriedade da entidade com um valor usando um operador de comparação. Se forem dadas várias condições com a palavra-chave AND, será necessário que uma entidade atenda a todas as condições a serem retornadas pela consulta. O GQL não tem um operador OR. No entanto, tem um operador IN, que dá uma forma limitada de OR.

O operador IN compara o valor de uma propriedade com todos os itens de uma lista. O operador IN equivale a muitas consultas =, uma para cada valor, que são combinadas com o OR. É possível que uma entidade com valor da propriedade indicada igual a qualquer um dos valores da lista seja retornada para a consulta.

Observação: os operadores IN e != utilizam diversas consultas nos bastidores. Por exemplo, o operador IN executa uma consulta subjacente ao armazenamento de dados separada para cada item da lista. As entidades retornadas são resultado de vários produtos de todas as consultas subjacentes ao armazenamento de dados. A duplicação dessas entidades é eliminada. Um máximo de 30 consultas ao armazenamento de dados é permitido para qualquer consulta GQL única.

Uma condição também testa se uma entidade tem uma determinada entidade como ancestral, utilizando o operador ANCESTOR IS. O valor é uma instância de modelo ou uma chave da entidade do ancestral. Para mais informações sobre ancestrais, consulte Chaves e grupos de entidades.

O lado esquerdo de uma comparação é sempre o nome de uma propriedade. Normalmente, o nome de uma propriedade consiste em caracteres alfanuméricos, que podem ser combinados com sublinhados e pontos. Em outras palavras, eles correspondem à expressão regular [a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*.

Cuidado: é necessário usar aspas duplas em nomes de propriedade que contenham outros caracteres imprimíveis. Por exemplo: "first-name". Espaços ou caracteres não imprimíveis em nomes de propriedade não são compatíveis.

O lado direito de uma comparação pode ser um dos itens a seguir (conforme for apropriado para o tipo de dados da propriedade):

  • Um literal str, como uma string entre aspas simples. É necessário usar o escape '' nos caracteres entre aspas simples na string. Por exemplo: 'Joe''s Diner'.
  • Um literal de número inteiro ou com ponto flutuante. Por exemplo: 42.7.
  • Um literal booleano, como TRUE ou FALSE.
  • O literal NULL, que representa o valor nulo (None no Python).
  • Um literal de data e hora, de data ou de hora, com valores numéricos ou representação de string, nas seguintes formas:
    • DATETIME(year, month, day, hour, minute, second)
    • DATETIME('YYYY-MM-DD HH:MM:SS')
    • DATE(year, month, day)
    • DATE('YYYY-MM-DD')
    • TIME(hour, minute, second)
    • TIME('HH:MM:SS')
  • Um literal de chave de entidade, com uma chave codificada por string ou um caminho completo de IDs/nomes de tipos e chaves:

    • KEY('encoded key')
    • KEY('kind', 'name'/ID [, 'kind', 'name'/ID...])
  • Um literal de objeto User, com o endereço de e-mail do usuário:
    USER('email-address')
  • Um literal de GeoPt, com latitude e longitude como valores de ponto flutuante:
    GEOPT(lat, long)
  • Um valor de parâmetro vinculado. Na string de consulta, os parâmetros posicionais são referenciados por número: title = :1. Os parâmetros de palavra-chave são referenciados por nome: title = :mytitle.

Observação: as condições do formato property = NULL verificam se um valor nulo está armazenado explicitamente no armazenamento de dados dessa propriedade. Isso não é o mesmo que verificar se a entidade não tem algum valor da propriedade. As consultas de armazenamento de dados que se referem a uma propriedade jamais retornam entidades que não tenham um valor dessa propriedade.

É possível vincular os parâmetros como argumentos posicionais ou de palavra-chave transmitidos para o construtor GqlQuery ou para um método gql() da classe de modelo. Os tipos de dados de propriedade que não tenham sintaxe literal de valor correspondente precisam ser especificados usando a vinculação de parâmetro, inclusive o tipo de dado da lista. As vinculações de parâmetros podem ser vinculadas outra vez com novos valores durante o ciclo de vida da instância GqlQuery (como para reutilizar uma consulta com eficiência) usando o método bind().

A cláusula opcional ORDER BY indica que os resultados serão retornados classificados conforme as propriedades fornecidas, em ordem crescente (ASC) ou decrescente (DESC). A cláusula ORDER BY especifica diversas ordens de classificação como uma lista delimitada por vírgulas, avaliada da esquerda para a direita. Se a direção não for especificada, o padrão será ASC. Se nenhuma cláusula ORDER BY for especificada, a ordem dos resultados será indefinida e mudará ao longo do tempo.

Uma cláusula LIMIT opcional faz a consulta parar de retornar resultados após as primeiras entidades <count>. A cláusula LIMIT também inclui um <offset> para ignorar muitos desses resultados e encontrar o primeiro a retornar. Uma cláusula OFFSET opcional especifica um <offset>, se não houver uma cláusula LIMIT.

Observação: como o parâmetro offset para o método fetch(), um OFFSET em uma string de consulta GQL não reduz o número de entidades buscadas no armazenamento de dados. Isso só afeta quais resultados serão retornados pelo método fetch(). Uma consulta com um deslocamento tem características de desempenho correspondentes de maneira linear ao tamanho do deslocamento mais o tamanho limite.

Para informações sobre como executar consultas GQL, vincular parâmetros e acessar resultados, consulte a classe GqlQuery e o método de classe Model.gql().

Exemplos

from google.appengine.ext import db

class Person(db.Model):
  name = db.StringProperty()
  age = db.IntegerProperty()

# We use a unique username for the Entity's key.
amy = Person(key_name='amym', name='Amy', age=48)
amy.put()
Person(key_name='bettyd', name='Betty', age=42).put()
Person(key_name='charliec', name='Charlie', age=32).put()
Person(key_name='charliek', name='Charlie', age=29).put()
Person(key_name='eedna', name='Edna', age=20).put()
Person(key_name='fredm', name='Fred', age=16, parent=amy).put()
Person(key_name='georgemichael', name='George').put()

Para encontrar todas as entidades do tipo Person com idades entre 18 e 35 anos (ou seja, os dois Charlies e a Edna), use esta consulta:

SELECT * FROM Person WHERE age >= 18 AND age <= 35

Para encontrar as três entidades do tipo Person que têm as idades mais altas (ou seja, Amy, Betty e Charlie), use esta consulta:

SELECT * FROM Person ORDER BY age DESC LIMIT 3

Para encontrar as entidades do tipo Person que têm os nomes "Betty" ou "Charlie", use esta consulta:

SELECT * FROM Person WHERE name IN ('Betty', 'Charlie')

Para retornar apenas os valores name de cada Person, use esta consulta:

SELECT name FROM Person

Para retornar apenas os valores name de cada Person, ordenados por age, use esta consulta:

SELECT name FROM Person ORDER BY age

Para encontrar as chaves das entidades do tipo Person com idade de None (ou seja, KEY('Person', 'georgemichael')), use esta consulta:

SELECT __key__ FROM Person WHERE age = NULL

Para encontrar todas as entidades, independentemente do tipo, que estejam no grupo de entidades da Amy (ou seja, Amy e Fred), use esta consulta:

SELECT * WHERE __key__ HAS ANCESTOR KEY(Person, 'Amy')

Para fazer a correspondência por chave, use __key__ no lado esquerdo de uma condição. Por exemplo, é possível usar isso para receber todas as entidades Person que tenham um nome de usuário que comece com "a".

SELECT * FROM Person WHERE __key__ >= KEY('Person', 'a') AND __key__ < KEY('Person', 'b')

Observação: se você criar uma consulta com uma igualdade em __key__, use get() para buscar a entidade diretamente.