我有一个相当繁重的User
文档类,我想将它分成两部分:用户的个人资料(姓名和头像)位于UserProfile
文档中,其余部分位于{{} 1}}文档,像这样(使用MongoEngine):
User
我想为UserProfile和User提供相同的ObjectId,因此我只需要一个ObjectId来引用User和UserProfile。毕竟,这真的是一对一的关系,而且由于用户可以创作很多帖子,我不想将自己的个人资料嵌入帖子本身。在创建用户文档时,我会立即创建相应的配置文件,如下所示:
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()
到目前为止一切顺利。现在我有一个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
我想基于相同的ObjectId添加class Post(Document):
author = ReferenceField("User", dbref = False)
text = StringField()
引用。我试过这个:
author_profile
但我得到以下例外:
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
我想这不是那么糟糕,但是没有更好的解决方案吗?
感谢。
注意:我阅读了关于一对一关系的mongodb documentation以及mongoengine ReferenceField documentation,但它对这个具体问题没有帮助。
答案 0 :(得分:0)
您必须存储两次相同的ID才能执行此操作:
class Post(Document):
author = ReferenceField("User", dbref = False)
author_profile = ReferenceField("UserProfile", dbref = False)
text = StringField()
我不确定这是否会给您的解决方案带来任何好处 - 解除引用的查询数量可能会有所改善,但我必须对其进行测试!
答案 1 :(得分:0)
我最后写了这个:
def user_profile(reference_name):
attrib_name = "_" + reference_name + "_profile"
def user_profile_getter(self):
if not hasattr(self, attrib_name):
reference = self._data.get(reference_name, None)
if not reference:
return None
setattr(self, attrib_name, UserProfile.objects.get(reference.id))
return getattr(self, attrib_name)
return property(user_profile_getter)
我的Post
课程现在看起来像这样:
class Post(Document):
author = ReferenceField("User", dbref = False)
author_profile = user_profile("author")
text = StringField()
每当我添加指向ReferenceField
类的User
时,我也会添加user_profile
(只读)引用。请注意,如果您只访问author_profile
,则不会加载author
,反之亦然。