2013-06-21 60 views
1

我的应用程序以JSON格式生成日志。日志看起来像这样:将ISODate字符串转换为mongoDB本地ISODate数据类型

{"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数据类型。

有3种方法我能想到的这样做:

我)解析每个JSON日志线和转换线在应用程序代码,以ISODate类型,然后将其插入。缺点:我将不得不解析每一行,然后推送到mongoDB,这将是一个有点贵

ii)每个插入后运行查询将最后插入的文档的字符串日期时间转换为使用ISODate

element.Datetime = ISODate(element.Datetime); 

缺点:同样昂贵的,因为我会在运行每个刀片 III中的一个额外的查询)修改我在生成点日志,以便我不必在应用程序代码级别做任何分析,或每次插入后运行更新查询

此外,只是好奇,有没有一种方法可以配置mongoDB自动将日期时间字符串转换为其本机isodate格式?

TIA

编辑: 我使用pymongo用于插入JSON日志

我的文件看起来是这样的:

{ “LogLevel的”: “错误”, “日期时间”: “2013-06-21T11:20:17Z”,“模块”:“DB”,“方法”:“ExecuteSelect”,“请求”:“WS_VALIDATE”,“错误”:“过程或函数'WS_VALIDATE'期望参数' @LOGIN_ID',它没有提供。“}

有数百行像一个mentio以上内容。 这是我如何将它们插入到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

您可以控制应用程序 - 为什么不从ISODate生成日期并从头开始存储? –

+0

谢谢@AsyaKamsky。我的应用程序生成日志并将它们作为文件存储在其特定的服务器上。这些日志被移动到一个中央日志存储服务器,从那里我把日志推送到mongoDB。日志文件在字符串中有ISODate格式的时间,但是当我将日志推送到mongoDB时,它将时间数据作为一个字符串。 – texens

+0

通过使用批量插入并将文档附加到数组中,然后在数组中包含X条目时插入,可以减少插入的数量。 – Ross

回答

0

这取决于您推送日志的语言/驱动程序/实用程序。我假设你正在使用mongoimport

mongoimport不支持ISODate()。参考此问题https://jira.mongodb.org/browse/SERVER-5543 ISODate()不是JSON格式,因此在mongoimport中不受支持。 i)方法似乎更有效率。 ii)在mongo上执行两个操作:插入&更新。在将某些日志数据导入到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位的纪元。

+0

我使用pymongo,用Python推送日志。我已经添加了一个小代码样本,说明我目前正在做什么。 – texens

+0

您链接的问题不是正确的问题 - 正确的问题是https://jira.mongodb.org/browse/SERVER-5675并且已修复此问题。 –

1

此外,只是好奇,有没有一种方法可以配置mongoDB自动将日期时间字符串转换为其本机isodate格式?

您可能想要为时间戳创建Python datetime对象,并使用PyMongo插入该对象。这是作为MongoDB中的本地日期对象存储的。

因此,例如在Python:

from datetime import datetime 
object_with_timestamp = { "timestamp": datetime.now() } 
your_collection.insert(object_with_timestamp) 

当这个对象被从蒙戈外壳质疑,一个ISODate对象存在:

"timestamp" : ISODate("2013-06-24T09:29:58.615Z")

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,...

012替代许多其他“变量”

希望这有助于!

相关问题