Query 类

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

Query 类表示从 App Engine Datastore 检索实体的查询。(另请参阅相关的 GqlQuery 类,该类使用 GQL 定义查询,GQL 是一种类似 SQL 的查询语言。)

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

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

简介

应用可以直接调用 Query 构造函数为指定的实体种类创建查询对象:

class Song(db.Model):
  title = db.StringProperty()
  composer = db.StringProperty()
  date = db.DateTimeProperty()

q = db.Query(Song)

也可以通过调用其模型类的 all() 类方法来创建查询对象:

q = Song.all()

无需进一步修改,生成的 Query 类实例将会检索指定种类的所有现有实体。然后可以调用对象方法,使用其他过滤条件、祖先条件和排序顺序来自定义该查询:

q.filter('title =', 'Imagine')
q.ancestor(ancestor_key)
q.order('-date')

为方便起见,所有这些方法都会返回查询对象本身,以便在单个语句中级联这些方法:

q.filter('title =', 'Imagine').ancestor(key).order('-date')

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

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

    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() 会更好。

构造函数

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

class Query (model_class=None, keys_only=False, cursor=None, namespace=None, projection=None, distinct=False)

创建一个用于从 App Engine Datastore 检索实体的 Query 类的实例。

无需进一步修改,生成的查询对象将会检索由 model_class 指定的种类的所有现有实体。然后,您可以使用实例方法 filter()ancestor(),order(),以通过其他过滤条件、祖先条件、排序顺序来自定义查询。

参数

model_class
模型(或 Expando)类,表示要应用查询的实体种类。
keys_only
如果为 true,则仅返回键,而不是完整实体。 与返回完整实体的查询相比,仅限于键的查询速度更快、费用更低。
cursor
继续查询的游标位置。
namespace
用于查询的命名空间。
投影
需要返回的属性名称的列表或元组。只返回具有指定属性的实体。如果未指定,则默认返回整个实体。 与返回完整实体的查询相比,投影查询速度更快、费用更低。

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

distinct
对于投影查询distinct=True 指定仅在结果集中返回完全独一无二的结果。这样将仅返回与所投影的属性具有相同值的实体的第一条结果。
True
仅返回投影中属性的每个不同的值集的第一条结果。
False
返回所有结果。

实例方法

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

filter (property_operator, value)

向查询添加属性过滤条件。查询将仅返回属性满足所有过滤条件的实体。

参数

property_operator
由属性名称和可选的比较运算符(=!=<<=>>=IN)组成的字符串,用空格分隔:例如,'age >'。如果只指定属性名称,而没有指定比较运算符,则在默认情况下,过滤条件会比较两个值是否相等 (=)。
value
需要与属性值进行比较的值。例如:

q.filter('height >', 42).filter('city =', 'Seattle')
q.filter('user =', users.get_current_user())

指定的比较值应与要比较的属性的值类型相同。

ancestor (ancestor)

向查询添加祖先过滤条件。查询将仅返回具有指定祖先的实体。

参数

祖先实体
祖先实体或键。
order (property)

向查询添加排序顺序。如果添加了多个排序顺序,这些排序顺序将按指定的顺序应用。

参数

属性
用于指定要排序的属性名称的字符串,您可以在前面附加连字符 (-) 以指定降序。如果省略连字符,则会默认指定升序。 例如:
# Order alphabetically by last name:
q.order('last_name')

# Order by height, tallest to shortest:
q.order('-height')
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 秒),但可以向下调整,以确保特定操作快速失败(例如,更快地向用户给出响应、重试操作、尝试其他操作,或将该操作添加到任务队列)。
offset
返回第一条结果之前要跳过的结果数。
limit
返回的结果数上限。 如果省略或设置为 None,默认情况下将检索所有可用的结果。
batch_size
每批尝试检索的结果数量。如果设置了 limit,则默认为指定的该上限;否则默认为 20
keys_only
如果为 true,则仅返回键,而不是完整实体。 与返回完整实体的查询相比,仅限于键的查询速度更快、费用更低。
投影
需要返回的属性名称的列表或元组。只返回具有指定属性的实体。如果未指定,则默认返回整个实体。 与返回完整实体的查询相比,投影查询速度更快、费用更低。

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

start_cursor
开始查询的游标位置。
end_cursor
结束查询的游标位置。
get (read_policy=STRONG_CONSISTENCY, read_policy=STRONG_CONSISTENCY, read_policy=STRONG_CONSISTENCY, read_policy=STRONG_CONSISTENCY, read_policy=STRONG_CONSISTENCY, read_policy=STRONG_CONSISTENCY, read_policy=STRONG_CONSISTENCY)

执行查询并返回第一个结果,如果未找到结果,则返回 None

参数

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

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

deadline
在使用错误代码取消查询之前,等待 Datastore 返回结果的最长时间(以秒为单位)。接受整数或浮点值。设置的值不能高于默认值(60 秒),但可以向下调整,以确保特定操作快速失败(例如,更快地向用户给出响应、重试操作、尝试其他操作,或将该操作添加到任务队列)。
offset
返回第一条结果之前要跳过的结果数。
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 秒),但可以向下调整,以确保特定操作快速失败(例如,更快地向用户给出响应、重试操作、尝试其他操作,或将该操作添加到任务队列)。
offset
返回第一条结果之前要跳过的结果数。
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 秒),但可以向下调整,以确保特定操作快速失败(例如,更快地向用户给出响应、重试操作、尝试其他操作,或将该操作添加到任务队列)。
offset
对第一个结果计数之前要跳过的结果数量。
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.Query(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 编码的游标字符串,指定结束查询的位置。