【问题标题】:How to query a entity from datastore with Namespace In golang?如何在 golang 中使用命名空间从数据存储中查询实体?
【发布时间】:2018-04-20 20:04:19
【问题描述】:

我正在开发一个多租户应用程序,我需要从 KIND 和特定命名空间查询特定用户。

我能够从默认命名空间中获取值。我在这里使用的包是"google.golang.org/appengine/datastore"

q := datastore.NewQuery(ENTITYNAME).Filter("Name =", ed.Expense.Name)
    var expenses []ExpenseEntiry
    return q.GetAll(ed.Ctx, &expenses)

【问题讨论】:

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


    【解决方案1】:

    命名空间值不是查询的一部分(它不是查询的属性)。命名空间来自执行查询时传递的上下文,例如到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,你应该已经在那里应用了命名空间,这样你就可以避免“意外”暴露其他租户的数据(这是一个主要的安全问题)。

    【讨论】:

    • @NagarajaSV,如果它有效,你也可以投票给答案。
    • > "很少需要创建具有不同命名空间的新上下文,ed.Ctx 应该已经是具有正确命名空间的上下文。"您是否介意将此扩展到像我这样的 Go 新手?我从http.Request 获得的ctx 对象以及它如何已经拥有正确的命名空间?
    • @dustinmoris 在编写此问答时,上下文不是context.Context,而是包含命名空间的特定于应用引擎的上下文。
    • 感谢您的澄清。我实际上在这里找到了如何在 Datastore 模式下为 Google Firestore 设置最新的 Go 包的命名空间:github.com/googleapis/google-cloud-go/issues/…
    【解决方案2】:

    如果您使用的是旧库:google.golang.org/appengine/datastore,那么您需要使用命名空间创建上下文:

    ctx2, err := appengine.Namespace(ed.Ctx, "mynamespace")
    if err != nil {
        return err
    }
    

    但您想使用最新的库:cloud.google.com/go/datastore。 Namespace 可以直接在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
    }
    

    【讨论】:

      猜你喜欢
      • 2019-09-17
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      • 2016-11-21
      • 2014-12-13
      • 2019-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多