如何在 golang 中使用命名空间从数据存储中查询实体?
How to query a entity from datastore with Namespace In golang?
我正在开发一个多租户应用程序,我需要从 KIND 和特定命名空间查询特定用户。
我可以从默认 Namespace.the 包中获取值,我在这里使用的是 "google.golang.org/appengine/datastore"
q := datastore.NewQuery(ENTITYNAME).Filter("Name =", ed.Expense.Name)
var expenses []ExpenseEntiry
return q.GetAll(ed.Ctx, &expenses)
命名空间值不是查询的一部分(它不是查询的 属性)。命名空间来自您在执行查询时传递的上下文,例如至 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
,您应该已经在那里应用了命名空间,这样就可以避免 "accidental" 暴露其他租户的数据(这是一个主要的安全问题)。
如果您使用的是旧库: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
}
我正在开发一个多租户应用程序,我需要从 KIND 和特定命名空间查询特定用户。
我可以从默认 Namespace.the 包中获取值,我在这里使用的是 "google.golang.org/appengine/datastore"
q := datastore.NewQuery(ENTITYNAME).Filter("Name =", ed.Expense.Name)
var expenses []ExpenseEntiry
return q.GetAll(ed.Ctx, &expenses)
命名空间值不是查询的一部分(它不是查询的 属性)。命名空间来自您在执行查询时传递的上下文,例如至 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
,您应该已经在那里应用了命名空间,这样就可以避免 "accidental" 暴露其他租户的数据(这是一个主要的安全问题)。
如果您使用的是旧库: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
}