今天在测试插入操作的时候,定义了一个拥有嵌套类的自定义类型
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