如何使用命名空间在golang中从数据存储区查询实体?

时间:2017-11-08 08:11:50

标签: google-app-engine go google-cloud-datastore gcp

我正在开发一个多租户应用程序,我需要从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)

2 个答案:

答案 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
}