我的问题是关于在ndb中建模一对多关系。我知道这可以(至少)以两种不同的方式完成:使用重复属性或使用“外键”。我在下面创建了一个小例子。基本上我们有一篇文章可以有任意数量的标签。我们假设可以删除标记,但添加标记后无法更改。我们也假设我们不担心交易安全。
我的问题是:建模这些关系的首选方式是什么?
我的考虑因素:
我是否有一些我在这里缺少的东西,还有其他需要考虑的因素吗?
非常感谢你的帮助。
示例(A):
class Article(ndb.Model):
title = ndb.StringProperty()
# some more properties
tags = ndb.KeyProperty(kind="Tag", repeated=True)
def create_tag(self):
# requires two writes
tag = Tag(name="my_tag")
tag.put()
self.tags.append(tag)
self.put()
def get_tags(self):
return ndb.get_multi(self.tags)
class Tag(ndb.Model):
name = ndb.StringProperty()
user = ndb.KeyProperty(Kind="User") # User that created the tag
# some more properties
示例(B):
class Article(ndb.Model):
title = ndb.StringProperty()
# some more properties
def create_tag(self):
# requires one write
tag = Tag(name="my_tag", article=self.key)
tag.put()
def get_tags(self):
# obviously we could cache this query in memcache
return Tag.gql("WHERE article :1", self.key)
class Tag(ndb.Model):
name = ndb.StringProperty()
article = ndb.KeyProperty(kind="Article")
user = ndb.KeyProperty(Kind="User") # User that created the tag
# some more properties
答案 0 :(得分:6)
您是否看过以下有关使用Structured Properties
https://developers.google.com/appengine/docs/python/ndb/properties#structured的信息。关于Contact
和Addresse
的简短讨论可以简化您的问题。另请参阅https://developers.google.com/appengine/docs/python/ndb/queries#filtering_structured_properties。讨论很短暂。
此外,展望不允许加入的事实,选项A
看起来更好。
答案 1 :(得分:1)
如前所述,数据存储区中没有连接,因此所有"外键#34;这个概念并不适用。可以做的是使用Query类来查询数据存储区中的正确标记。
例如,如果您使用的是端点,则:
class Tag(ndb.model):
user = ndb.UserProperty()
请求期间执行:
query.filter(Tag.user == endpoints.get_current_user())
答案 2 :(得分:0)
在大多数情况下,方法(A)应该是首选。虽然添加标记需要两次写入,但这可能比读取标记的频率低得多。只要你没有大量的标签,它们都应该适合重复的Key属性。
正如您所提到的,通过键获取标记要比执行查询快得多。此外,如果您只需要标记的名称和用户,则可以创建标记,其中User
作为父键,Name
作为标记的ID:
User -> Name -> Tag
要创建此标记,您可以使用:
tag = Tag(id=name, parent=user, ...)
article.tags.push(tag)
ndb.put_multi([tag, article])
然后当你检索标签时,
for tag in article.tags:
user = tag.parent()
name = tag.id()
然后,您存储在Article.tags
中的每个密钥都将包含用户密钥和Tag
名称!这样可以避免您在Tag
中阅读以获取这些值。