Google app engine Go在Google应用程序引擎数据存储中有很多关系

Google app engine Go在Google应用程序引擎数据存储中有很多关系,google-app-engine,go,google-cloud-datastore,Google App Engine,Go,Google Cloud Datastore,我是个新手,到目前为止我很喜欢它。然而,我一辈子也弄不明白这一点 我有一个简单的包裹,发票 type Invoice struct { key datastore.Key Name string Created time.Time Updated time.Time lineItems []LineItem } 发票有多个行项目 type LineItem struct { key datastore.Key InvoiceKey *da

我是个新手,到目前为止我很喜欢它。然而,我一辈子也弄不明白这一点

我有一个简单的包裹,发票

type Invoice struct {
    key datastore.Key
    Name string
    Created time.Time
    Updated time.Time
    lineItems []LineItem
}
发票有多个行项目

type LineItem struct {
    key datastore.Key
    InvoiceKey *datastore.Key
    Name string
    Description string
}
我的软件包有两个功能

func New(c appengine.Context) (i Invoice)
func (i *Invoice) Update()
func (i *Invoice) Save(c appengine.Context)
func (i *Invoice) AddLineItem(c appengine.Context, name string)
New()返回新发票,并将datastore.newIncompletKey()生成的密钥作为未报告变量保存在发票中,以便以后保存

所有这些都很好,这是否是正确的方法是另一个问题。我也愿意就此发表评论。我似乎无法理解的是最后一个函数

func (i *Invoice) AddLineItem(c appengine.Context, name string) {
    key := datastore.NewIncompleteKey(c, "LineItem", &i.key)
    lineItem := LineItem{key: *key, InvoiceKey: &i.key, Name: name}
    i.lineItems = append(i.lineItems, lineItem)
}
在Save()中

我一直在这里得到一个无效的密钥错误。我基本上只是想让一张发票能够有很多行项目。能够将它们全部保存到数据存储中,然后根据需要取出包含所有行项目的整个发票


我走对了吗?有更好的方法吗?

您的
lineItems[]LineItem
密钥数据存储。密钥
未报告,它们需要以大写字母开头,否则GAE将无法使用它

从:

可以导出标识符以允许从另一个包访问它。如果出现以下两种情况,则导出标识符:

  • 标识符名称的第一个字符是Unicode大写字母(Unicode类“Lu”);及
  • 标识符在包块中声明,或者是字段名或方法名
  • 不会导出所有其他标识符


    不要使用
    datastore.Key
    ,而是使用
    *datastore.Key
    。任何时候你认为它可能不会被设置是一个bug的来源,并且可能会把你的无效密钥错误变成恐慌


    您正在给
    行项目
    键一个父项(
    发票
    ),这很好,但是为什么除了
    行项目
    键之外还要存储
    发票
    键呢?您可以通过调用后者的父方法来获取前者。

    我遇到的问题是试图使用不完整的发票密钥生成不完整的LineItem密钥

    key, err := datastore.Put(c, &i.key, i)
    
    使用put返回的完整密钥

    for _, lineItem := range i.lineItems {
        key := datastore.NewIncompleteKey(c, "LineItem", key)
        lineItem.InvoiceKey = k
        _, err := datastore.Put(c, key, &lineItem)
        if err != nil {
            panic(err)
        }
    }
    

    那是储存它们的地方。现在,我们来研究如何从数据存储中读取它们!祝我好运。

    它们不是故意的。它们不是问题所在。仅供参考,为了避免将来让您头疼,这是来自文档:“不要命名属性”键。此名称是为用于存储模型键的特殊属性保留的。尽管它可能在本地工作,但名为“键”的属性将阻止部署到App Engine。”
    for _, lineItem := range i.lineItems {
        key := datastore.NewIncompleteKey(c, "LineItem", key)
        lineItem.InvoiceKey = k
        _, err := datastore.Put(c, key, &lineItem)
        if err != nil {
            panic(err)
        }
    }