前文
在用es.scan的时候,意外发现报错,而相关的错误网上没有资料可查,阅读官网也只是标明了通过raise_on_error来控制是否报出错误,但本身用es.scan就是为了大数据量的时候保证数据的完整性,如果跳过异常,那不是数据完整性得不到保证了,所以还是得确认问题异常。
问题排查
通过堆栈异常:
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/search.py", line 223, in _get_result
return callback(hit)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/utils.py", line 413, in from_es
doc._from_dict(data)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/utils.py", line 420, in _from_dict
v = f.deserialize(v)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/field.py", line 95, in deserialize
return self._deserialize(data)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/field.py", line 190, in _deserialize
return self._wrap(data)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/field.py", line 167, in _wrap
return self._doc_class.from_es(data, data_only=True)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/document.py", line 105, in from_es
return super(InnerDoc, cls).from_es(data)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/utils.py", line 413, in from_es
doc._from_dict(data)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/utils.py", line 420, in _from_dict
v = f.deserialize(v)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/field.py", line 95, in deserialize
return self._deserialize(data)
File "/root/lyb/py3/lib/python3.6/site-packages/elasticsearch_dsl/field.py", line 317, in _deserialize
return int(data)
ValueError: invalid literal for int() with base 10: ''
可以确认是在scan内部报的异常,所以是第三方库的异常,第三方库的异常要么通过升级第三方库,要么通过定位到问题来绕过该报错。明显选择第二种思路,途中的int(data)报错,也就是data并不是数字字符串,而是空字符串’',导致在int的时候无法识别报错。但遗憾的是,没有标记出是哪个字段导致。
此时最快的就是通过将记录定位到,然后通过查找""在该记录里面对应的字段,然后再查该字段是否是integer或者long类型即可。
问题解决
在思路未清晰的时候,需要花大量的时间去定位es第三方库,但如果定位到是字段的异常,那就一切简单了;而es在bulk insert的时候,是没有在python端做这个校验,而在es.scan的时候去做了该校验