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,没有写代码的朋友,讨论起来很困难。