【问题标题】:Not getting results with datastore.GetAll in golang在 golang 中使用 datastore.GetAll 没有得到结果
【发布时间】:2016-08-07 18:32:54
【问题描述】:

我有两个功能:一个将实体写入数据存储区,另一个用于检索它们。当我在检索中使用 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 := "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)
    }
}

【问题讨论】:

    标签: google-app-engine testing go google-cloud-datastore


    【解决方案1】:

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

    但是在您的TestCreateUser() 方法中,当您使用datastore.Get() 时,即使它是新(“刚刚”)保存的实体,它也会返回给您,因为它是通过键查找,并且它们是 强烈一致

    幕后发生的事情是当你调用datastore.Put()时,实体数据(属性的值)被保存并且它的键被索引,然后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

    【讨论】:

    • @katkinson 因为它有效,所以适当的做法是通过单击左侧旁边的复选标记将答案标记为已接受。 meta.stackexchange.com/questions/5234/…这让未来的读者知道答案解决了问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多