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 語法:

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 <屬性清單>,其中的「屬性」是以半形逗號分隔的清單,當中包含查詢傳回的一或多項實體屬性。不過,GQL 查詢無法執行類似於 SQL 的「彙整」查詢。

提示:SELECT __key__ or SELECT <property list> 查詢比 SELECT * 查詢的速度更快,耗用的 CPU 作業時間也較短。

選用的 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 的條件會確認空值是否明確儲存在該項屬性的資料儲存庫中。這和檢查該屬性的實體是否缺少任何值不同!參照屬性的資料儲存庫查詢一律不會為該屬性傳回沒有任何值的實體。

繫結參數可以繫結為位置引數或關鍵字引數,並傳送給 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()

如要尋找 Person 種類中年齡介於 18 到 35 歲之間的所有實體 (亦即包含 Charlies 和 Edna),請使用這個查詢:

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

如要尋找 Person 種類中年齡最大的三個實體 (亦即 Amy、Betty 和 Charlie),請使用這個查詢:

SELECT * FROM Person ORDER BY age DESC LIMIT 3

如要尋找 Person 種類中名字為「Betty」或「Charlie」之一的實體,請使用這個查詢:

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

如果只要傳回每個 Personname 值,請使用這個查詢:

SELECT name FROM Person

如果只要傳回每個 Personname 值,並依 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__。舉例來說,我們可以使用這個查詢取得使用者名稱以「a」開頭的所有 Person 實體。

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

注意事項:如果您使用等式建立查詢的 __key__,請考慮改用 get() 直接擷取實體。

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Python 2 適用的 App Engine 標準環境