Datastore 查詢

Datastore 的「查詢」會自 Cloud Datastore 中擷取滿足一組特定條件的「實體」

典型的查詢包含以下幾項:

執行查詢時,查詢會擷取屬於指定種類且符合所有指定篩選器的所有實體,並按照指定順序排序。查詢會以唯讀方式執行。

本頁說明在 App Engine 中,用於從 Cloud Datastore 擷取資料的查詢結構和種類。

篩選器

查詢的「篩選器」會對待擷取實體的屬性金鑰祖系設定限制。

屬性篩選器

「屬性篩選器」指定

  • 屬性名稱
  • 比較運算子
  • 屬性值
例如:

q := datastore.NewQuery("Person").Filter("Height <=", maxHeight)

屬性值必須由應用程式提供,不能參照其他屬性或以其他屬性計算得出。如果實體具有指定名稱的屬性,且屬性值與篩選器中指定的值比較,符合比較運算子描述的方式,則該實體符合篩選器的條件。

比較運算子可以為以下任何一種:

運算子 含義
= 等於
< 小於
<= 小於或等於
> 大於
>= 大於或等於

金鑰篩選器

如要篩選實體金鑰的值,請使用特殊屬性 __key__

q := datastore.NewQuery("Person").Filter("__key__ >", lastSeenKey)

在比較不等式時,金鑰會依序按下列條件進行排序:

  1. 祖系路徑
  2. 實體種類
  3. ID (金鑰名稱或數字 ID)

祖系路徑的元素會以類似的方式進行比較:先比較種類 (字串),再比較金鑰名稱或數字 ID。種類和金鑰名稱都是字串,且會按照位元組值排序;數字 ID 為整數,會按照數值順序排序。若父項和種類相同的實體混用金鑰名稱和數字 ID,則會先列出採用數字 ID 的實體,再列出採用金鑰名稱的實體。

金鑰查詢像屬性查詢一樣會使用索引,而且在相同情況下都需要自訂索引,只有少數例外狀況:不等式篩選器或金鑰遞增排序不需使用自訂索引,但金鑰遞減排序則必須使用。與所有查詢相同,測試需要自訂索引的查詢時,開發網頁伺服器會在索引設定檔中建立適當的項目。

祖系篩選條件

您可以將 Datastore 查詢篩選為指定的祖系,傳回的結果就會只包含來自指定祖系的實體:

q := datastore.NewQuery("Person").Ancestor(ancestorKey)

特殊查詢類型

請特別注意下列幾種特定查詢類型:

無種類查詢

沒有種類且沒有祖系篩選器的查詢,會從 Datastore 中擷取應用程式的所有實體,包括其他 App Engine 功能建立及代管的實體,例如統計資料實體Blobstore 中繼資料實體 (如有)。這類「無種類的查詢」不能包含屬性值篩選條件或排序順序。不過,這類查詢可以指定 __key__ 屬性名稱,以利按實體金鑰進行篩選。

q := datastore.NewQuery("").Filter("__key__ >", lastSeenKey)

祖系查詢

查詢若採用祖系篩選條件,會將結果限制在指定實體及其子系:

// Create two Photo entities in the datastore with a Person as their ancestor.
tomKey := datastore.NewKey(ctx, "Person", "Tom", 0, nil)

wPhoto := Photo{URL: "http://example.com/some/path/to/wedding_photo.jpg"}
wKey := datastore.NewKey(ctx, "Photo", "", 0, tomKey)
_, err := datastore.Put(ctx, wKey, wPhoto)
// check err

bPhoto := Photo{URL: "http://example.com/some/path/to/baby_photo.jpg"}
bKey := datastore.NewKey(ctx, "Photo", "", 0, tomKey)
_, err = datastore.Put(ctx, bKey, bPhoto)
// check err

// Now fetch all Photos that have tomKey as an ancestor.
// This will populate the photos slice with wPhoto and bPhoto.
q := datastore.NewQuery("Photo").Ancestor(tomKey)
var photos []Photo
_, err = q.GetAll(ctx, &photos)
// check err
// do something with photos

無種類祖系查詢

無論種類為何,包含祖系篩選器的無種類查詢將會擷取指定的祖系及其所有子系。這類查詢不需要自訂索引。如同無種類查詢,這類查詢不能包含屬性值篩選條件或排序順序,但是可以篩選實體金鑰:

q := datastore.NewQuery("").Ancestor(ancestorKey).Filter("__key__ >", lastSeenKey)

以下範例說明如何擷取指定祖系的所有實體:

tomKey := datastore.NewKey(ctx, "Person", "Tom", 0, nil)

weddingPhoto := &Photo{URL: "http://example.com/some/path/to/wedding_photo.jpg"}
_, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Photo", tomKey), weddingPhoto)

weddingVideo := &Video{URL: "http://example.com/some/path/to/wedding_video.avi"}
_, err = datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Video", tomKey), weddingVideo)

// The following query returns both weddingPhoto and weddingVideo,
// even though they are of different entity kinds.
q := datastore.NewQuery("").Ancestor(tomKey)
t := q.Run(ctx)
for {
	var x interface{}
	_, err := t.Next(&x)
	if err == datastore.Done {
		break
	}
	if err != nil {
		log.Errorf(ctx, "fetching next Photo/Video: %v", err)
		break
	}
	// Do something (e.g. switch on types)
	doSomething(x)
}

僅限金鑰查詢

「僅限金鑰查詢」僅傳回結果實體的金鑰而非實體本身,與擷取整個實體相比,延遲及成本都較低。

q := datastore.NewQuery("Person").KeysOnly()

一般查詢會擷取的實體可能多於您實際需要的實體,因此,先進行僅限金鑰查詢再從查詢結果中擷取實體子集通常較符合經濟效益。

請注意,僅限金鑰查詢有可能會傳回 1000 以上的結果,但 GetAll 一次只能擷取 1000 個金鑰,若在出現筆數較多的結果時呼叫,可能會出現錯誤並失敗。因此,建議您新增 1000 個金鑰的查詢限制。

投影查詢

有時候,您只需要用到查詢結果中幾項特定屬性的值。在這種情況下,使用「投影查詢」就能只擷取實際所需屬性。相較於擷取整個實體,這個方式的延遲情況較少,費用也較為低廉。詳情請參閱投影查詢頁面。

排序順序

查詢的「排序順序」指定

  • 屬性名稱
  • 排序方向 (遞增或遞減)

在 Go 中,遞減排序的順序會由屬性名稱前面的連字符號 (-) 表示;省略連字號則表示指定遞減排序 (預設排序)。例如:

// Order alphabetically by last name:
q := datastore.NewQuery("Person").Order("LastName")

// Order by height, tallest to shortest:
q = datastore.NewQuery("Person").Order("-Height")

如果查詢包含多個排序順序,他們將按照指定的順序排序。以下的範例首先將「last name」遞增排列,並將「height」遞減排列。

q := datastore.NewQuery("Person").Order("LastName").Order("-Height")

若未指定排序順序,則會按照從 Cloud DataStore 擷取的順序傳回結果。

附註:由於 Cloud Datastore 執行查詢的方式所致,如果查詢指定以不等式篩選某個屬性並對其他屬性進行排序,則在不等式篩選中使用的屬性必須排序在其他屬性之前。

索引

每個 Datastore 查詢會使用一或多個「索引」來計算其結果,這些索引包含順序由索引屬性及實體祖系 (選用) 指定的實體金鑰。索引會逐步更新並反映應用程式針對實體進行的任何更改,以利提供所有查詢的正確結果,不需再進一步運算。

App Engine 會針對實體的每個屬性預先定義簡單的索引。在名為 index.yaml索引設定檔中,您可以為 App Engine 應用程式進一步定義自訂索引。開發伺服器遇到無法使用現有索引執行的查詢時,即會自動在這個檔案中新增建議。在上傳應用程式之前,您可以透過編輯檔案的方式來手動調整索引。

查詢介面範例

Go Datastore API 提供用於準備及執行查詢的查詢類型

type Person struct {
	FirstName string
	LastName  string
	City      string
	BirthYear int
	Height    int
}

func handle(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)

	// The Query type and its methods are used to construct a query.
	q := datastore.NewQuery("Person").
		Filter("LastName =", "Smith").
		Filter("Height <=", maxHeight).
		Order("-Height")

	// To retrieve the results,
	// you must execute the Query using its GetAll or Run methods.
	var people []Person
	if _, err := q.GetAll(ctx, &people); err != nil {
		// Handle error.
	}
	// ...
}

後續步驟

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

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

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