【问题标题】:How to flatten a 'friendship' model within User model in GAE?如何在 GAE 的用户模型中展平“友谊”模型?
【发布时间】:2013-07-03 17:04:54
【问题描述】:

我最近看到一些文章指出要扁平化 NoSQL 数据库的数据。来自传统的 SQL 数据库,我意识到我正在 GAE 中复制 SQL 数据库行为。所以我开始尽可能地重构代码。

我们有例如一个社交媒体网站,用户可以在其中成为朋友。

class Friendship(ndb.Model):
   from_friend = ndb.KeyProperty(kind=User)
   to_friend = ndb.KeyProperty(kind=User)

该应用实际上在两个用户之间创建了一个友谊实例。

friendshipA = Friendship(from_friend = UserA, to_friend = userB)
friendshipB = Friendship(from_friend = UserB, to_friend = userA)

我现在如何将其移动到实际的用户模型以将其展平。我想也许我可以使用 StructuredProperty。我知道它仅限于 5000 个条目,但这对朋友来说应该足够了。

class User(UserMixin, ndb.Model):
     name = ndb.StringProperty()
     friends = ndb.StructuredProperty(User, repeated=True)

所以我想出了这个,但是用户不能指向自己,所以看起来。因为我得到了NameError: name 'User' is not defined

知道如何将其展平,以便单个 User 实例包含其所有朋友及其所有属性吗?

【问题讨论】:

  • 您可以使用ListProperty 字符串作为用户所有朋友的ID。这不是非常 OOP,但它很容易和简单。

标签: google-app-engine google-cloud-datastore app-engine-ndb


【解决方案1】:

您不能创建引用自身的 StructuredProperty。此外,使用 StructuredProperty 存储User 的副本还有一个额外的问题,即如果用户修改了存储的属性,则需要执行手动级联更新。

但是,由于 KeyProperty 接受 String 作为kind,您可以按照@dragonx 的建议轻松存储使用 KeyProperty 的用户列表。您可以通过使用ndb.get_multi 进一步优化读取,以避免在检索朋友时多次往返 RPC 调用。

这是一个示例代码:

class User(ndb.Model):
     name = ndb.StringProperty()
     friends = ndb.KeyProperty(kind="User", repeated=True)

userB = User(name="User B")
userB_key = userB.put()

userC = User(name="User C")
userC_key = userC.put()

userA = User(name="User A", friends=[userB_key, userC_key])
userA_key = userA.put()

# To retrieve all friends
for user in ndb.get_multi(userA.friends):
    print "user: %s" % user.name

【讨论】:

    【解决方案2】:

    使用存储用户实例密钥的 KeyProperty。

    【讨论】:

    • 但这就像 ForeignKey 样式。我会收集朋友的钥匙,但没有他们的名字等。你知道我的意思吗?它还不是很平整...
    • 然而(重复的)KeyProperty 是您应该做的。让单个 User 实例包含其所有朋友的副本的想法是行不通的,因为它包含不会在任何朋友更新其属性时更新的副本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-28
    • 2011-12-01
    • 2023-04-04
    • 2012-04-05
    • 1970-01-01
    • 2012-01-27
    相关资源
    最近更新 更多