我的应用程序以JSON格式生成日志。日志看起来像这样:
{"LogLevel":"error","Datetime":"2013-06-21T11:20:17Z","Module":"DB","Method":"ExecuteSelect","Request":"WS_VALIDATE","Error":"Procedure or function 'WS_VALIDATE' expects parameter '@LOGIN_ID', which was not supplied."}
目前,我正在推进上述日志行,因为它是进入mongoDB的。但是mongoDB将Datetime存储为字符串(这是预期的)。既然我想在这些日志上运行一些数据处理工作,我宁愿将Datetime存储为mongoDB的本机ISODate数据类型。
我有三种方法可以考虑这样做:
i)解析每个JSON日志行并将字符串转换为应用程序代码中的ISODate类型,然后插入它。缺点:在将其推送到mongoDB之前,我必须解析每一行,这将是一个有点贵的
ii)每次插入后运行一个查询,使用
将最后插入的文档的字符串日期时间转换为ISODateelement.Datetime = ISODate(element.Datetime);
缺点:再次昂贵,因为我将为每个插入运行一个额外的查询 iii)在生成点修改我的日志,这样我就不必在应用程序代码级别进行任何解析,或者在每次插入后运行更新查询
另外,只是好奇,有没有办法可以配置mongoDB自动将日期时间字符串转换为其原生的isodate格式?
TIA
编辑: 我正在使用pymongo插入json日志
我的文件看起来像这样:
{ “LogLevel的”: “错误”, “日期时间”: “2013-06-21T11:20:17Z”, “模块”: “DB”, “方法”: “的ExecuteSelect”, “请求”:“WS_VALIDATE “,”错误“:”过程或函数'WS_VALIDATE'需要参数'@LOGIN_ID',这是未提供的。“}
上面提到的数百行。 这就是我将它们插入mongodb的方式:
for line in logfile:
collection.insert(json.loads(line))
以下将解决我的问题:
for line in logfile:
data = json.loads(line)
data["Datetime"] = datetime.strptime(data["Datetime"], "%Y-%M-%DTHH:mmZ")
collection.insert(data)
我想要做的是摆脱我必须在上面做的日期时间的额外操作。希望这能澄清问题。
答案 0 :(得分:2)
看起来你已经有了答案......我会坚持:
for line in logfile:
data = json.loads(line)
data["Datetime"] = datetime.strptime(data["Datetime"], "%Y-%M-%DTHH:mmZ")
collection.insert(data)
我遇到了类似的问题,但我事先并不知道应该用datetime对象替换它。所以我将我的json信息更改为:
{"LogLevel":"error","Datetime":{"__timestamp__": "2013-06-21T11:20:17Z"},"Module":"DB","Method":"ExecuteSelect","Request":"WS_VALIDATE","Error":"Procedure or function 'WS_VALIDATE' expects parameter '@LOGIN_ID', which was not supplied."}
并用以下内容解析json:
json.loads(data, object_hook=logHook)
将'logHook'定义为:
def logHook(d):
if '__timestamp__' in d:
return datetime.strptime(d['__timestamp__'], "%Y-%M-%DTHH:mmZ")
return d
此 logHook 函数也可以扩展为用 elif,elif 替换许多其他“变量”......
希望这有帮助!
答案 1 :(得分:1)
另外,只是好奇,有没有办法可以配置mongoDB自动将日期时间字符串转换为其原生的isodate格式?
您可能希望为时间戳创建一个Python datetime
对象,并使用PyMongo插入它。它作为MongoDB中的本机日期对象存储在引擎盖下。
所以,例如在Python中:
from datetime import datetime
object_with_timestamp = { "timestamp": datetime.now() }
your_collection.insert(object_with_timestamp)
当从Mongo shell查询此对象时,会出现一个ISODate对象:
"timestamp" : ISODate("2013-06-24T09:29:58.615Z")
答案 2 :(得分:0)
这取决于您推送日志的语言/驱动程序/实用程序。我假设你正在使用 mongoimport 。
mongoimport 不支持ISODate()。请参阅此问题https://jira.mongodb.org/browse/SERVER-5543 ISODate()不是JSON格式,因此 mongoimport 不支持。
i)方法似乎更有效率。 ii)对mongo做两个动作:insert&更新。将一些日志数据导入mongo时遇到了同样的问题。我最终将ISO 8601格式的日期转换为纪元格式。
{"LogLevel":"error","Datetime":{"$date" : 1371813617000},"Module":"DB","Method":"ExecuteSelect","Request":"WS_VALIDATE","Error":"Procedure or function 'WS_VALIDATE' expects parameter '@LOGIN_ID', which was not supplied."}
以上JSON应该可行。请注意,它是64位而不是32位纪元。