У меня довольно тяжелый User
класс документа, и я хотел бы, чтобы сократить его на две части: профиль (имя и аватар) пользователя в UserProfile
документе, а остальные в User
документе, как это (используя MongoEngine):Как я могу использовать одну и ту же ObjectId для 2 коллекций, используя MongoEngine ReferenceField?
from mongoengine import *
class User(Document):
login = StringField()
password = StringField()
posts = ListField(ReferenceField("Post", dbref = False))
#... a bunch of other fields
class UserProfile(Document):
name = StringField()
avatar = URLField()
Я хотел был бы иметь тот же ObjectId как для UserProfile, так и для пользователя, так что мне нужен только один ObjectId для ссылки как на пользователя, так и на UserProfile. В конце концов, это действительно отношения «один к одному», и поскольку пользователь может создавать множество сообщений, я не хочу включать ее профиль в свои записи. При создании пользовательского документа я немедленно создаю соответствующий документ профиля следующим образом:
john = User.objects.create(login = "john", password = "super!password")
john_profile = UserProfile.objects.create(id = john.id, name = "John Smith",
avatar = "http://www.example.com/img/photo.jpg")
Пока все хорошо. Теперь у меня есть Post
документ с author
поле, которое ссылается на User
документ:
class Post(Document):
author = ReferenceField("User", dbref = False)
text = StringField()
Я хотел бы добавить author_profile
ссылку, основанную на том же ObjectId. Я попытался это:
class Post(Document):
author = ReferenceField("User", dbref = False)
author_profile = ReferenceField("User", db_field = "author", dbref = False)
text = StringField()
Но я получаю следующее исключение:
mongoengine.base.InvalidDocumentError: Multiple db_fields defined for: author
Таким образом, кажется, что я должен сделать это «вручную». Что-то вроде этого возможно:
class Post(Document):
author = ReferenceField("User", dbref = False)
text = StringField()
@property
def author_profile(self):
if hasattr(self, "_author_profile"):
return self._author_profile
self._author_profile = UserProfile.objects.get(id = self._data["author"].id)
return self._author_profile
Я думаю, это не так уж плохо, но разве нет лучшего решения?
Спасибо.
Примечание: Я прочитал mongodb documentation об отношениях один к одному, а также mongoengine ReferenceField documentation, но это не помогло мне в этом конкретном вопросе.
Почему вы не используете логин (я полагаю, что он уникален) как _id? –
Да, я могу, вы правы, но я не думаю, что он исправляет мою проблему: как я буду реализовывать 'post.author' и' post.author_profile'? Мне нужны два ReferenceFields, один указывает на пользователя, а другой указывает на UserProfile, оба с тем же идентификатором (будь то objectid или login). Вы видите мою мысль? – MiniQuark
Я никогда не работал с mongoengine, поэтому, к сожалению, я не могу с этим поделать. Кроме того, я не люблю использовать DBRef, потому что я предпочитаю управлять отношениями вручную. Я не знаю, если вы новичок в mongodb, но одна важная вещь, о которой нужно помнить, - это не проектные данные, как в реляционных базах данных. –