Elasticsearch DSL 中动态生成的 DocType

Dynamically generated DocType in Elasticsearch DSL

我正在生成 DocType class 用于基于我的 ORM 构建映射和保存文档。

def get_doc_type(self):
    attributes = {}

    ...
    # Build attributes dictionary here

    DT = type('DocType', (DocType,), attributes)
    return DT

这看起来工作正常,我在映射方面没有任何问题。我的问题是当我尝试保存文档时。

这行不通

Doc = get_doc_type()

for instance in queryset:
    doc = Doc()
    for field_name in fields:
        attribute = getattr(instance, field_name, None)
        setattr(doc, field_name, attribute)
    doc.save(index)

发生这种情况时,文档 得到保存,但是,我的 none 属性已设置。这只是一个空文档。

我已调试代码以确认 field_nameattribute 包含我期望的值。

这行得通

Doc = self.get_doc_type()

for instance in queryset:
    kwargs = {}

    for field_name in fields:
        attribute = getattr(instance, field_name, None)
        kwargs.update({field_name: attribute})

    doc = Doc(**kwargs)
    doc.save(index=index)

当我使用此策略时,文档按预期保存,所有信息和 attributes 已从我的 instance 传递到 doc.

问题

这可能是什么原因造成的?我不明白为什么这两种策略都无效。

我想在你的情况下,它必须有一些更多的信息供 save() 方法知道应该存储哪个 field_name

可能是这样的:

    class Doc(object):
        def __init__(self, **kwargs):
            self.fields_valid = kwargs.copy()
            ...
        ...
        def save(self, index=None):
            ...
            for field in self.fields_valid:
                do_save(field)
            ....

因此,您应该查看 Doc class 中的 __init__save 方法,以了解它实际上做了什么来持久化 Doc 对象。

我无法复制你的行为,因为一切对我来说都很好:

class DT(DocType):
    pass

dt = DT()

for x in range(10):
    setattr(dt, 'i_%i' % x, x)
dt.save()

DT.search().execute()[0].to_dict()

完全符合我的预期。如果它对您不起作用,您能否在 github 上提出问题,因为在这种情况下出现问题。谢谢!

顺便说一句,当从 ORM 序列化到 elaasticsearch-dsl 时,我通常做的是在 Model 上直接使用 to_search 或类似方法生成 DocType 实例.它使一切变得如此简单,包括使用信号同步两个数据集。