2016-04-15 104 views
1

我有兩個函數:一個是將實體寫入數據存儲區,另一個是假設檢索它們。當我在檢索中使用datastore.GetAll()函數時,它不返回任何結果。我有一個測試,驗證寫作似乎正常工作。任何關於爲什麼檢索不起作用的想法?golang中的datastore.GetAll沒有得到結果

這裏是應用程序代碼:

package tracker 

import (
    "fmt" 

    "appengine" 
    "appengine/datastore" 
) 

type User struct { 
    Email string 
} 

func createUser(ctx appengine.Context, email string) (*datastore.Key, error) { 
    u := &User{ 
     Email: email, 
     } 
    incompleteKey := datastore.NewIncompleteKey(ctx, "User", nil) 
    key, err := datastore.Put(ctx, incompleteKey, u) 
    if err != nil { 
     return key, err 
    } 

    return key, nil 
} 

func getUser(ctx appengine.Context, email string) (u *User, e error) { 
    users := []User{} 
    q := datastore.NewQuery("User").Filter("Email", email) 
    keys, err := q.GetAll(ctx, &users) 
    if err != nil { 
     return nil, err 
    } 
    fmt.Printf("KEYS: %v", keys) 
    return &users[0], nil 
} 

下面是測試代碼:

package tracker 

import (
    "fmt" 
    "testing" 

    "appengine/datastore" 
    "appengine/aetest" 
) 

// This test is passing. 
func TestCreateUser(t *testing.T) { 
    ctx, err := aetest.NewContext(nil) 
    if err != nil { 
     t.Fatal(err) 
    } 
    defer ctx.Close() 

    email := "[email protected]" 
    newKey, err := createUser(ctx, email) 
    if err != nil { 
     t.Errorf("Failed to create a new user: %v", err) 
    } 

    u := User{} 
    datastore.Get(ctx, newKey, &u) 

    if u.Email != email { 
     t.Errorf("Expected email to be %s, found %v.", email, u.Email) 
    } 
} 

func TestGetUser(t *testing.T) { 
    ctx, err := aetest.NewContext(nil) 
    if err != nil { 
     t.Fatal(err) 
    } 
    defer ctx.Close() 

    email := "[email protected]" 
    newKey, err := createUser(ctx, email) 
    fmt.Printf("key, %v; ", newKey) 
    u, err := getUser(ctx, newKey) 
    fmt.Printf("user, %v; error: %s", u, err) 

    if u.Email != email { 
     t.Error("Expected email to be %s, found %v.", email, u.Email) 
    } 
} 

回答

5

datastore.GetAll()不返回結果給你,因爲與查詢最終一致性適用。 SDK模擬最終的一致性,不會立即向您返回新保存的實體。

但在你TestCreateUser()方法,當您使用datastore.Get(),將返回保存即使是新(「剛纔」)的實體,因爲它是一個查找的關鍵,他們是強一致

幕後發生的事情是,當您撥打datastore.Put()時,保存了實體數據(屬性值)並對其鍵進行了索引,然後返回,並且其他屬性和組合索引的索引被異步更新。背景」。因此,如果您嘗試執行使用索引來查找/列出實體的查詢(您正在查詢Email屬性),那麼該查詢將不會看到(不會包含)新實體,直到它們被正確編入索引。當您執行datastore.Get()時,它會通過其密鑰加載實體,而不是通過其他(非密鑰屬性或複合)索引加載實體,因此通過密鑰獲取實體將立即看到新實體(在返回datastore.Put()之後)。

如果你想在本地環境中測試這一點,你可以創建將用於創建新的上下文實例時提供StronglyConsistentDatastore選項,如:

inst, err := aetest.NewInstance(&aetest.Options{StronglyConsistentDatastore: true}) 
if err != nil { 
    t.Fatalf("Failed to create instance: %v", err) 
} 
defer inst.Close() 

req, err := inst.NewRequest("GET", "/", nil) 
if err != nil { 
    t.Fatalf("Failed to create req: %v", err) 
} 
ctx := appengine.NewContext(req) 

還要注意的是,如果你使用睡眠(例如time.Sleep(time.Millisecond * 500)),datastore.GetAll()也會返回新的實體,但上面的選項是測試這個的正確方法。

有許多類似的問題(+答案),閱讀更多細節:

Google App Engine Datastore - Testing Queries fails

How to filter a GAE query?

Google app engine datastore query with cursor won't iterate all items

+0

感謝那些工作就像一個魅力! – katkinson

+1

@katkinson由於它的工作原因,要做的恰當事情是通過點擊左側旁邊的複選標記來將答案標記爲已接受。 http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work這讓未來的讀者知道答案可以解決問題。 – sberry