Как запросить модель отношений «многие ко многим»? - Google App Engine - PullRequest
2 голосов
/ 07 сентября 2010

Вот мои модели:

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 ]

3 голосов
/ 09 сентября 2010

Ваш ответ будет работать, но он выполнит 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 голос
/ 15 сентября 2010

Я бы порекомендовал другой подход, который менее "реляционно-ориентирован", чем ваши 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

1 голос
/ 07 сентября 2010

После некоторого тестирования кажется, что я могу использовать:

 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)
...