我有一個相當重要的文檔類User
,我想將它分成兩部分:UserProfile
文檔中的用戶配置文件(名稱和頭像),其餘部分位於User
文檔中,如下所示(使用MongoEngine):如何使用MongoEngine ReferenceField爲2個集合使用相同的ObjectId?
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()
我想爲UserProfile和User都有相同的ObjectId,這樣我只需要一個ObjectId即可引用User和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? – 2013-04-05 12:12:09
是的,我可以,你是對的,但我不認爲它解決了我的問題:我將如何實現'post.author'和'post.author_profile'?我需要兩個ReferenceFields,一個指向User,另一個指向UserProfile,它們都具有相同的ID(無論是objectid還是login)。你看到我的觀點了嗎? – MiniQuark 2013-04-05 19:25:03
我從來沒有與mongoengine合作過,所以不幸的是我無法幫助你。另外,我不喜歡使用DBRef,因爲我更喜歡手動控制關係。我不知道你是否對mongodb是陌生的,但需要記住的一點是,關係數據庫不是設計數據。 – 2013-04-09 11:41:47