GqlQuery 类

注意强烈建议构建新应用的开发者使用 NDB 客户端库,它与 DB 客户端库相比具有多项优势,例如可通过 Memcache API 进行自动实体缓存。如果您当前使用的是较早的 DB 客户端库,请参阅 DB 到 NDB 的迁移指南

GqlQuery 表示使用类似于 SQL 的 App Engine 查询语言 GQL 从 App Engine Datastore 中检索实体的查询。如需查看 GQL 语法和功能的完整介绍,请参阅 GQL 参考文档;另请参见相关类 Query,该类使用对象和方法(而不是 GQL)来准备查询。

GqlQuery 在模块 google.appengine.ext.db 中定义。

注意:基于索引的查询机制支持多种查询,适用于大多数应用,但它不支持其他数据库技术中常见的某些种类的查询:特别是 Datastore 查询引擎不支持联接和聚合查询。如需了解 Datastore 查询的相关限制,请参阅 Datastore 查询页面。

简介

应用通过直接调用 GqlQuery 构造函数或调用实体种类的模型类的 gql() 类方法来创建 GQL 查询对象。GqlQuery 构造函数将查询字符串(即以 SELECT ... FROM model-name 开头的完整 GQL 语句)作为参数。WHERE 子句中的值可以是数字或字符串字面量,也可以对值使用参数绑定。参数可以使用定位参数或关键字参数来绑定:

q = GqlQuery("SELECT * FROM Song WHERE composer = 'Lennon, John'")

q = GqlQuery("SELECT __key__ FROM Song WHERE composer = :1", "Lennon, John")

q = GqlQuery("SELECT * FROM Song WHERE composer = :composer", composer="Lennon, John")

为方便起见,ModelExpando 类有一个可返回 GqlQuery 实例的类方法 gql()。此方法接受不含 SELECT ... FROM model-name 前缀的 GQL 查询字符串(该前缀的含义已暗含其中):

q = Song.gql("WHERE composer = 'Lennon, John'")

然后,应用可以执行查询并以下列任一方式访问结果:

  • 将查询对象视为一个可迭代对象,每次处理一个匹配的实体:

    for song in q:
      print song.title

    这样会隐式调用查询的 run() 方法来生成匹配的实体,因而等效于

    for song in q.run():
      print song.title

    您可以使用关键字参数 limit 设置要处理的结果数量上限:

    for song in q.run(limit=5):
      print song.title

    迭代器接口不会缓存结果,因此通过查询对象创建新的迭代器会从头开始重复执行相同的查询。

  • 调用查询的 get() 方法,以获取在 Datastore 中找到的第一个匹配实体:

    song = q.get()
    print song.title
  • 调用查询的 fetch() 方法,以获取所有匹配实体的列表,直到达到指定的结果数:

    results = q.fetch(limit=5)
    for song in results:
      print song.title

    run() 一样,查询对象不会缓存结果,因此第二次调用 fetch() 会重新发出相同的查询。

    注意:您应该很少需要使用此方法;通常情况下,改用 run() 会更好。

构造函数

GqlQuery 类的构造函数定义如下:

class GqlQuery (query_string, *args, **kwds)

创建 GqlQuery 类的实例,以便使用 GQL 查询语言从 App Engine Datastore 中检索实体。

参数

query_string
包含完整 GQL 语句的字符串。
args
定位参数值。
kwds
关键字参数值。

实例方法

GqlQuery 类的实例具有以下方法:

bind (*args, **kwds)

重新绑定查询的参数值。重新绑定参数后,访问第一个结果时,将执行修改后的查询。

将参数重新绑定到现有 GqlQuery 对象比构建新的 GqlQuery 对象更快,因为无需再次解析查询字符串。

参数

args
新的位置参数值。
kwds
新的关键字参数值。
projection()

返回投影中的属性元组或 None

is_keys_only()

返回一个布尔值,指示查询是否为仅限于键的查询。

run (read_policy=STRONG_CONSISTENCY, deadline=60, offset=0, limit=None, batch_size=20, keys_only=False, projection=None, start_cursor=None, end_cursor=None)

返回一个用于遍历查询结果的可迭代对象。这样,您将可以使用参数设置指定查询的操作,并以迭代方式访问结果:

  1. 检索并舍弃 offset 参数指定的数量的结果。
  2. 检索并返回结果,结果的数量不超出 limit 参数指定的上限。

因此,循环的性能与 offset + limit 之和呈线性比例关系。如果您知道想要检索的结果数量,应始终设置一个显式 limit 值。

此方法使用异步预取来提升性能。默认情况下,此方法以小批量的形式从 Datastore 检索其结果,让应用可以停止迭代,避免检索结果超出所需的数量。

提示:如需在结果数量未知时检索所有可用的结果,请将batch_size 设置为较大的值,例如 1000

提示:如果您不需要更改默认参数值,可以直接将查询对象用作可迭代对象来控制循环。这样会使用默认参数隐式调用 run()

参数

read_policy
指定所需的数据一致性级别的读取政策:
STRONG_CONSISTENCY
保证返回最新的结果,但仅限于单个实体组
EVENTUAL_CONSISTENCY
可以跨越多个实体组,但有时可能会返回过时的结果。通常,最终一致性查询比强一致性查询的运行速度更快,但并不保证始终如此。

注意:全局(非祖先)查询会忽略此参数。

deadline
在使用错误代码取消查询之前,等待 Datastore 返回结果的最长时间(以秒为单位)。接受整数或浮点值。设置的值不能高于默认值(60 秒),但可以向下调整,以确保特定操作快速失败(例如,更快地向用户给出响应、重试操作、尝试其他操作,或将该操作添加到任务队列)。
偏移
返回第一条结果之前要跳过的结果数。
limit
返回的结果数上限。 如果省略此参数,则将使用 GQL 查询字符串的 LIMIT 子句中指定的值。如果明确设置为 None,将检索所有可用的结果。
batch_size
每批尝试检索的结果数量。如果设置了 limit,则默认为指定的该上限;否则默认为 20
keys_only
如果为 true,则仅返回键,而不是完整实体。 与返回完整实体的查询相比,仅限于键的查询速度更快、费用更低。
投影
需要返回的属性名称的列表或元组。只返回具有指定属性的实体。如果未指定,则默认返回整个实体。 与返回完整实体的查询相比,投影查询速度更快、费用更低。

注意:指定此参数可能会更改查询的索引要求。

start_cursor
开始查询的游标位置。
end_cursor
结束查询的游标位置。
get (read_policy=STRONG_CONSISTENCY, deadline=60, offset=0, keys_only=False, projection=None, start_cursor=None, end_cursor=None)

执行查询并返回第一个结果,如果未找到结果,则返回 None。 从数据存储区中检索至多一个结果;如果有 GQL 查询字符串的 LIMIT 子句,则会被忽略。

参数

read_policy
指定所需的数据一致性级别的读取政策:
STRONG_CONSISTENCY
保证返回最新的结果,但仅限于单个实体组
EVENTUAL_CONSISTENCY
可以跨越多个实体组,但有时可能会返回过时的结果。通常,最终一致性查询比强一致性查询的运行速度更快,但并不保证始终如此。

注意:全局(非祖先)查询会忽略此参数。

deadline
在使用错误代码取消查询之前,等待 Datastore 返回结果的最长时间(以秒为单位)。接受整数或浮点值。设置的值不能高于默认值(60 秒),但可以向下调整,以确保特定操作快速失败(例如,更快地向用户给出响应、重试操作、尝试其他操作,或将该操作添加到任务队列)。
偏移
返回第一条结果之前要跳过的结果数。
keys_only
如果为 true,则仅返回键,而不是完整实体。 与返回完整实体的查询相比,仅限于键的查询速度更快、费用更低。
投影
需要返回的属性名称的列表或元组。只返回具有指定属性的实体。如果未指定,则默认返回整个实体。 与返回完整实体的查询相比,投影查询速度更快、费用更低。

注意:指定此参数可能会更改查询的索引要求。

start_cursor
开始查询的游标位置。
end_cursor
结束查询的游标位置。
fetch (limit, read_policy=STRONG_CONSISTENCY, deadline=60, offset=0, keys_only=False, projection=None, start_cursor=None, end_cursor=None)

执行查询并返回一个(可能为空的)结果列表:

  1. 检索并舍弃 offset 参数指定的数量的结果。
  2. 检索并返回结果,结果的数量不超出 limit 参数指定的上限。

因此,方法的性能与 offset + limit 之和呈线性比例关系。

注意:此方法仅仅是 run() 方法的一个瘦封装容器,与直接使用 run() 相比,效率较低,而占用的内存较多。您应该很少需要使用 fetch();提供此方法的主要目的是为了让您在需要检索查询结果的完整内存列表时更方便。

提示fetch() 方法旨在仅检索 limit 参数指定的数量的结果。如需在结果数量未知时检索查询的所有可用结果,请使用较大批次的 run()(例如 run(batch_size=1000)),而不要使用 fetch()

参数

limit
返回的结果数上限。 如果设置为 None,将检索所有可用的结果。
read_policy
指定所需的数据一致性级别的读取政策:
STRONG_CONSISTENCY
保证返回最新的结果,但仅限于单个实体组
EVENTUAL_CONSISTENCY
可以跨越多个实体组,但有时可能会返回过时的结果。通常,最终一致性查询比强一致性查询的运行速度更快,但并不保证始终如此。

注意:全局(非祖先)查询会忽略此参数。

deadline
在使用错误代码取消查询之前,等待 Datastore 返回结果的最长时间(以秒为单位)。接受整数或浮点值。设置的值不能高于默认值(60 秒),但可以向下调整,以确保特定操作快速失败(例如,更快地向用户给出响应、重试操作、尝试其他操作,或将该操作添加到任务队列)。
偏移
返回第一条结果之前要跳过的结果数。
keys_only
如果为 true,则仅返回键,而不是完整实体。 与返回完整实体的查询相比,仅限于键的查询速度更快、费用更低。
投影
需要返回的属性名称的列表或元组。只返回具有指定属性的实体。如果未指定,则默认返回整个实体。 与返回完整实体的查询相比,投影查询速度更快、费用更低。

注意:指定此参数可能会更改查询的索引要求。

start_cursor
开始查询的游标位置。
end_cursor
结束查询的游标位置。
count (read_policy=STRONG_CONSISTENCY, deadline=60, offset=0, limit=1000, start_cursor=None, end_cursor=None)

返回与查询匹配的结果数量。这样比实际检索所有结果要快一个常数因子的倍数,但运行时间仍然与 offset + limit 之和呈线性比例关系。除非预计结果数很少,否则最好指定一个 limit 参数;不然该方法将持续运行,直到其完成计数或超时为止。

参数

read_policy
指定所需的数据一致性级别的读取政策:
STRONG_CONSISTENCY
保证返回最新的结果,但仅限于单个实体组
EVENTUAL_CONSISTENCY
可以跨越多个实体组,但有时可能会返回过时的结果。通常,最终一致性查询比强一致性查询的运行速度更快,但并不保证始终如此。

注意:全局(非祖先)查询会忽略此参数。

deadline
在使用错误代码取消查询之前,等待 Datastore 返回结果的最长时间(以秒为单位)。接受整数或浮点值。设置的值不能高于默认值(60 秒),但可以向下调整,以确保特定操作快速失败(例如,更快地向用户给出响应、重试操作、尝试其他操作,或将该操作添加到任务队列)。
偏移
对第一个结果计数之前要跳过的结果数量。
limit
需要计数的结果数量上限。

注意:如果明确指定,则此参数将替换 GQL 查询字符串的 LIMIT 子句中设置的任何值。不过,如果省略了此参数,默认值 1000 不会替换 GQL 查询的 LIMIT 子句,并且仅在未指定 LIMIT 子句时才会应用。

start_cursor
开始查询的游标位置。
end_cursor
结束查询的游标位置。
index_list()

返回已执行查询使用的索引列表,包括主索引、复合索引、种类索引和单属性索引。

注意:对尚未执行的查询调用此方法将引发 AssertionError 异常。

注意:开发服务器不完全支持此功能。对开发服务器调用此方法时,结果会是空列表,或只包含一个复合索引的列表。

例如,以下代码会输出有关查询使用的索引的各种信息:

# other imports ...
import webapp2
from google.appengine.api import users
from google.appengine.ext import db

class Greeting(db.Model):
  author = db.StringProperty()
  content = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)

class MainPage(webapp2.RequestHandler):
  def get(self):
    user = users.get_current_user()
    q = db.GqlQuery(Greeting)
    q.filter("author =", user.user_id())
    q.order("-date")
    q.fetch(100)
    index_list = q.index_list()
    for ix in index_list:
      self.response.out.write("Kind: %s" % ix.kind())
      self.response.out.write("<br />")
      self.response.out.write("Has ancestor? %s" % ix.has_ancestor())
      self.response.out.write("<br />")
      for name, direction in ix.properties():
        self.response.out.write("Property name: "+name)
        self.response.out.write("<br />")
        if direction == db.Index.DESCENDING:
          self.response.out.write("Sort direction: DESCENDING")
        else:
          self.response.out.write("Sort direction: ASCENDING")
        self.response.out.write("<br />")

这样会为每个索引生成如下输出:

Kind: Greeting
Has ancestor? False
Property name: author
Sort direction: ASCENDING
Property name: date
Sort direction: DESCENDING
cursor()

返回 base64 编码的游标字符串,用于表示查询结果集中检索到的最后一条结果后面的位置。游标字符串可以安全地用于 HTTP GETPOST 参数,也可以存储在 Datastore 或 Memcache 中。未来对同一查询的调用可以通过 start_cursor 参数或 with_cursor() 方法提供此字符串,以继续从此位置检索结果。

注意:对尚未执行的查询调用此方法将引发 AssertionError 异常。

注意:并非所有查询都与游标兼容;如需了解详情,请参阅 Datastore 查询页面。

with_cursor (start_cursor, end_cursor=None)

在要从中检索结果的查询结果集中,指定起始位置和(可选)结束位置。表示起始和结束位置的游标字符串可以在先前调用查询之后调用 cursor() 来获得。当前查询必须与先前的调用完全相同,包括实体种类、属性过滤条件、祖先实体过滤条件以及排序顺序。

参数

start_cursor
Base64 编码的游标字符串,指定开始查询的位置。
end_cursor
Base64 编码的游标字符串,指定结束查询的位置。