在Elasticsearch DSL中动态生成DocType

时间:2016-12-24 21:01:47

标签: python elasticsearch kwargs setattr elasticsearch-dsl

我正在生成一个DocType类,用于根据我的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)

发生这种情况时,文档保存,但是,我的所有属性都没有设置。这只是一个空文件。

我已调试代码以确认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

问题

可能导致这种情况的原因是什么?对我来说,为什么两种策略都无效是没有意义的。

2 个答案:

答案 0 :(得分:1)

在我的情况下,我想,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类中的__init__save方法,以了解它是如何保留Doc对象的。

答案 1 :(得分:1)

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

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时,我通常所做的就是直接在生成to_search实例的Model上使用DocType或类似的方法。它使一切变得如此简单,包括使用信号同步两个数据集。