如何查询多对多关系模型? - Google App Engine

时间:2010-09-07 12:55:33

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

以下是我的模特:

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

3 个答案:

答案 0 :(得分:3)

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

  • 1用于调用User.get_by_key_name()
  • 1用于调用UserPage ... fetch()
  • 5,循环内的每个x.page.id解除引用

另一种只对数据存储区进行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

答案 1 :(得分:1)

经过一些测试,似乎我可以使用:

 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)

答案 2 :(得分:1)

我会建议采用不同的方法,这种方法不是“关系导向”而是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