将ISODate字符串转换为mongoDB本机ISODate数据类型

时间:2013-06-21 13:27:53

标签: mongodb pymongo isodate

我的应用程序以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)每次插入后运行一个查询,使用

将最后插入的文档的字符串日期时间转换为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',这是未提供的。“}

上面提到的数百行。 这就是我将它们插入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)

我想要做的是摆脱我必须在上面做的日期时间的额外操作。希望这能澄清问题。

3 个答案:

答案 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位纪元。