2016-04-15 5 views
1

Ich habe zwei Funktionen: eine, die Entitäten in den Datenspeicher schreibt und der andere soll sie abrufen. Wenn ich datastore.GetAll() Funktion in meinem Abruf verwende, gibt es keine Ergebnisse zurück. Ich habe einen Test, der bestätigt, dass das Schreiben korrekt zu funktionieren scheint. Irgendwelche Ideen, warum das Retrieval nicht funktioniert? HierKeine Ergebnisse mit Datastore.GetAll in Golang

ist der Anwendungscode:

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 
} 

Hier ist der Testcode:

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) 
    } 
} 

Antwort

5

datastore.GetAll() nicht Ergebnis an Sie zurück, weil mit dieser Abfrage Eventual Consistency gilt. Das SDK simuliert die eventuelle Konsistenz und gibt die neu gespeicherten Entitäten nicht sofort zurück.

Aber in Ihrer TestCreateUser() Methode, wenn Sie datastore.Get() verwenden, die Sie an dem Unternehmen zurück, auch wenn es neu („gerade jetzt“) gespeichert war, weil es von einem Schlüssel ein Lookup ist, und sie sind stark konsistent.

Was hinter den Kulissen passiert, ist, dass, wenn Sie datastore.Put() aufrufen, wird die Objektdaten (Werte von Eigenschaften) gespeichert und dessen Schlüssel indiziert ist, dann datastore.Put() Renditen und Indizes anderer Eigenschaften und Composite-Indizes werden aktualisiert asynchron „in der Hintergrund". Wenn Sie also versuchen, eine Abfrage auszuführen, die einen Index zum Suchen/Auflisten von Entitäten verwendet (Sie haben die Email-Eigenschaft abgefragt), werden neue Entitäten erst dann wieder angezeigt, wenn sie ordnungsgemäß indiziert sind. Wenn Sie eine datastore.Get() tun, lädt die Entität nach ihrem Schlüssel und nicht nach anderen (Nicht-Schlüsseleigenschaft- oder zusammengesetzten) Indizes. Wenn Sie also eine Entität per Schlüssel erhalten, wird die neue Entität "sofort" angezeigt (nachdem datastore.Put() zurückgegeben wurde).

Wenn Sie dies in der lokalen Umgebung testen möchten, können Sie StronglyConsistentDatastore Option zur Verfügung stellen, wenn die Instanz zu schaffen, die verwendet wird, um einen neuen Kontext zu schaffen, wie folgt aus:

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) 

Beachten Sie auch, dass, wenn Sie eine verwenden Schlaf (z. B. time.Sleep(time.Millisecond * 500)), datastore.GetAll() wird auch die neue Entität zurückgeben, aber die obige Option ist der richtige Weg, dies zu testen.

Es gibt zahlreiche ähnliche Fragen (+ Antworten), lesen Sie für weitere Informationen:

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

Dank, die sich wie ein Charme! – katkinson

+1

@katkinson Da es funktioniert hat, ist es angemessen, die Antwort als akzeptiert zu markieren, indem Sie auf das Häkchen daneben links klicken. http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work Dies lässt zukünftige Leser wissen, dass die Antwort das Problem gelöst hat. – sberry