mongodb 在Mongoengine中对单独集合中的文档进行子类化

ohfgkhjo  于 2023-03-01  发布在  Go
关注(0)|答案(3)|浏览(160)

我在Mongoengine中有一个集合,其中包含一些文档的字段列表很长:

class Component(Document):
    name = StringField(unique=True)
    title = StringField(required=True)
    description = StringField(default='')
    # And so on...

现在我需要另一个类似于第一个集合的集合,但有一些额外的东西,所以我在第一个集合中使用allow_inheritance进行子类化:

class Component(Document):
    name = StringField(unique=True)
    title = StringField(required=True)
    description = StringField(default='')
    # And so on...
    meta = {'allow_inheritance': True}

class ChildComponent(Component):
    extra_stuff = StringField()

但是正如文档中提到的,这样所有的数据都将保存在同一个集合中。
所以我尝试将abstract添加到父文档的meta中,这样我就可以有两个独立的集合。

class Component(Document):
    name = StringField(unique=True)
    title = StringField(required=True)
    description = StringField(default='')
    # And so on...
    meta = {'allow_inheritance': True, 'abstract': True}

但是现在,当我尝试使用Component.objects().all()Component获取文档时,我得到了这个错误:
属性错误:类型对象"Component"没有属性"objects"
我应该创建一个基本文档并从中抽象出我的两个集合,还是有更简单的方法来解决这个问题?

    • 更新**

即使我创建了一个基类并从它继承了这两个类:

class BaseComponent(Document):
    name = StringField(unique=True)
    title = StringField(required=True)
    description = StringField(default='')
    # And so on...
    meta = {'allow_inheritance': True, 'abstract': True}

class Component(BaseComponent):
    pass

class ChildComponent(BaseComponent):
    extra_stuff = StringField()

当我尝试Component.objects.all()时,结果将是和空列表。

    • UPDATE 2**如果我用.save()添加一个component,我可以用Component.objects.all()得到那个。但是已经保存在那个集合中的其余文档怎么办?我如何恢复它们?
tjjdgumg

tjjdgumg1#

由于我没有得到答案,我找到了一个解决方法。当在 meta中使用abstract时,子集合会得到一个额外的字段_cls,其值为集合名称。因此,我使用pymongo更新现有文档,使其具有_cls字段,其值等于集合名称,如下所示:

db["component"].update_many({}, {"$set": {"_cls": "Component"}}, upsert=False, array_filters=None)

完成这些操作后,现在我可以使用mongoengine Component.objects().all()查询获取文档。

2vuwiymt

2vuwiymt2#

只需使用'abstract': True并删除'allow_inheritance': True。更多详细信息请参见此。

mxg2im7a

mxg2im7a3#

我有非常相同的问题,Vahid Panahianswer是好的,我已经试过了。完整的例子在这里与可选的集合名称:

from mongoengine import *

connect('test')

class BaseTest(Document):
    _id = ObjectIdField()
    name = StringField()

    meta = {
        'abstract': True,
        'allow_inheritance': True
    }

class Test(BaseTest):
    pass
    # meta = {
    #     'collection': 'Test',
    # }

class TestExtended(BaseTest):
    text = StringField()

    # meta = {
    #     'collection': 'TestExtended'
    # }

model1 = Test()
model1.name = 'foo'
model1.save()

model2 = TestExtended()
model2.name = 'bar'
model2.text = 'foo bar story'
model2.save()

for model in Test.objects.all():
    print(f"Test: {model.name}")
for model in TestExtended.objects.all():
    print(f"TestExtended: {model.name}")

将打印:

Test: foo
TestExtended: bar

实际上模型被存储在不同的集合中。

相关问题