3

我正在尝试持久化实体,并允许数据库生成密钥。不幸的是,我似乎无法从 API 中提取合成 ID ......这就是我正在做的事情:

case "POST":
    d,_ := ioutil.ReadAll( r.Body)
    participant := new(Participant)
    err := json.Unmarshal( d, &participant)
    if err != nil {
        serveError( c, w, err)
        return
    }

    var key *datastore.Key;
    if participant.ID == 0 {
        // no id yet .. create an incomplete key and allow the db to create one.
        key = datastore.NewIncompleteKey( c, "participant", parentKey)
    } else {
        // we have an id.  use that to update
        key = datastore.NewKey( c, "participant", "", participant.ID, parentKey)
    }
    // PERSIST!
    putKey, e := datastore.Put( c, key, participant)
    if e != nil {
         serveError( c, w, e)
         return
    }

    // Fetch back out of the database, presumably with my new ID
    if e = datastore.Get( c, putKey, participant); e != nil {
         serveError( c, w, e)
         return
    }

    // send to the consumer
    json,_ := json.Marshal( participant)
    w.Write( json)

好吧,奇怪的是,ID 总是为零!详细信息被保留,但我得到多个值与相同的 ID 字段一起保留。对于咧嘴笑,这是对象定义:

type Participant struct {
    ID         int64
    LastName   string
    FirstName  string
    Birthdate  string
    Email      string
    Cell       string
}

执行 GET 操作后,我会看到一个 ID 为零的实体列表(是的,我创建的实体,与我创建它们的次数一样多)。

[
 {"ID":0,"LastName":"Schmuck","FirstName":"Joe","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""}
]

为了完整起见,我还尝试使用 ID 值为 0 的 NewKey(),但结果相同。关于 NewKey 的 API 文档说明了(字符串)名称和 ID 都为零创建一个不完整的密钥——我不确定如何使字符串为零,但 nil 不起作用。

一旦指出文档的正确部分,有人帮我弄清楚什么可能非常明显。

4

2 回答 2

5

我没有看到您在任何地方填充 ID 字段,因此它当然会为 0,因为这是该字段的零值。AppEngine 在存储它时不会修改您的结构。当您使用不完整的键时,您在放置结构时返回的新创建的键包含生成的 IntId()。我认为您的困惑是由于假设文档从未说过的话引起的。也就是说,AppEngine 会为您自动填充存储数据中的 ID 字段。

因为在您的情况下,您希望结构的 ID 字段存储密钥中使用的 id,您可能希望在创建密钥而不是使用不完整的密钥时生成您自己的唯一 ID。

当文档说字符串可以为零时,它指的是字符串类型的零值,即空字符串“”。您可以在此处阅读有关零值的更多信息:http: //golang.org/ref/spec#The_zero_value

于 2013-01-04T06:36:27.157 回答
2

我没有看到您在 Put 之前实际更改 ID 值的位置?据我所知,它总是为 0。我本来希望看到如下内容:

// PERSIST!
putKey, e := datastore.Put( c, key, participant)
if e != nil {
    // ...
}
// ...
participant.ID = putKey.IntID()
putKey, e = datastore.Put(c, putKey, participant)

未经测试,但你得到了图片......否则 ID 将始终为 0。

于 2013-01-04T06:38:58.997 回答