在Google App Engine Datastore中使用Golang进行“IN Array”查询。

huangapple go评论76阅读模式
英文:

Doing a "IN Array" query on google app engine datastore with golang

问题

在Datastore中,可以使用ids []int64进行查询吗?我尝试了以下方法,但都没有成功。

  1. 报错

     q := datastore.NewQuery("Category").Filter("Id IN", ids)
    
  2. 只能获取Datastore中的所有类别

     for _, id := range ids {
         q.Filter("Id =", id)
     }
    

在icza的回答之后

var keys []*datastore.Key

for _, id := range ids {
    keys = append(keys, datastore.NewKey(c, "Category", "", id, nil))
}

categories := make([]Category, len(keys))
err := datastore.GetMulti(c, keys, categories)
if err != nil {
    return nil, err
}
英文:

Is there a way to do a query with ids []int64 on datastore? I've tried the following with no avail.

  1. Errors out

     q := datastore.NewQuery("Category").Filter("Id IN", ids)
    
  2. Just gets me all the the categories in the datastore

     for _, id := range ids {
         q.Filter("Id =", id)
     }
    

After icza's answer

var keys []*datastore.Key

for _, id := range ids {
	keys = append(keys, datastore.NewKey(c, "Category", "", id, nil))
}

categories := make([]Category, len(keys))
err := datastore.GetMulti(c, keys, categories)
if err != nil {
	return nil, err
}

答案1

得分: 5

通常情况下,Datastore 不支持使用 "IN" 过滤器。Query.Filter() 的文档列出了允许的操作符:

">", "<", ">=", "<=", 或 "="

你可以为要过滤的数组中的每个元素执行一个单独的查询。如果元素是连续范围的,你可以用 id>=minid<=max 替换 "IN"。例如:

ids := []int64{1,2,3,4}
q := datastore.NewQuery("Category").Filter("Id>=", 1).Filter("Id<=", 4)

另外请注意,虽然一般情况下不支持 "IN",但如果属性本身是实体键,你可以使用 datastore.GetMulti() 函数来获取由键数组指定的实体列表:

func GetMulti(c appengine.Context, key []*Key, dst interface{}) error

注意:

你的第二次尝试返回所有实体,因为你在查询上调用了 Filter(),但你没有存储返回值,所以最终执行的查询将没有任何过滤器。Query.Filter() 返回一个包含刚刚指定的过滤器的派生查询,你必须继续使用返回的 Query。所以应该是:

q = q.Filter("Id=", id)

但即使这样也不会起作用:如果指定了多个过滤器,它们将以逻辑 AND 连接,所以很可能会得到 0 个结果,因为我怀疑没有一个类别的 Id 是一个包含你想要过滤的所有 id 的列表。

英文:

Generally &quot;IN&quot; filters are not supported by the Datastore. The documentation of Query.Filter() lists the allowed operators:

&quot;&gt;&quot;, &quot;&lt;&quot;, &quot;&gt;=&quot;, &quot;&lt;=&quot;, or &quot;=&quot;

What you can do is execute a separate query for each of the elements in the array you want to filter by. Also if the elements are in a continous range, you can substitute the IN with id&gt;=min and id&lt;=max. E.g.:

ids := []int64{1,2,3,4}
q := datastore.NewQuery(&quot;Category&quot;).Filter(&quot;Id&gt;=&quot;, 1).Filter(&quot;Id&lt;=&quot;, 4)

Also note that while the IN is not supported in general, if the property is the entity key itself, you can get a list of entities specified by an array of their keys using the datastore.GetMulti() function:

func GetMulti(c appengine.Context, key []*Key, dst interface{}) error

Note:

Your 2nd attempt returns all entities because you call Filter() on your query, but you don't store the return value, so the query you end up executing will have no filters at all. Query.Filter() returns a derivative query which contains the filter you just specified, you have to use the returned Query ongoing. So it should be:

q = q.Filter(&quot;Id=&quot;, id)

But even this won't work either: if multiple filters are specified, they will be in logical AND connection so it will most likely give you 0 results as I suspect no category will exists where Id is a list and which would contain all the ids you want to filter by.

huangapple
  • 本文由 发表于 2015年3月23日 10:39:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/29202516.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定