dgh*_*dgh 4 go google-cloud-datastore
阅读了有关Google数据存储区的概念/理论后,我开始使用Go数据存储区包
场景:种类User和LinkedAccount要求每个用户都有一个或多个关联账户(耶第三方登录)。为了保持高度一致性,LinkedAccounts将是关联用户的子级。然后,创建新用户涉及创建一个User和一个LinkedAccount,而不仅仅是一个。
用户创建似乎是交易的完美用例。如果说LinkedAccount创建失败,则事务回滚失败。目前看来这不可能。目标是在事务中创建父级,然后创建子级。
根据文档
如果事务是单个组事务,则事务中的所有数据存储区操作必须在同一实体组中的实体上进行操作
我们希望有一个新的User并且LinkedAccount要在同一个组中,所以对我来说,Datastore应该支持这种情况。我担心的是预期的含义是可以在单个事务中执行对同一组中现有实体的操作。
tx, err := datastore.NewTransaction(ctx)
if err != nil {
return err
}
incompleteUserKey := datastore.NewIncompleteKey(ctx, "User", nil)
pendingKey, err := tx.Put(incompleteUserKey, user)
if err != nil {
return err
}
incompleteLinkedAccountKey := datastore.NewIncompleteKey(ctx, "GithubAccount", incompleteUserKey)
// also tried PendingKey as parent, but its a separate struct type
_, err = tx.Put(incompleteLinkedAccountKey, linkedAccount)
if err != nil {
return err
}
// attempt to commit
if _, err := tx.Commit(); err != nil {
return err
}
return nil
Run Code Online (Sandbox Code Playgroud)
从库中可以清楚地知道为什么这行不通。PendingKey的不是键,不完整的键不能用作父键。
这是数据存储区还是库的必要限制?对于那些有这种需求经验的人,您只是牺牲了强大的一致性并使这两种类型具有全球性吗?
对于Google功能:
需要注意的一件事是,Cloud Datastore API中的事务最多可以对25个实体组进行操作,但这并不能回答如何在同一实体组中创建两个实体作为单个事务的一部分的问题。
有几种方法可以解决此问题(请注意,这适用于Cloud Datastore API的任何使用,而不仅仅是gcloud-golang库):
使用(字符串)名称作为父键,而不是让数据存储区自动分配数字ID:
parentKey := datastore.NewKey(ctx, "Parent", "parent-name", 0, nil)
childKey := datastore.NewIncompleteKey(ctx, "Child", parentKey)
Run Code Online (Sandbox Code Playgroud)进行明确调用,AllocateIds以使数据存储区为父键选择一个数字ID:
incompleteKeys := [1]*datastore.Key{datastore.NewIncompleteKey(ctx, "Parent", nil)}
completeKeys, err := datastore.AllocateIDs(ctx, incompleteKeys)
if err != nil {
// ...
}
parentKey := completeKeys[0]
childKey := datastore.NewIncompleteKey(ctx, "Child", parentKey)
Run Code Online (Sandbox Code Playgroud)