2016-01-03 2 views
1

Я пытаюсь mongoengine в колбе (python). И пытался создать поле «один-к-одному».Mongoengine - добраться туда, куда направлен объект

У меня есть модель User, а также модели для типов пользователей, как Author, Buyer и т.д. Вот простой вариант моих моделей:

class User(db.Document): 
    username = db.StringField() 
    password = db.StringField() 

class Author(db.Document): 
    books = db.ListField(db.StringField()) 
    user = db.ReferenceField(document_type=User, required=True) 

Теперь я могу получить пользователь от автора, просто

a = author.objects.all()[0] # Or get author through some other method 
a.user 

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

u = user.objects.all()[0] 
u.get_author() # ??? 

Я знаю, что могу сделать Author.objects.get(user=u), но мне было интересно, если это может быть сделано без дополнительного запроса.

ответ

1

Ваши документы User хранятся в отдельной коллекции без ссылки на коллекцию Author, поэтому нет никакого способа сделать это без дополнительного запроса. У вас есть несколько вариантов, которые могут сделать этот процесс проще:

Добавить свойство автора к User класса:

class User(db.Document): 
    username = db.StringField() 
    password = db.StringField() 

    @property 
    def author(self): 
     return Author.objects(user=self).get() 

class Author(db.Document): 
    books = db.ListField(db.StringField()) 
    user = db.ReferenceField(document_type=User, required=True) 

Это позволит вам сделать:

u = User.objects.first() 
print(u.author.books) 

Тем не менее, кажется, что в этом контексте, когда автором является только особый тип User, тогда вы должны использовать document inheritance, например:

class User(db.Document): 
    username = db.StringField() 
    password = db.StringField() 

    meta = {'allow_inheritance': True} 

class Author(User): 
    books = db.ListField(db.StringField()) 

a = Author(username="dr_seuss", password="sneech16", 
      books=["Green Eggs and Ham","The Cat in the Hat"]) 
a.save() 

Это позволит вам запрашивать либо Author или User:

>>> Author.objects.first().username 
'dr_seuss' 

>>> User.objects.first().username 
'dr_seuss' 
+0

Хорошая идея о недвижимости! К сожалению, нет никакого способа сделать это без дополнительного запроса. (Пример пользователя автора был упрощенным примером, и в моем реальном случае я не могу реализовать наследование документов.) – AbdealiJK

+0

Если вас больше беспокоит оптимизация чтения, чем оптимизация записи, вы всегда можете сохранить ссылку в обоих документах на момент написания. –