在golang中没有得到datastore.GetAll的结果

kat*_*son 1 testing google-app-engine go google-cloud-datastore

我有两个函数:一个将实体写入数据存储区,另一个函数用于检索它们.当我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
}
Run Code Online (Sandbox Code Playgroud)

这是测试代码:

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 := "testing@testing.go"
    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 := "testing@testing.go"
    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)
    }
}
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 5

datastore.GetAll()不会将结果返回给您,因为该查询适用最终一致性.SDK模拟最终的一致性,并不会立即返回新保存的实体.

但是在TestCreateUser()你使用的方法中datastore.Get(),即使它是新的("刚刚")保存,也会返回实体,因为它是按键查找,并且它们非常一致.

幕后发生的事情是,当您调用时datastore.Put(),保存实体数据(属性值)并对其键进行索引,然后datastore.Put()返回,其他属性和复合索引的索引将在"后台"异步更新.因此,如果您尝试执行使用索引查找/列出实体的查询(您正在通过Email属性进行查询),则该查询将不会看到(将不包括)新实体,直到它们被正确编入索引.当你执行a时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)
Run Code Online (Sandbox Code Playgroud)

另请注意,如果您使用sleep(例如time.Sleep(time.Millisecond * 500)),datastore.GetAll()也会返回新实体,但上述选项是测试此方法的正确方法.

有许多类似的问题(+答案),请阅读它们以获取更多详细信息:

Google App Engine数据存储区 - 测试查询失败

如何过滤GAE查询?

使用游标的Google应用引擎数据存储区查询不会迭代所有项目