3 回答
TA贡献1864条经验 获得超6个赞
让我们先明确一些事情:
实体键的标识符部分可以是
一键名字符串
或整数数字 ID
但不能两者兼而有之。所以当你保存一个实体时,它的键要么有一个string
名为name的ID要么(异或)一个int64
名为intID的ID 。
2 个可选的标识符字段是不同的:如果您有一个实体,name="1234"
它与 with 的实体不同intID=1234
。
当您在未明确指定name
或 的情况下保存新实体时intID
,数据存储将为它分配一个新的唯一intID
标识符。数据存储永远不会string
name
自己分配 a 。string
name
如果您string
name
自己指定,则只能拥有带有标识符的实体。
数据存储知道intID
它自己生成的自动生成的s,并且永远不会生成相同的intID
两次(井行为)。但是,如果您intID
自己指定一个新实体,则在保存新实体时,您必须注意它的唯一性。这将需要首先检查intID
您想要使用的是否尚未使用(例如通过首先查询它以查看是否还没有实体intID
),但即使这样也不能100%保证到您最终实际保存时具有此功能的实体仍将不被使用。该AllocateIDs()
函数可用于获取连续范围的intID
s,数据存储稍后将不会使用该范围intID
自行生成s,因此您可以自由使用分配的范围intID
s 安全。这也意味着,如果有并发请求也试图保存新实体(在同一实例中或在其他实例中),intID
如果标识符生成留给数据存储,它们也将永远不会使用这些s。
回到你的问题
您真的需要手动分配标识符吗?在大多数情况下,这仅在您已经拥有实体的唯一属性时才使用/需要,该属性对于 2 个不同的实体不能相同(例如,实体Person
具有IdentityCardId
每个人都已经独一无二的属性)。
如果你有这样一个独特的属性,你可以使用本质上确保唯一性的属性。如果您没有这样的属性,那么您首先不应该使用手动标识符分配,您可以只使用/依赖intID
数据存储的自动分配。
请注意,您可以拥有相同类型的不同实体的混合标识符(例如,您可以拥有一个Person
withintID
和另一个Person
with name
)。
如上所述,intID
s 和name
s 是不同的。所以AllocateIDs()
不会name
仅仅因为name
包含有效数字而考虑带有标识符的实体。从数据存储中,您无法获得“分配”name
标识符(类似于 to AllocateIDs()
allocation intID
s)的帮助,因此它必须是应用程序逻辑以确保分配name
的唯一性,否则您最终将“覆盖”/替换现有实体。
TA贡献1803条经验 获得超6个赞
您可以通过在 id 前面加上您知道从未用于密钥的任何字符串作为前缀来避免任何冲突的可能性。例如:
String key = "id" + entity.getKey().getId();
只有当您为字符串键使用整数序列时,所有这些才是必要的。
TA贡献1856条经验 获得超11个赞
让数据存储为您生成字符串键的方法是使用NewIncompleteKey.
ikey := datastore.NewIncompleteKey(ctx, "Thing", nil)
key, _ := datastore.Put(ctx, ikey, nil) // TODO: check the error
fmt.Println(key.Encode()) // randomly-generated string key
然后从字符串键取回它......
ks := req.FormValue("key") // e.g., from an HTTP request parameter
key, _ := datastore.DecodeKey(ks) // TODO: check the error
var t Thing
_ = datastore.Get(ctx, key, &t) // TODO: check the error
- 3 回答
- 0 关注
- 255 浏览
添加回答
举报