投影查詢

大多數的 Cloud Datastore 查詢結果會傳回完整實體,但應用程式真正需要的往往只有該實體的幾項屬性。您可以按照實際需求,運用「投影查詢」在 Cloud Datastore 中單純查詢某個實體的特定屬性,相較於擷取完整實體,這種方式更有助於減少延遲時間及降低成本。

投影查詢近似於下列形式的 SQL 查詢:

SELECT name, email, phone FROM CUSTOMER

您可以使用所有適用於查詢標準實體的篩選及排序功能,但必須遵守以下說明的幾項限制。查詢會傳回只包含指定屬性的節略版結果 (以此範例來說就是 nameemailphone),且這些屬性均已填入值;其他所有屬性均沒有資料。

在 Python 2 中使用投影查詢

請參考下列模型:

class Article(ndb.Model):
    title = ndb.StringProperty()
    author = ndb.StringProperty()
    tags = ndb.StringProperty(repeated=True)

指定投影的方式如下:

def print_author_tags():
    query = Article.query()
    articles = query.fetch(20, projection=[Article.author, Article.tags])
    for article in articles:
        print(article.author)
        print(article.tags)
        # article.title will raise a ndb.UnprojectedPropertyError

處理這些查詢結果的方式,與處理標準實體查詢結果的方式如出一轍,例如可以疊代處理結果。

for article in articles:
        print(article.author)
        print(article.tags)
        # article.title will raise a ndb.UnprojectedPropertyError

您可以透過結構化屬性來投影已建立索引的子屬性。如果僅要取得聯絡人 address 結構化屬性的 city 屬性,您可以使用類似以下的投影:

class Address(ndb.Model):
    type = ndb.StringProperty()  # E.g., 'home', 'work'
    street = ndb.StringProperty()
    city = ndb.StringProperty()
...
class Contact(ndb.Model):
    name = ndb.StringProperty()
    addresses = ndb.StructuredProperty(Address, repeated=True)
...
Contact.query().fetch(projection=["name", "addresses.city"])
Contact.query().fetch(projection=[Contact.name, Contact.addresses.city])

分組(實驗版)

投影查詢可以使用 distinct 關鍵字確認結果集只傳回完全不重複的結果。如有多個實體的投影屬性包含相同的值,這種方式只會傳回第一個結果。

Article.query(projection=[Article.author], group_by=[Article.author])
Article.query(projection=[Article.author], distinct=True)

兩種查詢相同,每個作者的名稱僅會產生一次。

投影限制

投影查詢必須遵循以下限制:

  • 只能投影已建立索引的屬性。

    未建立索引的屬性不支援投影功能 (不分明確或隱含)。長文字字串 (Text) 和長位元組字串 (Blob) 皆未建立索引。

  • 不能重複投影同一個屬性。

  • 不能投影等號 (=) 或成員資格 (IN) 篩選器所參照的屬性。

    例如:

    SELECT A FROM kind WHERE B = 1
    

    有效 (等式篩選器未使用投影屬性),

    SELECT A FROM kind WHERE A > 1
    

    (非等式篩選器) 也有效,但

    SELECT A FROM kind WHERE A = 1
    

    (等號篩選器使用了投影屬性) 則無效。

  • 不能將投影查詢傳回的結果存回 Cloud Datastore。

    由於這類查詢只傳回部分填入的結果,因此不能再將結果寫回 Cloud Datastore。

投影與多值屬性

投影有多個值的屬性時,並不會填入該屬性的所有值,而是每找到一組與查詢相符且不重複的投影值,就傳回一個獨立實體。例如,假設有一個 Foo 種類的實體包含兩個多值屬性 AB

entity = Foo(A=[1, 1, 2, 3], B=['x', 'y', 'x'])

那麼投影查詢

SELECT A, B FROM Foo WHERE A < 3

會傳回四個包含下列組合值的實體:

A = 1B = 'x'
A = 1B = 'y'
A = 2B = 'x'
A = 2B = 'y'

請注意,如果實體的某個多值屬性沒有值,則不會在索引中加入項目,也不會從包含該屬性的投影查詢傳回該實體的結果。

投影索引

投影查詢要求必須將投影指定的屬性全數納入 Cloud Datastore 索引。App Engine 部署伺服器會在索引設定檔 index.yaml 中自動產生需要的索引;這是使用您的應用程式上傳的檔案。

如要盡可能減少必要的索引數目,其中一種方法是一致投影相同的屬性 (即使並非每一次都需要其中所有屬性)。例如,以下查詢需要兩個獨立的索引:

SELECT A, B FROM Kind
SELECT A, B, C FROM Kind

不過,若您一律投影 ABC 等屬性 (即使是在不需要 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

「不會」變更必要的索引,因為現有查詢中已包含投影屬性 AB

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

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

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