GQL 是類似 SQL 的語言,用於擷取實體和金鑰。GQL 查詢的語法與 SQL 相似。本頁提供參考資料,說明如何搭配使用 Python NDB 和 DB 用戶端程式庫使用 GQL。
GQL 大致對應至 SQL:您可以將 GQL kind
視為 SQL 資料表、GQL entity
視為 SQL 資料列,以及 GQL property
視為 SQL 欄。不過,SQL 的資料列-資料欄查詢為單一值,但 GQL 的屬性值可能是一份清單。
GQL 版本
根據執行查詢的位置,您會需要不同版本的 GQL。以下提供兩份 GQL 參考資料:
-
Python NDB/DB 適用的 GQL 參考資料,適用於 NDB 和 DB 用戶端程式庫中使用的 GQL 文法 (請使用本頁的參考資料)。
- GQL 參考資料:提供 Cloud Datastore API 和 Google Cloud 控制台 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 查詢會傳回 0 個以上所要求種類的完整實體、投影實體或金鑰。每項 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
- 布林常值,指
TRUE
或FALSE
。 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
的條件會確認空值是否明確儲存在該項屬性的資料儲存庫中。這與檢查實體是否缺少屬性值不同!資料儲存庫查詢參照屬性時,絕不會傳回沒有該屬性值的實體。
繫結參數可以繫結為位置引數或關鍵字引數,並傳送給 GqlQuery 建構函式或模型類別的 gql() 方法。屬性資料類型 (包括清單資料類型) 如沒有對應的值字面語法,就必須使用參數繫結指定。在 GqlQuery 執行個體的生命週期內 (例如有效率地重複使用查詢),參數繫結可以使用 bind() 方法與新值重新建立繫結。
選用的 ORDER BY
子句表示結果應以遞增 (ASC
) 或遞減 (DESC
) 順序,依指定屬性排序後傳回。ORDER BY
子句可將多個排序順序指定為以逗號分隔的清單,並從左到右進行評估。如未指定方向,則預設為 ASC
。如果未指定 ORDER BY
子句,則結果的順序未定義,且可能會隨時間而變更。
選用的 LIMIT
子句會讓查詢在第一個 <count>
實體後停止傳回結果。LIMIT
子句也可以包含 <offset>
,藉此略過多個結果,找出要傳回的第一個結果。如果沒有 LIMIT
子句,選用的 OFFSET
子句可以指定 <offset>
。
注意:如同 fetch() 方法的 offset
參數,GQL 查詢字串中的 OFFSET
不會減少從資料儲存庫擷取的實體數量。這只會影響 fetch() 方法傳回的結果。使用 offset 的查詢含有效能特性,可以隨著偏移大小和限制大小進行線性對應。
如要瞭解如何執行 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 歲的所有 Person
類型實體 (即 Charlies 和 Edna),請使用以下查詢:
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')
如要只傳回每個 Person
的 name
值,請使用以下查詢:
SELECT name FROM Person
如要只傳回每個 Person
的 name
值,並按照 age
排序,請使用以下查詢:
SELECT name FROM Person ORDER BY age
如要尋找 Person
類型實體的索引鍵,且該實體的年齡為 None
(即 KEY('Person', 'georgemichael')
),請使用以下查詢:
SELECT __key__ FROM Person WHERE age = NULL
如要尋找 Amy 的實體群組中 (亦即 Amy 和 Fred) 的所有實體,不限種類,請使用這個查詢:
SELECT * WHERE __key__ HAS ANCESTOR KEY(Person, 'Amy')
如要依 Key 比對,我們可以在限制條件左側使用 __key__
。舉例來說,我們可以使用這個查詢取得使用者名稱以「a」開頭的所有 Person
實體。
SELECT * FROM Person WHERE __key__ >= KEY('Person', 'a') AND __key__ < KEY('Person', 'b')
注意:如果您使用等式建立查詢的 __key__
,請考慮改用 get()
直接擷取實體。