MongoEngine 中的经典映射
Classical mapping in MongoEngine
我是 MongoEngine 的新手,看来我们需要从 mongoengine
创建 class Document
的子 class 来为我们的数据库建模。我在这里有点担心,因为这违反了 SOLID 原则中的依赖倒置。因此,如果我以后需要使用另一个数据库,我将不得不更改我的域模型 classes,而我真的不应该这样做。
SQLAlchemy 通过提供漂亮的 classical mapping 克服了这个问题。使用它,依赖于数据库的代码从我的领域模型中分离出来,所以我真的不需要担心数据库提供者,如果我需要更改我的数据库,我可以很容易地抽象出细节。
MongoDB 是否有等效的,最好在 MongoEngine 中?
Pymongo 的官方 doc provides a list of the existing ORM/ODM and frameworks but to my knowledge they all implement the Active Record Pattern(就像 django ORM),正如你所说,它违反了 SOLID 原则,但对于许多简单的用例来说已经足够好了。
受 SQLAlchemy 启发的 MongoAlchemy 使用 session 的概念,因此它可能更接近您正在寻找的内容,但该项目不再维护。
如果我理解正确,您正在尝试使用 mongoengine 将 object 映射到文档架构。
让我们为用户创建文档class:
from mongoengine import Document, StringField
class UserDocument(Document):
username = StringField(required=True)
password = StringField(required=True)
email = StringField(required=True)
现在添加一个 class 创建新用户的方法:
from mongoengine import disconnect, connect, Document, StringField
class UserDocument(Document):
username = StringField(required=True)
password = StringField(required=True)
email = StringField(required=True)
@classmethod
def new(cls):
data = UserDocument(username=cls.username, password=cls.password, email=cls.email)
connect('test_collection')
data.save()
disconnect('test_collection')
据我了解你的问题,你在这个例子中的问题是 UserDocument 会知道 mongoengine 从而违反了依赖倒置原则。这可以用 child class.
来解决
首先在UserDocument中允许继承:
...
class UserDocument(Document):
meta = {'allow_inheritance': True}
username = StringField(required=True)
...
接下来我们构建 child:
from user_document import UserDocument
# Maps object to schema
class User(UserDocument):
def __init__(self, *args, **values):
super().__init__(*args, **values)
接下来添加创建方法:
from user_document import UserDocument
# Maps object to schema
class User(UserDocument):
def __init__(self, *args, **values):
super().__init__(*args, **values)
def create(self, username, password, email):
self.username, self.password, self.email = username, password, email
User.new()
现在我们的用户 object 继承了 UserDocument 字段。 UserDocument.new 可以直接访问或通过 child 和 User.new() 访问。
from model import User
username, password, email = 'cool username', 'super secret password', 'mrcool@example.com'
User.create(User, username, password, email)
用户 object 知道 UserDocument 又依赖于 mongoengine。
如果我误解或使用了不正确的词汇来描述示例解决方案,我深表歉意。我比较新,self-taught,没有写代码的朋友,讨论起来很困难。
我是 MongoEngine 的新手,看来我们需要从 mongoengine
创建 class Document
的子 class 来为我们的数据库建模。我在这里有点担心,因为这违反了 SOLID 原则中的依赖倒置。因此,如果我以后需要使用另一个数据库,我将不得不更改我的域模型 classes,而我真的不应该这样做。
SQLAlchemy 通过提供漂亮的 classical mapping 克服了这个问题。使用它,依赖于数据库的代码从我的领域模型中分离出来,所以我真的不需要担心数据库提供者,如果我需要更改我的数据库,我可以很容易地抽象出细节。
MongoDB 是否有等效的,最好在 MongoEngine 中?
Pymongo 的官方 doc provides a list of the existing ORM/ODM and frameworks but to my knowledge they all implement the Active Record Pattern(就像 django ORM),正如你所说,它违反了 SOLID 原则,但对于许多简单的用例来说已经足够好了。
受 SQLAlchemy 启发的 MongoAlchemy 使用 session 的概念,因此它可能更接近您正在寻找的内容,但该项目不再维护。
如果我理解正确,您正在尝试使用 mongoengine 将 object 映射到文档架构。
让我们为用户创建文档class:
from mongoengine import Document, StringField
class UserDocument(Document):
username = StringField(required=True)
password = StringField(required=True)
email = StringField(required=True)
现在添加一个 class 创建新用户的方法:
from mongoengine import disconnect, connect, Document, StringField
class UserDocument(Document):
username = StringField(required=True)
password = StringField(required=True)
email = StringField(required=True)
@classmethod
def new(cls):
data = UserDocument(username=cls.username, password=cls.password, email=cls.email)
connect('test_collection')
data.save()
disconnect('test_collection')
据我了解你的问题,你在这个例子中的问题是 UserDocument 会知道 mongoengine 从而违反了依赖倒置原则。这可以用 child class.
来解决首先在UserDocument中允许继承:
...
class UserDocument(Document):
meta = {'allow_inheritance': True}
username = StringField(required=True)
...
接下来我们构建 child:
from user_document import UserDocument
# Maps object to schema
class User(UserDocument):
def __init__(self, *args, **values):
super().__init__(*args, **values)
接下来添加创建方法:
from user_document import UserDocument
# Maps object to schema
class User(UserDocument):
def __init__(self, *args, **values):
super().__init__(*args, **values)
def create(self, username, password, email):
self.username, self.password, self.email = username, password, email
User.new()
现在我们的用户 object 继承了 UserDocument 字段。 UserDocument.new 可以直接访问或通过 child 和 User.new() 访问。
from model import User
username, password, email = 'cool username', 'super secret password', 'mrcool@example.com'
User.create(User, username, password, email)
用户 object 知道 UserDocument 又依赖于 mongoengine。
如果我误解或使用了不正确的词汇来描述示例解决方案,我深表歉意。我比较新,self-taught,没有写代码的朋友,讨论起来很困难。