【问题标题】:How do I query a many to many relationship model? - Google App Engine如何查询多对多关系模型? - 谷歌应用引擎
【发布时间】:2010-09-07 12:55:33
【问题描述】:

这是我的模型:

class User(db.Model):
    id = db.StringProperty(required=True)
    created = db.DateTimeProperty(auto_now_add=True)
    updated = db.DateTimeProperty(auto_now=True)
    name = db.StringProperty(required=True)
    email = db.StringProperty()

class Page(db.Model):
    id = db.StringProperty(required=True)
    created = db.DateTimeProperty(auto_now_add=True)
    updated = db.DateTimeProperty(auto_now=True)
    name = db.StringProperty(required=True)
    link = db.StringProperty(required=True)

class UserPage(db.Model): 
    user = db.ReferenceProperty(User, collection_name='pages') 
    page = db.ReferenceProperty(Page, collection_name='users')

如何构造查询来查找用户页面?

我发现一篇文章描述了一种方法,但这是最好的方法吗? http://blog.arbingersys.com/2008/04/google-app-engine-better-many-to-many.html

【问题讨论】:

    标签: google-app-engine many-to-many google-cloud-datastore bigtable


    【解决方案1】:

    您的答案会起作用,但它会对数据存储区执行 7 次调用:

    • 1 用于调用 User.get_by_key_name()
    • 1 用于调用 UserPage...fetch()
    • 循环内每次取消引用 x.page.id 5 个

    另一种只对数据存储区调用 3 次的方法是这样的:

    myuser = User.get_by_key_name("1") 
    up = UserPage.all().filter('user =', myuser).fetch(5)
    keys = [UserPage.page.get_value_for_datastore(x) for x in up]
    pages = db.get(keys)
    for p in pages: 
         self.response.out.write(p.id)
    

    更多详情请见http://blog.notdot.net/2010/01/ReferenceProperty-prefetching-in-App-Engine

    【讨论】:

    • 哦,非常好!我不知道循环是如此昂贵。谢谢提醒。
    【解决方案2】:

    经过一些测试,看来我可以使用:

     myuser = User.get_by_key_name("1")
     up = UserPage.all().filter('user =', myuser).fetch(5)
     for x in up:
         self.response.out.write(x.page.id)
    

    【讨论】:

      【解决方案3】:

      我会推荐一种不同的方法,即比您的 UserPage 关系更不“面向关系”:

      class User(db.Model):
          id = db.StringProperty(required=True)
          created = db.DateTimeProperty(auto_now_add=True)
          updated = db.DateTimeProperty(auto_now=True)
          name = db.StringProperty(required=True)
          email = db.StringProperty()
      
      class Page(db.Model):
          id = db.StringProperty(required=True)
          created = db.DateTimeProperty(auto_now_add=True)
          updated = db.DateTimeProperty(auto_now=True)
          name = db.StringProperty(required=True)
          link = db.StringProperty(required=True)
      
          # Users linking to this page
          users = db.ListProperty(db.Key)
      

      然后您可以通过以下查询获取特定用户的所有页面:

      Page.gql("WHERE users = :1", user.key())
      

      请注意,您应该将键的列表属性放在您期望较少项目的一侧。我假设与链接到用户的页面相比,喜欢页面的用户会更少,因此我将其放在 Page 一侧,但这取决于您的具体用例。

      有关多对多主题的官方建议请参见此处:http://code.google.com/appengine/articles/modeling.html

      【讨论】:

      • 感谢此方法和文章。我会用它做一些测试。
      • 再次感谢您,我最终采用了这种方法。
      猜你喜欢
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-14
      • 2012-07-15
      • 1970-01-01
      • 1970-01-01
      • 2014-03-02
      相关资源
      最近更新 更多