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