duansen6750 2016-04-15 17:05
浏览 43
已采纳

无法在Golang中使用datastore.GetAll获得结果

I have two functions: one which writes entities to datastore and the other is suppose to retrieve them. When I use datastore.GetAll() function in my retrieval it returns no results. I do have a test that verifies that the writing seems to be working correctly. Any ideas as to why retrieval isn't working?

Here is the application code:

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
}

Here is the test code:

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)
    }
}
  • 写回答

1条回答 默认 最新

  • douzi115522 2016-04-15 17:39
    关注

    datastore.GetAll() doesn't return result to you because with that query eventual consistency applies. The SDK simulates the eventual consistency and doesn't return you the newly saved entities immediately.

    But in your TestCreateUser() method when you use datastore.Get(), that will return you the entity even if it was newly ("just now") saved, because it's a lookup by a key, and they are strongly consistent.

    What happens behind the scenes is that when you call datastore.Put(), the entity data (values of properties) is saved and its key is indexed, then datastore.Put() returns, and indices of other properties and composite indices are updated asynchronously "in the background". So if you try to execute a query that uses an index to find/list entities (you were querying by the Email property), that query will not see (will not include) new entities until they are properly indexed. When you do a datastore.Get(), that loads the entity by its key and not by other (non-key property or composite) indices, so getting an entity by key will see the new entity "immediately" (after datastore.Put() has returned).

    If you want to test this in local environment, you may provide StronglyConsistentDatastore option when creating the instance that will be used to create a new context, like this:

    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)
    

    Also note that if you use a sleep (e.g. time.Sleep(time.Millisecond * 500)), datastore.GetAll() will also return the new entity, but the above option is the proper way to test this.

    There are numerous similar questions (+answers), read them for more details:

    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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 求解vmware的网络模式问题 别拿AI回答
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码
  • ¥15 关于资源监视工具的e-care有知道的嘛
  • ¥35 MIMO天线稀疏阵列排布问题
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?