【问题标题】:How to handle ReferenceField migration with flask mongoengine?如何使用烧瓶 mongoengine 处理 ReferenceField 迁移?
【发布时间】:2019-12-09 15:22:13
【问题描述】:

我已经用 mongodb 实现了一个简单的烧瓶应用程序,现在需要一些升级。

假设有一个 Foo 的类模型和一个 Bar 的类模型,其中有一个 Foo 的引用字段

class Foo(Document):
  title = StringField()

class Bar(Document):
  name = StringField()
  foo = ReferenceField('Foo')

让烧瓶应用程序运行一段时间,这样现在数据库中有一些数据。

由于需求变化,我们需要重构 Foo 类,从一个新的超类继承它:

class SuperFoo(Document):
  meta = { 'allow_inheritance': True,}
  #[...]

class Foo(SuperFoo):
  #[...]

class Bar(Document):
  name = StringField()
  foo = ReferenceField('Foo')

上面的代码适用于空数据库。

但是如果其中有一些数据,当烧瓶管理员尝试显示 Bar 实例(在编辑模式下)时,mongoengine 会引发异常

File "[...]/site-packages/mongoengine/fields.py", line 1124, in __get__
    raise DoesNotExist('Trying to dereference unknown document %s' % value)
mongoengine.errors.DoesNotExist: Trying to dereference unknown document DBRef('super_foo', ObjectId('5617a08939c6c70cbaa2af6e'))

我想数据模型需要以某种方式迁移。

怎么做?

谢谢, 亚历山德罗。

【问题讨论】:

    标签: python mongoengine flask-admin flask-mongoengine


    【解决方案1】:

    经过一点分析,我想解决这个问题。

    Mongoengine 创建一个新集合super_foo

    每个继承类的文档都进入这个super_foo 集合,并带有一个附加属性_cls。 该值是该类的 CamelCased 层次结构路径。在此示例中,文档将具有

    '_cls': 'SuperFoo.Foo' 字段。

    我所做的是将旧 foo 集合中的每个文档复制到新的 super_foo 集合中,并将字段 {'_cls': u'SuperPlesso.Plesso'} 添加到每个集合中。

    迁移函数应该如下所示:

    def migrationFunc():
        from pymongo.errors import DuplicateKeyError
        from my.app import models
    
        _cls = {'_cls': u'SuperFoo.Foo'}
    
        fromOldCollection = models.Foo._collection
        toSuperCollection = models.Superfoo._collection
    
        for doc in fromOldCollection.find():
            doc.update(_cls)
            try:
                toSuperCollection.insert(doc)
            except DuplicateKeyError:
                logger.error('...')
    

    然后我用实际的新层次结构更新了模型的基本代码:

    class SuperFoo(Document):
      meta = { 'allow_inheritance': True,}
      #[...]
    
    # was class Foo(Document)
    class Foo(SuperFoo):
      #[...]
    

    所有在Bar 集合或其他地方对Foo 的反向引用都会被保留。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多