【问题标题】:Classical mapping in MongoEngineMongoEngine 中的经典映射
【发布时间】:2020-05-03 14:43:40
【问题描述】:

我是 MongoEngine 的新手,看起来我们需要从 mongoengine 创建类 Document 的子类来建模我们的数据库。我在这里有点担心,因为这违反了 SOLID 原则的依赖倒置。因此,如果稍后我需要使用另一个数据库,我将不得不更改我不应该做的领域模型类。

SQLAlchemy 通过提供漂亮的classical mapping 克服了这个问题。使用它,依赖于数据库的代码与我的域模型分离,所以我真的不需要担心数据库提供者,如果我需要更改我的数据库,我可以轻松地抽象出细节。

MongoDB 是否有类似的功能,最好是在 MongoEngine 中?

【问题讨论】:

    标签: python mongodb sqlalchemy pymongo mongoengine


    【解决方案1】:

    Pymongo 的官方doc 提供了现有 ORM/ODM 和框架的列表,但据我所知,它们都实现了Active Record Pattern(就像 django ORM),正如你所说,这违反了 SOLID 原则但已经足够好了适用于许多简单的用例。

    受 SQLAlchemy 启发的 MongoAlchemy 使用 session 的概念,因此它可能更接近您正在寻找的内容,但该项目不再维护。

    【讨论】:

      【解决方案2】:

      如果我理解正确,您正在尝试使用 mongoengine 将对象映射到文档架构。

      让我们为用户创建一个文档类:

      from mongoengine import Document, StringField
      
      
      class UserDocument(Document):
          username = StringField(required=True)
          password = StringField(required=True)
          email = StringField(required=True)
      

      现在添加一个创建新用户的类方法:

      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 从而违反了依赖倒置原则。这可以通过子类来解决。

      首先允许在 UserDocument 中继承:

      ...
      class UserDocument(Document):
          meta = {'allow_inheritance': True}
          username = StringField(required=True)
          ...
      

      接下来我们构建孩子:

      from user_document import UserDocument
      
      
      # Maps object to schema
      class User(UserDocument):
          def __init__(self, *args, **values):
              super().__init__(*args, **values)
      

      接下来添加一个create方法:

      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()
      

      现在我们的 User 对象继承了 UserDocument 字段。可以直接访问 UserDocument.new,也可以使用 User.new() 通过子级访问。

      from model import User
      
          username, password, email = 'cool username', 'super secret password', 'mrcool@example.com'
          User.create(User, username, password, email)
      

      User 对象知道 UserDocument,而后者又依赖于 mongoengine。

      如果我误解或使用了不正确的词汇来描述示例解决方案,我深表歉意。我是相对较新的人,自学成才,没有朋友会编写代码,这使得讨论变得困难。

      【讨论】:

        猜你喜欢
        • 2013-09-19
        • 1970-01-01
        • 1970-01-01
        • 2021-11-06
        • 1970-01-01
        • 2010-12-07
        • 1970-01-01
        • 1970-01-01
        • 2021-08-02
        相关资源
        最近更新 更多