【问题标题】:ndb many to many, retrieve list of one of the relationndb 多对多,检索关系之一的列表
【发布时间】:2015-03-06 09:45:43
【问题描述】:

我有这张桌子

class ClubMembership(GCModel):
    member = ndb.KeyProperty(kind='User', required=True)
    club = ndb.KeyProperty(kind='Club', required=True)
    is_active = ndb.BooleanProperty(default=True)
    membership_type = ndb.StringProperty(choices=set(["MEMBER", "TRAINER", "OWNER"]), default="MEMBER",
                                     required=True)

然后在表中Club 我有这个

class Club(GCModel):
    @property
    def members(self):
        return ClubMembership.query(ndb.AND(ClubMembership.club == self.key,
                                            ClubMembership.membership_type == "MEMBER",
                                            ClubMembership.is_active == True))

我真正需要的是检索User 的列表。我该怎么办?

获取此查询,而不是使用 for 循环获取每个 member 使用其键?

我尝试通过member 上的投影来使用ndb.get_multi,但它不起作用。 像这样的

members= ClubMembership.query(ndb.AND(ClubMembership.club == self.key,
                                            ClubMembership.membership_type == "MEMBER",
                                            ClubMembership.is_active == True),projection=['member']).fetch()
ndb.get_multi(members)

【问题讨论】:

    标签: python google-app-engine google-cloud-datastore data-modeling app-engine-ndb


    【解决方案1】:

    get_multi 适用于密钥列表,您有一个 ClubMembership 实例列表。您需要为每个人获取member 密钥:

    memberships = ClubMembership.query(...)
    member_keys = [m.member for m in memberships]
    members = ndb.get_multi(member_keys)
    

    【讨论】:

    • 这就是我的感觉。如果我做一个 for 循环(因为我需要一些其他处理)for membership in memberships: user = membership.member.get(),会有任何性能差异吗?
    • 请参阅the docs ——在循环中执行此操作将导致每个实体单独的 RPC,这肯定会比单个 get_multi 调用慢。最好一次获取所有内容并对结果进行处理。
    • 我明白了,那么,获得所有用户及其成员类型的最佳方式应该是什么?因为会员类型在会员列表中。因此,我使用 get_multi 获取用户,但现在:如何将用户与成员列表中的用户匹配以检索其成员类型?这两个列表的顺序是否相同?
    • @EsseTi 很简单。对检索到的用户使用循环,并在每个成员上再使用一个嵌套循环来查找成员匹配项。
    • @EsseTi 如果您想获取所有成员及其成员类型,您可以执行类似 zip(memberships, ndb.get_multi([m.member for m in members])) 之类的操作
    【解决方案2】:

    您还应该考虑将会员信息存储在用户实体中。这样您就可以在一个查询中获取所有用户,速度要快得多。

    class Membership(ndb.Model):
      club = ndb.KeyProperty(kind='Club', required=True)
      is_active = ndb.BooleanProperty(default=True)
      membership_type = ndb.StringProperty(
        choices=set(["MEMBER", "TRAINER", "OWNER"]), default="MEMBER", required=True)
    
    class User(ndb.Model):
      memberships = ndb.StructuredProperty(Membership, repeated=True)
    
    class Club(ndb.Model):
      @property
      def members(self):
        membership = Membership(
          User.memberships.club == self.key,
          User.memberships.membership_type == 'MEMBER',
          User.memberships.is_active == True)
        return User.query(User.memberships == membership)
    

    【讨论】:

    • 我明白了,事实上我对这个重复的实体持怀疑态度stackoverflow.com/questions/15377119/…
    • 用户将成为许多俱乐部的成员的情况似乎非常罕见,但这是您的决定。
    • 但是我的课程也有同样的问题,人们可能会订阅很多课程..
    • 无论如何都要对数据进行反规范化——这对于应用引擎数据存储来说是一个很好的做法,您应该能够使用单个查询生成整个页面,以使其速度极快。我认为它甚至应该适用于课程。
    • 你是对的,一件事。要获得用户所属的所有俱乐部,我应该怎么做?迭代用户的memberships,然后一一检查成员是否属于MEMBER
    猜你喜欢
    • 1970-01-01
    • 2014-08-15
    • 2016-06-03
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    相关资源
    最近更新 更多