15

我的问题是关于在 ndb 中建模一对多关系。我知道这可以通过(至少)两种不同的方式完成:使用重复属性或使用“外键”。我在下面创建了一个小例子。基本上我们有一篇文章,它可以有任意数量的标签。假设标签可以删除,但添加后无法更改。我们还假设我们不担心交易安全。

我的问题是:建模这些关系的首选方式是什么?

我的考虑:

  • 方法 (A) 需要对添加到文章的每个标签进行两次写入(一个用于文章,一个用于标签),而方法(B)只需要一次写入(仅标签)。
  • 方法 (A) 在获取文章的所有标签时利用 ndb 的缓存机制,而在方法 (B) 的情况下需要查询(另外还有一些自定义缓存)

我在这里遗漏了一些东西,还有其他需要考虑的因素吗?

非常感谢您的帮助。

示例(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
4

3 回答 3

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看起来更好。

于 2012-12-18T16:48:30.030 回答
1

如前所述,Datastore 中没有连接,因此所有“外键”概念都不适用。可以做的是使用 Query 类来查询您的数据存储以获取正确的标签。

例如,如果您使用 Endpoints,则:

class Tag(ndb.model):
    user = ndb.UserProperty()

并且在请求期间执行:

query.filter(Tag.user == endpoints.get_current_user())
于 2014-04-25T21:20:25.310 回答
1

在大多数情况下应该首选方法 (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以获取这些值。

于 2015-09-18T23:00:45.137 回答