Python Elasticsearch无法解析作为对象来自pymongo的datetime字段
我正在尝试使用pymongo和Python客户端Elasticsearch将数据从mongoDB流式传输到Elasticsearch 我已经设置了一个映射,我在这里报告与感兴趣的字段相关的代码片段: “更新地址”:{ “类型”:“日期”, “格式”:“dateOptionalTime” } 我的脚本使用pymongo从MongoDB中获取每个文档,并尝试将其索引到Elasticsearch中Python Elasticsearch无法解析作为对象来自pymongo的datetime字段,python,mongodb,
elasticsearch,pymongo,Python,Mongodb,
elasticsearch,Pymongo,我正在尝试使用pymongo和Python客户端Elasticsearch将数据从mongoDB流式传输到Elasticsearch 我已经设置了一个映射,我在这里报告与感兴趣的字段相关的代码片段: “更新地址”:{ “类型”:“日期”, “格式”:“dateOptionalTime” } 我的脚本使用pymongo从MongoDB中获取每个文档,并尝试将其索引到Elasticsearch中 from elasticsearch import Elasticsearch from pymongo
from elasticsearch import Elasticsearch
from pymongo import MongoClient
mongo_client = MongoClient('localhost', 27017)
es_client = Elasticsearch(hosts=[{"host": "localhost", "port": 9200}])
db = mongo_client['my_db']
collection = db['my_collection']
for doc in collection.find():
es_client.index(
index='index_name',
doc_type='my_type',
id=str(doc['_id']),
body=json.dumps(doc, default=json_util.default)
)
我在运行时遇到的问题是:
elasticsearch.exceptions.RequestError:TransportError(400,u'MapperParsingException[未能解析[Update_at]];嵌套:ElasticsearchIllegalArgumentException[未知属性[$date]];')
我认为问题的根源在于pymongo将更新的字段作为datetime.datetime对象序列化,如果我在for循环中打印文档,我可以看到:
更新时间:datetime.datetime(2014,8,31,17,18,13,17000)
这与Elasticsearch查找映射中指定的日期类型的对象相冲突
有什么办法可以解决这个问题吗?您走的是正确的道路,您的Python
datetime
需要序列化为日期字符串。因此,您需要在json.dumps()调用中添加CustomEncoder
。首先,将您的CustomEncoder
声明为jsonecoder
的子类,该子类将处理datetime
和time
属性的转换,但将其余部分委托给其超类:
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.strftime('%Y-%m-%dT%H:%M:%S%z')
if isinstance(obj, time):
return obj.strftime('%H:%M:%S')
if hasattr(obj, 'to_json'):
return obj.to_json()
return super(CustomEncoder, self).default(obj)
然后您可以在json.dumps
调用中使用它,如下所示:
...
body=json.dumps(doc, default=json_util.default, cls=CustomEncoder)
...
我猜你的问题是你在使用
body=json.dumps(doc, default=json_util.default)
但你应该使用
body=doc
这样做对我来说是可行的,因为elasticsearch似乎关心将字典的别名转换成JSON文档(当然,假设doc是一个字典,我猜是这样)
至少在我使用的elasticsearch版本(2.x)中,datetime.datetime的别名是正确的,不需要映射。例如,这对我很有用:
doc = {"updated_on": datetime.now(timezone.utc)}
res = es.index(index=es_index, doc_type='my_type',
id=1, body=doc)
Kibana将其识别为日期。这解决了datetime对象的序列化问题:正文中的字段现在是“updated_at”:{“$date”:1409505493017}。然而,我得到了同样的错误,所以这个问题肯定是其他一些问题。