【问题标题】:GAE: NDB query on listGAE:列表上的 NDB 查询
【发布时间】:2017-09-29 19:29:09
【问题描述】:

Google App Engine NDB 数据模型如下:

Users
    Username
    FirstName
    LastName

Posts
    PostID
    PosterUsername

SubscribedPosts
    PostID
    SubscriberUsername

对于特定用户,我想返回用户订阅的所有帖子并在页面上显示。

由于美妙的 NDB 不支持 JOIN,我们执行两个查询:

postIDList = 
SubscribedPosts.query(SubscribedPosts.SubscriberUsername == 'johndoe').fetch()

这为我们提供了订阅帖子的列表。那么如何获取我的 postIDList 列表并将其用作 Posts 查询的过滤条件?

类似:

results = Posts.query(Post.PostID IN postIDList.PostID)

在普通的关系数据库中,这将是一个使用表连接的简单查询。这在 Google 的 ndb 中是如何完成的?

【问题讨论】:

  • 我是否必须在帖子中添加一个重复的列(即:列表),这将是订阅该帖子的用户名列表?而不是将订阅帖子用于多对多关系的规范化关系设计?

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


【解决方案1】:

如果您尝试像在本示例中那样在关系数据库中设计表的方式来设计数据存储模型,那么您将遇到很多瓶颈。

您的评论可能朝着正确的方向发展,尽管还有其他解决方案。走这条路,我会放弃“subscribedPosts”模型,完全使用 User 模型中的重复 KeyProperty 实体来存储订阅的帖子。

查看此相关帖子:One-To-Many Example in NDB

【讨论】:

  • 也应该使用父/祖先模型行为而不是伪连接。
  • 当重复属性增长到大于 10 个属性时,查询重复属性的 IN 关系不会降级吗?
【解决方案2】:

似乎您正在寻找建立多对多关系的模型,而不是一对多。阅读Modelling Entity Relationships(虽然这是给旧的db,而不是新的ndb,它仍然给出了这个想法)。

两个实体中的一个应维护相关其他实体的键列表(重复=True)。哪个实体应该持有这份名单?列表最好位于通常具有较少关系的一侧,以便键列表更小。另一个考虑因素是哪一方对更新的争用可能较少。

在您的具体情况下,假设用户平均订阅 10 个帖子,并且假设每个帖子平均有 100 个用户订阅它。在这种情况下,我们希望将键列表放在关系的Users 一侧。

class Users(ndb.Model):
    user_name = ndb.StringProperty()
    first_name = ndb.StringProperty()
    last_name = ndb.StringProperty()
    posts = ndb.KeyProperty(kind='Posts', repeated=True)

class Posts(ndb.Model)
    post_id = ndb.StringProperty()
    poster_user_name = ndb.StringProperty()

通过添加到Users 实例中的列表来建立关系:

current_user.posts.append(current_post.key)

对于给定的Users 实例,获取所有订阅的Posts 很容易,因为订阅的Posts 的键列表已经在给定的Users 中:

ndb.get_multi(given_user.posts)

对于给定的Posts 实例,获取所有订阅Users 的...

query = Users.query(Users.posts == given_post.key)

【讨论】:

  • 我是如此根植于关系数据库的思维模式,以至于我设计了一个关系模式,而不是 NDB 遵循的任何范式。
  • 重复属性的一个问题是它们的大小有限。如果您有一组相当少的可能项目,那么它们是实用的。但是,如果它可能是一个相当大的集合,那么您将需要一个中间实体,它可以有效地表示一个 pre=computed 连接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 1970-01-01
  • 2016-07-28
  • 1970-01-01
相关资源
最近更新 更多