适用于 Python NDB/DB 的 GQL 参考

GQL 是一种类似于 SQL 的语言,用于检索实体和键。GQL 查询的语法类似于 SQL 语法。本页面介绍了如何将 GQL 用于 Python NDB 和 DB 客户端库。

GQL 与 SQL 大致对应:您可以将 GQL kind 视为 SQL 表,将 GQL entity 视为 SQL 行,将 GQL property 视为 SQL 列。但是,SQL 行列查询是单个值,而在 GQL 中,属性值可以是一个列表。

GQL 版本

根据您运行查询的位置,您需要使用不同版本的 GQL。有两个 GQL 参考:

  • 适用于 Python NDB/DB 的 GQL 参考,适用于在 NDB 和 DB 客户端库中使用的 GQL 语法(使用此页面上的参考)。

  • GQL 参考,适用于在当前 Datastore API 和 Google Cloud Console Datastore 查看器中使用的 GQL 语法。

语法

适用于 Python NDB/DB 的 GQL 语法可归纳汇总如下:

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> ...]])

与 SQL 一样,GQL 关键字不区分大小写。种类和属性名称区分大小写。

GQL 仅支持 SELECT 语句。

GQL 查询返回零个或零个以上完整实体、投影的实体或所请求种类的。每个 GQL 查询始终以 SELECT *SELECT __key__ 或 SELECT <property list> 开头,其中 property 是要从查询返回的一个或多个实体属性的英文逗号分隔列表。(GQL 查询无法执行类似于 SQL 的“联接”查询。)

提示SELECT __key__ or SELECT <property list> 查询速度更快,占用的 CPU 时间也比 SELECT * 查询少。

可选的 DISTINCT(实验性)子句指定结果集中仅返回完全唯一的结果。这将仅返回与所投影的属性具有相同值的实体的第一条结果。

可选的 FROM 子句将结果集限制为给定种类的实体。没有 FROM 子句的查询称为不分类查询,并且只能有指定 __key__ 属性的 WHERE

可选的 WHERE 子句对结果集进行限制,以便只包括满足一个或多个条件的实体。每个条件都使用比较运算符将实体的属性与值进行比较。如果使用 AND 关键字给出多个条件,则实体必须满足所有条件才能被查询返回。GQL 没有 OR 运算符。但是,它有一个 IN 运算符,提供有限形式的 OR 运算。

IN 运算符将属性的值与列表中的每个项进行比较。IN 运算符等同于多个 = 查询(每个值对应一个查询)通过 OR 运算结合到一起。若实体指定属性的值等于列表中的任何值,则可以被查询返回。

注意IN!= 运算符在后台使用多个查询。例如,IN 运算符针对列表中的每个项执行单独的基本数据存储区查询。返回的实体是所有基本数据存储区查询的交叉产物的结果,并且消除了重复项。对于任何单个 GQL 查询,最多允许 30 个数据存储区查询。

条件还可以使用 ANCESTOR IS 运算符测试实体是否采用指定的实体作为父实体。此值是祖先实体的模型实例或。如需详细了解祖先,请参阅键和实体组

属性名称始终位于比较的左侧。典型的属性名称由字母数字字符组成,可与下划线和点混合使用。换句话说,它们匹配正则表达式 [a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*

注意:必须使用英文双引号引住包含其他可打印字符的属性名称,例如:"first-name"。不支持在属性名称中使用空格或不可打印字符。

比较的右侧可以是以下内容之一(与属性的数据类型相对应):

  • str 字面量,带英文单引号的字符串。字符串自身中的英文单引号字符必须转义为 ''。例如:'Joe''s Diner'
  • 整数或浮点数字面量,例如:42.7
  • 布尔值字面量,为 TRUEFALSE
  • NULL 字面量,表示空值(在 Python 中为 None)。
  • 日期时间、日期或时间字面量(以数值或字符串表示),格式如下:
    • 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')
  • 实体键字面量,带有字符串编码键种类和键名称/ID 的完整路径

    • KEY('encoded key')
    • KEY('kind', 'name'/ID [, 'kind', 'name'/ID...])
  • 用户对象字面量,带有用户的电子邮件地址:
    USER('email-address')
  • GeoPt 字面量,带有浮点值形式的纬度和经度:
    GEOPT(lat, long)
  • 绑定参数值。在查询字符串中,位置参数由数字引用:title = :1。关键字参数由名称引用:title = :mytitle

注意:形式 property = NULL 的条件检查数据存储区中是否明确为该属性存储了 null 值。与查看实体的属性是否缺少任何值不同。 若数据存储区查询引用某个属性,则永远不会返回该属性没有值的实体。

绑定参数可以绑定为传递给 GqlQuery 构造函数或模型类的 gql() 方法的位置参数或关键字参数。必须使用参数绑定来指定没有对应值常量语法的属性数据类型,包括列表数据类型。 可以使用 bind() 方法在 GqlQuery 实例的生命周期内为参数绑定重新绑定新值(以便高效地重用查询)。

可选的 ORDER BY 子句指示应按照指定属性进行排序,以升序 (ASC) 或降序 (DESC) 返回结果。ORDER BY 子句可以用逗号分隔列表的形式指定多种排列顺序,从左到右进行评估。如果未指定方向,其默认为 ASC。如果未指定 ORDER BY 从句,则结果的顺序将未定义,且可能会随时更改。

可选 LIMIT 子句使查询在前 <count> 个实体后停止返回结果。LIMIT 子句还可以包含 <offset>,以便跳过该数量的结果后才查找要返回的第一个结果。如果不使用 LIMIT 子句,则可选的 OFFSET 子句可以指定 <offset>

注意:与 fetch() 方法的 offset 参数一样,GQL 查询字符串中的 OFFSET 不会减少从数据存储区中提取的实体数。它仅影响 fetch() 方法返回哪些结果。包含偏移的查询的性能特征与偏移大小加上限制大小呈线性对应关系。

如需了解如何执行 GQL 查询、绑定参数和访问结果,请参阅 GqlQuery 类和 Model.gql() 类方法。

示例

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

要查找年龄在 18 到 35 岁之间(即“Charlie”和“Edna”)的 Person 种类的所有实体,请使用以下查询:

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

要查找年龄最大的 Person 种类的三个实体(即 Amy、Betty 和 Charlie),请使用以下查询:

SELECT * FROM Person ORDER BY age DESC LIMIT 3

要查找名字为“Betty”或“Charlie”之一的 Person 种类实体,请使用以下查询:

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

要仅返回每个 Personname 值,请使用以下查询:

SELECT name FROM Person

要仅返回按 age 排序的每个 Personname 值,请使用以下查询:

SELECT name FROM Person ORDER BY age

要查找年龄为 None(即 KEY('Person', 'georgemichael'))的 Person 种类实体的键,请使用以下查询:

SELECT __key__ FROM Person WHERE age = NULL

要查找与 Amy 属于同一个实体组中的所有实体而不考虑其种类如何(即 Amy 和 Fred),请使用以下查询:

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

要按键进行匹配,可以在条件的左侧使用 __key__。 例如,可以使用它来获取所有用户名以“a”开头的 Person 实体。

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

注意:如果您在 __key__ 上构建了一个包含等式的查询,请考虑改用 get() 直接提取实体。