elasticsearch-py 无法解析复杂的自定义类的解决方案

时间:2022-05-04
本文章向大家介绍elasticsearch-py 无法解析复杂的自定义类的解决方案,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

今天在测试插入操作的时候,定义了一个拥有嵌套类的自定义类型

class A:
    pass

class B:
    pass

b = B()
b.a = A()

大致如以上代码,当然是有字段的

直接调用

es.index(index=index, doc_type=doc_type, body=b)

会报出 elasticsearch.exceptions.SerializationError Unable to serialize B 的错误

看到以上错误后,猜测 elasticsearch-py 无法解析复杂的自定义类型,于是打算自己解析成 json

def convert_to_builtin_type(obj):
    if isinstance(obj, (date, datetime)):
        return str(obj)
    else:
        dic = {}
        for att in obj.__dict__:
            value = getattr(obj, att)
            if value is object:
                dic.update(DocumentType.convert_to_builtin_type(value))
            else:
                dic[att] = value
        return dic

定义以上自定义处理方法后,调用

json.dumps(obj, default=convert_to_builtin_type)

这样 json 字符串是生成了,可是将其作为 body 进行插入的时候,又报出一个错误:

TransportError 400, 'mapper_parsing_exception', 'failed to parse datetime

当自定义类型中存在 datetime 类型的字段,经过上面自定义的处理方法后,生成的字符串与 elasticsearch-py 反序列化时的格式不同,就会报出这个错误

用 google 搜索解决方案的时候,不小心把 elasticsearch-py 的源代码搜出来了,又刚好看到它自定义的解析方法,于是把它的解析方式复制粘贴过来,问题解决。

def convert_to_builtin_type(obj):
    if isinstance(obj, (date, datetime)):
        return obj.isoformat()
    elif isinstance(obj, Decimal):
        return float(obj)
    elif isinstance(obj, uuid.UUID):
        return str(obj)
    else:
        dic = {}
        for att in obj.__dict__:
            value = getattr(obj, att)
            if value is object:
                dic.update(DocumentType.convert_to_builtin_type(value))
            else:
                dic[att] = value
        return dic