如何过滤GAE查询? [英] How to filter a GAE query?

查看:162
本文介绍了如何过滤GAE查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图保存两条记录,然后获得第二条记录。问题是过滤器似乎不起作用。虽然我按名称过滤(Andrew W),但我总是得到Joe Citizen。该计数器还表示2个记录,当它应该只是一个。这让我发疯。请参阅下面的完整代码。
结果打印 counter 2 e2 {Joe CitizenManager2015-03-24 09:08:58.363929 +0000 UTC}

 包主
导入(
fmt
时间
net / http

google.golang.org/appengine
google.golang.org/appengine/datastore



类型Employee结构{
名称字符串
角色字符串
HireDate time.Time
帐户字符串
}
func init(){

http.HandleFunc(/,句柄)
}
func句柄(w http.ResponseWriter,r * http.Request){
c:= appengine.NewContext(r )

e1:=员工{
名称:Joe Citizen,
角色:经理
HireDate:time.Now(),$ b $ (c,datastore.NewKey(c,employee,,0,nil),& e1)
if err! =无{
http.Error(w,err.Error(),http.StatusInternalServerError)
panic(err)
return

e1.Name =Andrew W

_,err = datastore.Put(c,datastore.NewKey(c,employee, ),0,nil),& e1)
if err!= nil {
http.Error(w,err.Error(),http.StatusInternalServerError)
panic(err)
return


var e2 Employee
q:= datastore.NewQuery(employee)
q.Filter(Name =,Andrew W)
cnt,err:= q.Count(c)
if err!= nil {
http.Error(w,err.Error(),http.StatusInternalServerError)
恐慌(错误)
返回
}
for t:= q.Run(c); ; {
if _,err:= t.Next(& e2); err!= nil {
http.Error(w,err.Error(),http.StatusInternalServerError)
panic(err)
return
}
break

fmt.Fprintf(w,counter%v e2%q,cnt,e2)
}


解决方案

第一个问题是这样的:

  q:= datastore.NewQuery(employee)
q.Filter(Name =,Andrew W)

Query.Filter() 返回包含您指定的过滤器的衍生查询。您必须存储返回值并继续使用它:

  q:= datastore.NewQuery(employee)
q = q.Filter(Name =,Andrew W)

或者只是一行:

  q:= datastore.NewQuery(employee)。Filter(Name =,Andrew W)$ b注意:如果没有这个,你执行的查询将没有过滤器,因此会返回所有先前保存的实体类型employee,其中Joe Citizen可能是您打印的第一个。



对于第一次运行,您很可能会看到0个结果。请注意,由于您不使用祖先查询,因此最终一致性适用。开发SDK以最终一致性模拟高复制数据存储,因此在 Put()操作之后的查询将不会看到结果。



如果您在继续查询之前放入一个小的 time.Sleep(),您将看到您期望的结果:

  time.Sleep(time.Second)

var e2 Employee
q:= datastore.NewQuery(employee ).Filter(Name =,Andrew W)
//其余代码...

另请注意,通过在SDK中运行代码,您可以通过创建上下文来模拟强一致性

  c,err:= aetest.NewContext(&aetest.Options {StronglyConsistentDatastore:true})

但是,当然这仅用于测试目的,您不能在生产中执行此操作。



如果您想获得强烈一致的结果,请指定创建密钥时的祖先密钥,an d使用祖先查询。祖先密钥只有在需要强烈一致的结果时才需要。如果延迟几秒钟就可以显示结果,那么您不必这样做。还要注意,祖先密钥不一定是现有实体的关键,它只是语义。您可以创建任何虚构键。对同一个实体组使用相​​同的(虚构的)密钥将会把它们放到同一个实体组中,并且对这个组的祖先查询将保持一致。通常情况下,祖先密钥是一个现有的密钥,通常来自当前的用户或帐户,因为它可以很容易地创建/计算,并保存/存储一些额外的信息,但是如上所述,它不一定是。


I'm trying to save two records and then get the 2nd one. The issue is that the filter doesn't seem to work. Although I filter by Name ("Andrew W") I always get "Joe Citizen". The counter also indicates 2 records when it should be just one. This drives me crazy. See the full code below. The result prints counter 2 e2 {"Joe Citizen" "Manager" "2015-03-24 09:08:58.363929 +0000 UTC" ""}

package main
import (
    "fmt"
    "time"
    "net/http"

    "google.golang.org/appengine"
    "google.golang.org/appengine/datastore"
)


type Employee struct {
    Name     string
    Role     string
    HireDate time.Time
    Account  string
}
func init(){

    http.HandleFunc("/", handle)
}
func handle(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)

    e1 := Employee{
        Name:     "Joe Citizen",
        Role:     "Manager",
        HireDate: time.Now(),
    }

    _, err := datastore.Put(c, datastore.NewKey(c, "employee", "", 0, nil), &e1)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    panic(err)
        return
    }
    e1.Name = "Andrew W"

    _, err = datastore.Put(c, datastore.NewKey(c, "employee", "", 0, nil), &e1)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    panic(err)
        return
    }

    var e2 Employee
    q :=  datastore.NewQuery("employee")
    q.Filter("Name =", "Andrew W")
    cnt, err  := q.Count(c)
    if err !=nil{
        http.Error(w, err.Error(), http.StatusInternalServerError)
        panic(err)
        return
    }
    for t := q.Run(c); ; {  
        if _, err := t.Next(&e2); err != nil {
             http.Error(w, err.Error(), http.StatusInternalServerError)
            panic(err)
            return
        }
        break
    }   
    fmt.Fprintf(w, "counter %v e2 %q", cnt, e2)
}

解决方案

The (first) problem is this:

q :=  datastore.NewQuery("employee")
q.Filter("Name =", "Andrew W")

Query.Filter() returns a derivative query with the filter you specified included. You have to store the return value and use it ongoing:

q := datastore.NewQuery("employee")
q = q.Filter("Name =", "Andrew W")

Or just one line:

q := datastore.NewQuery("employee").Filter("Name =", "Andrew W")

Note: Without this the query you execute would have no filters and therefore would return all previously saved entities of the kind "employee", where "Joe Citizen" might be the first one which you see printed.

For the first run you will most likely see 0 results. Note that since you don't use Ancestor queries, eventual consistency applies. The development SDK simulates the High replication datastore with its eventual consistency, and therefore the query following the Put() operations will not see the results.

If you put a small time.Sleep() before proceeding with the query, you will see the results you expect:

time.Sleep(time.Second)

var e2 Employee
q := datastore.NewQuery("employee").Filter("Name=", "Andrew W")
// Rest of your code...

Also note that running your code in the SDK you can simulate strong consistency by creating your context like this:

c, err := aetest.NewContext(&aetest.Options{StronglyConsistentDatastore: true})

But of course this is for testing purposes only, you can't do this in production.

If you want strongly consistent results, specify an ancestor key when creating the key, and use ancestor queries. An ancestor key is only required if you want strongly consistent results. If you're fine with a few seconds delay for the results to show up, you don't have to. Also note that the ancestor key does not have to be the key of an existing entity, it's just semantics. You can create any fictional key. Using the same (fictional) key to multiple entities will put them into the same entity group and ancestor queries on this group will be strongly consistent.

Often the ancestor key is an existing key, usually derived from the current user or account, because that can be created/computed easily and it holds/stores some additional information, but as noted above, it doesn't have to be.

这篇关于如何过滤GAE查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆