数据存储区中的每个实体都有一个键,一个对于应用程序中所有实体都唯一的标识符。一个键有若干个组成部分:路径描述两个实体之间的父子关系,实体的类型,以及由应用程序分配给实体的名称,或由数据存储区分配的数字 ID。
每个实体都属于特定的类型,类型是可以由查询返回的一组实体。与表中的行不同,虽然应用程序可以在一个数据模型中建立此类限制,然而相同类型的两个实体不需要有相同的属性。数据存储区 API 使用 Model(或 Expando)子类的名称作为类型的名称。
例如,该类定义了名为“Story”的类型的 Model。
class Story(db.Model): title = db.StringProperty() author = db.StringProperty()
每个实体都有标识符。应用程序可以通过授予实例构造函数 key_name 参数(str 值)来分配自己的标识符以便在键中使用。
s = Story(key_name="xzy123")
key_name 存储为 Unicode 字符串,str 值转换为 ASCII 文本。key_name 绝不能以数字开头,绝不能采用 __*__ 形式(以两根下划线开头和结尾)。如果您的应用程序使用用户提交的数据作为实体键名(例如电子邮件地址),应用程序应首先清理值,例如用已知的字符串作为前缀以符合这些要求。
如果未指定 key_name,则第一次将实体存储到数据存储区中时,会向其分配数字 ID。
s2 = Story() # s2 does not have a name or an ID. s2.put() # s2 is given an ID by the datastore.
一旦创建了实体,就不能更改其 ID 或名称。
提示:键名和 ID 不是属性值。但是,您可以通过引用特殊属性名 __key__ 对键执行有限的一组查询。如果所有实体的类型和父实体都相同,便可对键名或 ID 应用过滤条件和排序顺序。请参阅对键进行查询。
每个实体都属于一个实体组,它是可以在一个事务中控制的一组实体(一个或多个)。实体组关系会让 App Engine 在分布式网络的相同部分中存储若干实体。事务会针对实体组设置数据存储区操作,且所有操作都会以组的形式应用。如果事务失败,则全都不应用。
应用程序创建实体时,可使用 Model 构造函数中的 parent 参数将另一个实体指定为新实体的父实体。为新实体指定父实体会将新实体放置在与父实体相同的实体组中。
没有父实体的实体是根实体。作为另一个实体的父实体的实体也可以有父实体。从某实体到根的父实体链是该实体的路径,路径的成员是该实体的祖先。实体的父实体是在创建该实体时定义的,且以后不能再更改。
每个采用指定根实体作为祖先的实体都在相同的实体组中。一个组中的所有实体都存储在相同的数据存储区节点中。一个事务可以修改一个组中的多个实体,或向组添加新实体(方法是以组中的现有实体作为新实体的父实体)。
有关事务的详细信息,请参阅事务。
如果删除了某个作为其他实体的祖先的实体,则后续实体不会被删除。仍可以使用后续实体完整的键或路径对其进行访问。
您可以用祖先路径创建实体而无需先创建父实体。为此,您可以使用类型和键名为祖先创建一个 Key,然后将其用作新实体的父实体。所有具有同一根祖先的实体都属于同一实体组,与路径的根是否代表实际实体无关。
使用实体组的提示:
实体的完整键(包括路径、类型、名称或数字 ID)都是唯一的并特定于该实体。在数据存储区中创建实体时,会分配完整的键,且不能更改其任何部分。
只要至少一个部分不同,两个不同实体的键就可以有相似的部分。例如,如果两个实体有不同的父实体,它们可以有相同的类型和名称。类似地,如果两个实体的类型不同,它们可以有相同的父实体(或没有父实体)和名称。
应用程序不应依赖于以增序(实体创建的顺序)分配的数字 ID。这是通常情况,但并无保证。