实体的 id、 key_name 以及 path 都有什么用?

2010-12-31 18:17:46 +08:00
 darasion
一直搞不懂为啥要这样做。

在存在实体组的情况下,Model.get_by_id() 和 Model.get_by_key_name 都必须指定 parent 才能正确获得实体。而是用Model.get()则可以直接通过key来获取实体。那么为什么还用那个数字的id或者是字符串的key_name呢?是为了是用起来记着方便呢,还是要实现实体组这些东西必须这样做呢?

如果是为了是用起来记着方便,那为什么还必须写出完整路径(path)才能获取实体??例如:Model.get_by_id(123, parent=db.Key('xxxxxx'))

另外就是不知道 path 在实体组的操作上有什么不可替代的作用呢?
4915 次点击
所在节点    Google App Engine
10 条回复
ayanamist
2010-12-31 18:43:30 +08:00
谁说get_by_id和get_by_key_name要指定parent的?麻烦你再去看看文档吧……
另外get_by_id的速度是最快的,主要是性能上的差距吧
darasion
2010-12-31 18:52:02 +08:00
@ayanamist “在存在实体组的情况下”,必须指定parent,否则返回 None。这个我实测过,你实测过吗?
darasion
2010-12-31 18:58:53 +08:00
假设:
class A(db.Model):
#...

class B(db.Model):
#...


若:
a=A()
a.put()

b=B(parent=a)
b.put()


1、那么已知 b 的 id :

运行 B.get_by_id(id, parent=a)
返回 b

运行 B.get_by_id(id)
返回 None,或者其他不是b的实体。


2、已知b 的 key:

B.get(key) 或 db.get(key) 都可以
返回 b
ayanamist
2010-12-31 19:39:16 +08:00
@darasion 你创建Model的时候指定了parent,后面调用自然也要有parent……文档里很清楚的写了。另外你写个“存在实体组的情况下”,我真不明白这句话。我看的是英文文档。
文档里对你的问题描述的很清楚,因为可以有重名但不同parent的情况。
http://code.google.com/appengine/docs/python/datastore/keysandentitygroups.html
The keys of two different entities can have similar parts as long as at least one part is different. For instance, two entities can have the same kind and name if they have different parents. Similarly, two entities can have the same parent (or no parent) and name if they are of different kinds.
ayanamist
2010-12-31 19:40:08 +08:00
@darasion 其实这个Entity Group作用很有限。文档里也写了
Only use entity groups when they are needed for transactions. For other relationships between entities, use ReferenceProperty properties and Key values, which can be used in queries.
darasion
2010-12-31 20:10:13 +08:00
@ayanamist 我问的是为什么要这样做,而不是怎样做。怎样做我知道。

你 #4 中提到的文档段落我都看了。关键是为什么?

知其然,还要知其所以然嘛。

你 #5 中提到的文档段落我也都看到了。没错,我就是在这里需要一个事务性的删除。
keakon
2010-12-31 21:37:02 +08:00
简单来说,key和path是一回事,key只是将path(元组列表)编码成字符串了而已。

所以你的问题没什么好解释的,get一个实体使用完整的path本来就是必须的。get_by_id、get_by_key_name和get是完全等效的,最终都是通过key来获取。

有的时候你只想取根实体,那么通过path去构造key就显得太麻烦了,所以才会去用上述简写。有时你已经拿到父实体的key了,那么再去构造完整的path也显得多余。
ayanamist
2011-01-01 09:15:40 +08:00
@keakon get_by_id不是通过key来获取的吧……
keakon
2011-01-01 11:50:07 +08:00
@ayanamist
源码摆在SDK里,你自己看看就知道了:
@classmethod
def get_by_id(cls, ids, parent=None, **kwargs):
"""Get instance of Model class by id.

Args:
key_names: A single id or a list of ids.
parent: Parent of instances to get. Can be a model or key.
config: datastore_rpc.Configuration to use for this request.
"""
config = datastore._GetConfigFromKwargs(kwargs)
if isinstance(parent, Model):
parent = parent.key()
ids, multiple = datastore.NormalizeAndTypeCheck(ids, (int, long))
keys = [datastore.Key.from_path(cls.kind(), id, parent=parent)
for id in ids]
if multiple:
return get(keys, config=config)
else:
return get(keys[0], config=config)

一个实体在存储到datastore的时候,最多需要保存到3种类型的表,但没有任何一种表的任何一个字段是其id或key name,所有的表都只存储编码后的key。这就是为什么不可能不用key来获取实体的原因。

顺带一提,即使是query,也是查询索引表或自定义索引表,获得key,然后再到实体表获取key对应的实体。
darasion
2011-01-02 17:54:32 +08:00
@keakon 谢谢。又加深了一些理解。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/6574

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX