mongoengine.DynamicEmbeddedDocument与mongoengine.DictField有什么区别?

时间:2014-09-19 16:22:47

标签: python mongoengine

可以使用mongoengine.DynamicEmbeddedDocument来利用MongoDB灵活的无架构设计。它是可扩展的,并且不对字段应用类型约束,afaik。

mongoengine.DictField同样允许使用MongoDB的无模式特性。他们只是在文档中说(w.r.t. DictField

  

这类似于嵌入式文档,但结构未定义。

这是否意味着,mongoengine.fields.DictFieldmongoengine.DynamicEmbeddedDocument完全可以互换?

编辑(更多信息):

mongoengine.DynamicEmbeddedDocument继承自mongoengine.EmbeddedDocument,代码为:

  

未存储在自己的集合中的mongoengine.Documentmongoengine.EmbeddedDocuments应通过mongoengine.Documents字段类型用作mongoengine.EmbeddedDocumentField上的字段。

mongoengine.fields.EmbeddedDocumentField

  

嵌入式文档字段 - 带有声明的document_type。只有有效值是EmbeddedDocument的子类。

这是否意味着DictFieldDynamicEmbeddedDocument不能完全互换的唯一因素是DynamicEmbeddedDocument必须通过EmbeddedDocumentField字段类型定义?

1 个答案:

答案 0 :(得分:9)

从我所看到的,两者相似,但不完全可以互换。根据您的需求,每种方法都可能略有优势。首先,正如您所指出的,这两种方法在文档中需要不同的定义,如下所示。

class ExampleDynamicEmbeddedDoc(DynamicEmbeddedDocument):
    pass

class ExampleDoc(Document):
    dict_approach = DictField()
    dynamic_doc_approach = EmbeddedDocumentField(ExampleDynamicEmbeddedDoc, default = ExampleDynamicEmbeddedDoc())

注意:默认值不是必需的,但需要将dynamic_doc_approach字段设置为ExampleDynamicEmbeddedDoc对象才能保存。 (即在设置example_doc_instance.dynamic_doc_approach = {}之后尝试保存会抛出异常)。此外,如果您不想将字段绑定到特定类型的EmbeddedDocument,则可以使用GenericEmbeddedDocumentField,但该字段仍然需要指向从EmbeddedDocument子类化的对象以便保存。

设置完成后,两者在功能上相似,因为您可以根据需要将数据保存到它们中而不受任何限制:

e = ExampleDoc()
e.dict_approach["test"] = 10
e.dynamic_doc_approach.test = 10

但是,我看到的一个主要区别是你可以查询添加到DictField的任何值,而不能使用DynamicEmbeddedDoc。

ExampleDoc.objects(dict_approach__test = 10) # Returns a QuerySet containing our entry.
ExampleDoc.objects(dynamic_doc_approach__test = 10) # Throws an exception.

话虽这么说,使用EmbeddedDocument具有验证文档中存在的字段的优点。 (我们只需要将它们添加到ExampleDynamicEmbeddedDoc定义中)。因此,我认为最好在您熟悉字段的架构时使用DynamicEmbeddedDocument,并且只预期最小化添加字段(您不需要查询)。但是,如果您不关心验证或预计会添加许多您要查询的字段,请使用DictField。