我正在开发一个多租户应用程序,我需要从KIND和From Particular Namespace查询特定用户。
我可以从默认的Namespace获取值。我在这里使用的包是"google.golang.org/appengine/datastore"
q := datastore.NewQuery(ENTITYNAME).Filter("Name =", ed.Expense.Name)
var expenses []ExpenseEntiry
return q.GetAll(ed.Ctx, &expenses)
答案 0 :(得分:2)
命名空间值不是查询的一部分(它不是查询的属性)。命名空间来自您在执行查询时传递的上下文,例如到Query.GetAll()
。
如果您有上下文(在将其传递给q.GetAll()
时执行),则可以使用appengine.Namespace()
函数创建具有给定命名空间的派生上下文。
例如:
ctx2, err := appengine.Namespace(ed.Ctx, "mynamespace")
// check err
并使用此新上下文传递给Query.GetAll()
:
return q.GetAll(ctx2, &expenses)
您很少需要使用不同的命名空间创建新的上下文,ed.Ctx
应该已经是具有正确命名空间的上下文。因此,当您创建ed.Ctx
时,您应该已经在那里应用命名空间,这样您就可以避免“意外”暴露其他租户的数据(这是一个主要的安全问题)。
答案 1 :(得分:0)
如果您使用的是旧库:google.golang.org/appengine/datastore
,那么您需要使用命名空间创建上下文:
ctx2, err := appengine.Namespace(ed.Ctx, "mynamespace")
if err != nil {
return err
}
但您想使用最新的库:cloud.google.com/go/datastore
。命名空间可以直接在 Query
对象上设置。这是新的。然后您必须使用 datastoreClient.Run(ctx, query)
运行查询。
func deleteTestNamespace(ctx context.Context, namespaces string) error {
dsClient, err := datastore.NewClient(ctx, log, datastore.Config{...})
err := dsClient.DeleteMulti(ctx, keys[i:i+chunk])
if err != nil {
return err
}
var keys []*datastore.Key
for _, kind := range envKinds {
// Get all keys
query := datastore.NewQuery(kind).KeysOnly().Namespace(namespace)
it := dsClient.Run(ctx, query)
for {
var key datastore.Key
_, err := it.Next(&key)
if err == iterator.Done {
break
}
if err != nil {
return err
}
keys = append(keys, &key)
}
// Delete all records in chunks of 500 or less
for i := 0; i < len(keys); i += 500 {
chunk := min(len(keys)-i, 500)
err := dsClient.DeleteMulti(ctx, keys[i:i+chunk])
if err != nil {
return err
}
}
}
return nil
}
func min(num1 int, num2 int) int {
if num1 < num2 {
return num1
}
return num2
}