2011-06-03 50 views
2

在Python和引用中使用Google App Engine时,会自动从引用对象获取对应于您所处理对象的反向引用。这在回答here中描述得非常好。GAE模型:如何在父级中列出子节点

我想要做的是创建一个(更简单)一对多的关系,每个组都有一个标签列表,每个标签只属于一个组。我想象它像下面这样:

class Group(db.Model): 
    # All of my group-specific data here. 

class Tag(db.Model): 
    text = db.StringProperty(required=True) 
    group = db.ReferenceProperty(Group, collection='tags') 

假设我正确理解的一切......在上面,你风与每个Grouptags属性:

# Get the list of Tag objects that belong to a Group object 
mytags = mygroup.tags 

我的问题是,是有没有一种“标准”方式将这些信息包含在Group对象中?查看数据模型时,通过查看Group对象,您无法看到它有一个适用于它的标签列表。我想能够定义Group,Tags就像这样

class Group(db.Model): 
    # This should automatically be the same as the "tags" property that is 
    # created for the Group model by the definition of the Tag model 
    tags = db.ListProperty(db.Key) 
    # All of my group-specific data here. 

class Tag(db.Model): 
    text = db.StringProperty(required=True) 
    group = db.ReferenceProperty(Group, collection='tags', required=True) 
    # Other tag specific information here (such as url, etc) 

的想法是,我希望能够看到,当我在看的集团模式,它有标签的物体的列表属性。它感觉不自然我不得不看看标签模型知道这些信息。

注:这可能是值得指出的是,我计划有问题的Group是每一个它的父(对实体集团)是Tag秒。任何时候我修改一个Group,我都会完全更新它,用新的替换它的所有Tag,我想要得到他们对于我看到的Group给定“版本”的正确列表。

的用例为我的数据包括:

  • 更新组 - 创建或更新6组。如果创建,则为该组创建标签。如果更新,完全替换组的标签(删除旧标签) - 每隔5分钟左右发生一次
  • 阅读最近的组 - 获取最近修改过的6-20组(未确定),无需加载标签
  • 读单组 - 获取单个组的信息,包括它的标签(每个人都会有10到20个标签)

回答

1

你打算怎样查询您的标签,你会仅关注来自特定实体组的标签?如果是这种情况,由于您要将Tag实体放置在实体的实体组中,因此ReferenceProperty不提供实际价值。您可以改为使用tag_entity.key().parent()以获取Group实体的密钥或tag_entity.parent()以获得Group实体本身。然后,您可以使用 Group来存储标记实体的key_names(我认为这将是实际的'标记')。

由于您在更新Group实体时随时替换所有组的标签,您是否考虑使用ListProperty将标签直接存储在Group实体上。或者,直接在Group上存储标签key_name的列表。任何一种方法都可以使得一个组的所有标签都非常容易和有效。

+0

我在我的问题中添加了一些更多的细节,包括用例以及标签比文本更多的信息。我曾考虑将tag ID的ListProperty与组进行存储。然后问题(iiuc)是,当为一个组检索标签时,我需要使用“IN(ids)”子句,这会导致多个数据库命中。如果信息与标签一起存储,那么我可以使用“WHERE group_id =:group_id”类型的查询。 – RHSeeger 2011-06-03 21:13:22

+0

@RHSeeger实际上,如果您存储实体ID或名称的列表,那么您可以非常有效地直接使用Model.get_by_key_name(http://code.google.com/appengine/docs/python/datastore/modelclass.html# Model_get_by_key_name)。对于我喜欢使用(case normalized)标记作为标记实体key_name的标记,因为它为您提供了有用的数据,而无需获取标记实体。您也可以通过这种方式高效地删除(即不提取/查询)现有标签,因为您可以使用db.Key.from_path轻松构建标签实体密钥。 – 2011-06-05 04:48:09

+0

@Robert:你知道get_by_key_name的实际实现是什么吗?从我读过的类似功能看来,它似乎会为每个键敲击一次数据库......就像做一个“键列表”(键列表)sql查询。 – RHSeeger 2011-06-05 05:05:37

0

modeling in appengine

一个一对多的,使用父母会派上用场,你

你也可以考虑其他的例子

+0

对不起,在我的电话上回答 – 2011-06-04 00:20:35

+0

实体的父属性用于实体分组,用于保存数据并保存在一起并允许交易。用它来表示除了它被定义为意义之外的东西对我来说似乎是一个坏主意。 – RHSeeger 2011-06-04 04:02:48

1

有一个的ListProperty你的建议会,因为你可能实现,意味着你保留了两个参考文献,这是没有必要的。更简单的方法是简单地在描述关系的评论中注明。

不管怎样,如果您打算使用实体组,您不需要ReferencePropertyListProperty。您可以使用Tag.all().ancestor(my_group)来获取GroupTag子女。

另一种选择是将标签存储为字符串列表。其他信息可以存储在Tag实体中,key_name设置为标签名称。然后,您可以使用Tag.get_by_key_name(my_entity.tags)获取由对象引用的所有标记实体。如果您通常只需要标签名称并且仅有时检索完整数据,那么这非常有用 - 否则,您可以坚持使用ReferenceProperty或实体组。

相关问题