Динамически генерируемый DocType в 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_name и attribute содержат ожидаемые значения.

ЭТО РАБОТАЕТ

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.

ВОПРОС

Что может быть причиной этого? Мне непонятно, почему обе стратегии недействительны.


person The Brewmaster    schedule 24.12.2016    source источник


Ответы (2)


В вашем случае, я думаю, у него должна быть дополнительная информация для метода 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)
            ....

Таким образом, вы должны изучить оба метода __init__ и save в классе Doc, чтобы узнать, что на самом деле он делает для сохранения объекта Doc.

person DeFOX    schedule 25.12.2016

У меня возникли проблемы с воспроизведением вашего поведения, так как у меня все работает отлично:

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. Это делает все намного проще, включая синхронизацию обоих наборов данных с помощью сигналов.

person Honza Král    schedule 25.12.2016
comment
Это в основном то, что я сделал. Я сделал менеджер моделей как подкласс менеджера django (где находится мой метод, который генерирует класс). Я пытался избежать создания нового класса для каждой модели, а вместо этого просто мог добавить свой миксин. Когда НЕ используется type для создания класса, он работает нормально. - person The Brewmaster; 25.12.2016