数据存储:在实体组事务中创建父实体和子实体?(Datastore: Create parent and child entity in an entity group transaction?)

编程入门 行业动态 更新时间:2024-10-24 13:18:18
数据存储:在实体组事务中创建父实体和子实体?(Datastore: Create parent and child entity in an entity group transaction?)

在阅读了Google Datastore概念/理论后,我开始使用Go数据存储包

场景:种类User和LinkedAccount要求每个用户都有一个或多个链接帐户(yay第三方登录)。 为了保持一致性,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

从图书馆来源明确了为什么这不起作用。 PendingKey不是密钥,不完整的密钥不能用作父母。

这是数据存储区或库的必要限制吗? 对于那些有这种要求的人来说,你是否只是牺牲了强大的一致性并使这两种全球化?

对于谷歌能力:

数据存储区:无效密钥 数据存储区:不能将pendingKey用作类型*“google.golang.org/cloud/datastore”。键

After reading about Google Datastore concepts/theory I started using the Go datastore package

Scenario: Kinds User and LinkedAccount require that every user has one or more linked accounts (yay 3rd party login). For strong consistency, LinkedAccounts will be children of the associated User. New User creation then involves creating both a User and a LinkedAccount, never just one.

User creation seems like the perfect use case for transactions. If, say LinkedAccount creation fails, the transaction rolls back an fails. This doesn't currently seem possible. The goal is to create a parent and then a child within a transaction.

According to docs

All Datastore operations in a transaction must operate on entities in the same entity group if the transaction is a single group transaction

We want a new User and LinkedAccount to be in the same group, so to me it sounds like Datastore should support this scenario. My fear is that the intended meaning is that operations on existing entities in the same group can be performed in a single transaction.

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

From the library source its clear why this doesn't work. PendingKey's aren't keys and incomplete keys can't be used as parents.

Is this a necessary limitation of Datastore or of the library? For those experienced with this type of requirement, did you just sacrifice the strong consistency and make both kinds global?

For Google-ability:

datastore: invalid key datastore: cannot use pendingKey as type *"google.golang.org/cloud/datastore".Key

最满意答案

需要注意的一点是,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)

显式调用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)

One thing to note is that transactions in the Cloud Datastore API can operate on up to 25 entity groups, but this doesn't answer the question of how to create two entities in the same entity group as part of a single transaction.

There are a few ways to approach this (note that this applies to any use of the Cloud Datastore API, not just the gcloud-golang library):

Use a (string) name for the parent key instead of having Datastore automatically assign a numeric ID:

parentKey := datastore.NewKey(ctx, "Parent", "parent-name", 0, nil) childKey := datastore.NewIncompleteKey(ctx, "Child", parentKey)

Make an explicit call to AllocateIds to have the Datastore pick a numeric ID for the parent key:

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)

更多推荐

本文发布于:2023-04-27 15:52:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1327148.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:实体   数据存储   事务   Datastore   Create

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!