大多数 Datastore 查询将返回完整的实体作为其结果,但实际上应用经常仅关注实体的几个属性。借助投影查询,您可以仅在 Datastore 中查询针对某个实体而言您确实需要的特定属性;与检索整个实体相比,这既可以缩短延迟时间,又可以降低费用。
投影查询类似于如下形式的 SQL 查询:
SELECT name, email, phone FROM CUSTOMER
您可以使用所有适用于标准实体查询的过滤和排序功能,但需遵守下述限制。查询会返回删节的结果,其中只有指定的属性(name
、email
和 phone
)填充了值;其他所有属性均不含值。
在 Go 1.11 中使用投影查询
准备 Query
时,请使用 Project
方法指定投影:
您可以像处理标准实体查询一样处理这些查询的结果,例如通过迭代结果。
以下示例查询所有 EventLog
条目的 Title
、ReadPath
和 DateWritten
属性(按 DateWritten
升序排序),并将每个属性的值写入应用日志中:
分组(实验)
投影查询可以使用 Distinct
方法确保仅在结果集中返回完全唯一的结果。对于在所投影的属性上具有相同值的实体,只会返回第一条结果。
投影限制
投影查询受限于以下限制:
仅可投影编入索引的属性。
未编入索引(无论是显式还是隐式)的属性都不支持投影。无法将长度超过 1500 个字节的字符串和拥有超过 1500 个元素的字节数组编入索引。
同一个属性不能投影多次。
在相等性 (
=
) 过滤条件内引用的属性无法投影。例如:
SELECT A FROM kind WHERE B = 1
是有效的(投影的属性未在相等性过滤条件中使用),
SELECT A FROM kind WHERE A > 1
(不是相等性过滤条件)也是有效的,但
SELECT A FROM kind WHERE A = 1
(在相等性过滤条件中使用了投影的属性)则无效。
投影查询返回的结果不应保存回 Datastore。
由于查询返回的结果仅填充了部分值,因此不应将其写回到 Datastore。
投影和多值属性
投影具有多个值的属性不会填充该属性的所有值。相反,对于匹配查询的投影值的每个唯一组合,都会返回一个单独的实体。例如,假设您有一个种类为 Foo
的实体,它具有两个多值属性 A
和 B
:
以下投影查询
将返回具有以下值的组合的四个实体:
A
= 1
,B
= 'x'
A
= 1
,B
= 'y'
A
= 2
,B
= 'x'
A
= 2
,B
= 'y'
请注意,如果实体具有不带值的多值属性,则相关索引中不会包含任何条目,并且包含该属性的投影查询不会返回该实体对应的结果。
投影索引
投影查询要求投影中指定的所有属性都包含在 Datastore 索引中。App Engine 开发服务器会在索引配置文件 index.yaml
中为您自动生成所需的索引,该文件会随应用一起上传。
如需最大程度减少所需的索引数量,一种方式是始终投影相同的属性,即便并非总是需要所有这些属性。例如,以下查询需要两个单独的索引:
SELECT A, B FROM Kind
SELECT A, B, C FROM Kind
但是,如果您始终投影属性 A
、B
和 C
(即使不需要 C
),则只需要一个索引。
如果投影中的属性尚未包含在查询的另一部分中,则将现有查询转换为投影查询可能需要构建新的索引。例如,假设您有如下现有查询
SELECT * FROM Kind WHERE A > 1 ORDER BY A, B
该查询需要以下索引:
Index(Kind, A, B)
将其转换为以下任一投影查询
SELECT C FROM Kind WHERE A > 1 ORDER BY A, B
SELECT A, B, C FROM Kind WHERE A > 1 ORDER BY A, B
会引入一个新属性 (C
),因此需要构建一个新索引 Index(Kind,
A,
B,
C)
。请注意,投影查询
SELECT A, B FROM Kind WHERE A > 1 ORDER BY A, B
不会更改所需索引,因为投影属性 A
和 B
已包含在现有查询中。