2

我的应用程序生成 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 数据类型。

我可以想到 3 种方法来做到这一点:

i) 解析每个 JSON 日志行并将字符串转换为应用程序代码中的 ISODate 类型,然后将其插入。缺点:在将其推送到 mongoDB 之前,我必须解析每一行,这会有点贵

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

element.Datetime = ISODate(element.Datetime);

缺点:再次昂贵,因为我将在每次插入时运行一个额外的查询 iii) 在生成点修改我的日志,这样我就不必在应用程序代码级别进行任何解析,或者在每次插入后运行更新查询

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

TIA

编辑:我正在使用 pymongo 插入 json 日志

我的文件看起来像这样:

{"LogLevel":"error","Datetime":"2013-06-21T11:20:17Z","Module":"DB","Method":"ExecuteSelect","Request":"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)

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

4

3 回答 3

2

Looks like you already have the answer... I would stick with:

for line in logfile:
    data = json.loads(line)
    data["Datetime"] = datetime.strptime(data["Datetime"], "%Y-%M-%DTHH:mmZ")
    collection.insert(data)

I had a similar problem, but I didn't known beforehand where I should replace it by a datetime object. So I changed my json information to something like:

{"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."}

and parsed json with:

json.loads(data, object_hook=logHook)

with 'logHook' defined as:

def logHook(d):
    if '__timestamp__' in d:
        return datetime.strptime(d['__timestamp__'], "%Y-%M-%DTHH:mmZ")
    return d

This logHook function could also be extended to replace many other 'variables' with elif, elif, ...

Hope this helps!

于 2013-11-12T01:56:10.537 回答
1

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

您可能想datetime为时间戳创建一个 Python 对象,并使用 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")

于 2013-06-24T16:35:17.020 回答
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 位纪元。

于 2013-06-21T15:51:30.513 回答