查詢限制

本頁面涵蓋在 Google App Engine 查詢 Datastore 的相關限制。下方列出您在針對 Datastore 進行開發時會遇到的一般限制。

系統會忽略查詢中缺少屬性名稱的實體

相同種類的實體不一定具備相同的屬性。針對每一個在查詢篩選器和排序順序中指定的屬性,實體都必須擁有一個值 (可能是空值),才有資格做為查詢結果。否則用於執行查詢的索引就會忽略該實體,查詢結果自然就不會包含該實體。

篩選未建立索引的屬性不會傳回任何結果

查詢找不到未建立索引的屬性值,也無法排序這類屬性。請參閱資料儲存庫索引頁面,瞭解未建立索引的屬性相關詳細說明。

不等式篩選器最多限用於一個屬性

為避免必須掃描整個索引,查詢機制會要求一個查詢的所有可能結果在索引中彼此相鄰。為符合這項限制,單一查詢不能將不等式比較運算 (<<=>>=!=) 用於所有篩選器中超過一個屬性。例如,以下查詢的兩個不等式篩選器會套用至相同屬性,因此查詢有效:

SELECT * FROM Person WHERE birth_year >= :min_birth_year
                       AND birth_year <= :max_birth_year

但是,以下查詢「無效」,原因在於其對兩個不同的屬性使用不等式篩選器:

SELECT * FROM Person WHERE birth_year >= :max_birth_year
                       AND height <= :max_height          # ERROR

請注意,一項查詢「可以」結合用於查詢不同屬性的等式 (=) 篩選器,以及用於查詢單一屬性的一或多個不等式篩選器。因此,以下「是」有效查詢:

SELECT * FROM Person WHERE last_name = :target_last_name AND city = :target_city AND birth_year >= :min_birth_year AND birth_year <= :max_birth_year

若不指定排序順序,就不會定義查詢結果順序

查詢若不指定排序順序,會依擷取順序傳回結果。隨著 Datastore 實作的發展 (或是應用程式的索引變更時),這個順序可能會改變。因此,若您的應用程式要求按照特定順序排列查詢結果,請務必在查詢中清楚指定該排序順序。

如果有等式篩選器,則屬性的排序順序將被忽略

如果查詢有特定屬性的等式篩選器,系統就會忽略針對這個屬性指定的任何排序順序。因為屬性的所有結果值均相同且不需進一步排序,在不需要針對單值屬性進行多餘處理的狀況下,可以輕鬆地達到最佳化。但如果是多值屬性,除了比對等式篩選條件得出的值之外,可能還包含其他值。由於這樣的使用情形並不多見,套用排序順序需耗費較多成本,而且需要建立其他索引,因此即使是多值屬性,Datastore 查詢規劃工具也會直接忽略排序順序。這可能會導致查詢結果以異於排序隱含的順序傳回。

必須先排序不等式篩選器中使用的屬性

如要擷取所有與不等式篩選器相符的結果,查詢會掃描索引中符合篩選器的第一列,接著再繼續掃描,直到發現不一致的列為止。連續列必須按照不等式篩選器中使用的屬性排序,排列在任何其他屬性之前,才能包含完整的結果集。因此,如果查詢指定一或多個不等式篩選器及一或多個排序順序,第一個排序順序必須參照不等式篩選器中具名的相同屬性。以下查詢有效:

SELECT * FROM Person WHERE birth_year >= :min_birth_year ORDER BY birth_year, last_name

以下查詢「無效」,因為沒有按照不等式篩選器中所用的屬性排序:

SELECT * FROM Person WHERE birth_year >= :min_birth_year ORDER BY last_name # ERROR

同理可證,以下查詢也無效,原因在於不等式篩選器所用的屬性並不是排序後的第一個屬性:

SELECT * FROM Person WHERE birth_year >= :min_birth_year
                     ORDER BY last_name, birth_year       # ERROR

多值屬性有可能會出現令人意外的結果

由於實體建立索引的方式所致,如果實體的相同屬性具有多個值,有時候可能會與查詢篩選器及排序順序發生非預期的交互作用,因而出現令人意外的結果。

若查詢包含指定屬性的多個不等式篩選條件,除非屬性至少有一個屬性值符合「所有」篩選條件,否則實體不會與查詢一致。舉例來說,如果屬於 Widget 種類的實體包含 12 這兩個 x 屬性值,就「無法」與查詢相符:

SELECT * FROM Widget WHERE x > 1
                       AND x < 2

每個實體的 x 值各自符合其中一個篩選條件,但沒有一個值同時符合兩個篩選條件。請注意,等式篩選條件不適用這項原則。舉例來說,以上實體就「會」符合以下查詢條件

SELECT * FROM Widget WHERE x = 1
                       AND x = 2

即使實體沒有任何一個 x 值同時符合兩種篩選條件也無妨。

不等於 (!=) 運算子的用途在於進行「值不是」測試。舉例來說,以下查詢

SELECT * FROM Widget WHERE x != 1

符合 x 值不是 1 的任何 Widget 實體。

多值屬性的排序順序也一樣不尋常。由於這類屬性會在每個不重複值的索引中出現一次,因此,索引中出現的第一個值決定實體的排序順序:

  • 如果按遞增順序排序查詢結果,排序時就會使用該屬性的最小值。
  • 如果按遞減順序排序結果,排序時就會使用最大值。
  • 其他值和值的數量都不會影響排序順序。

這種情況會出現不尋常的結果:按遞增順序「和」遞減順序排列時,含有 19 屬性值的實體都會排在含有 4567 屬性值的實體之前。

交易內部查詢必須包含祖系篩選器

Datastore 交易只能使用屬於同一個實體群組 (具備共同祖系) 的實體。為維護這項限制,在交易中執行的所有查詢都須包含一個祖系篩選器,且該篩選器會如同交易中的其他作業,在相同的實體群組中指定祖系。