【问题标题】:MongoDB date and removed objectsMongoDB 日期和删除对象
【发布时间】:2012-06-17 09:45:07
【问题描述】:

昨天我对 MongoDB 有一些奇怪的体验。我正在使用 twisted 和 txmongo - mongodb 的异步驱动程序(类似于 pymongo)。

我有一个休息服务,它接收一些数据并将其放入 mongodb。一个字段是以毫秒为单位的时间戳,13 位。

首先,在 python 中将毫秒时间戳转换为 python 日期时间并非易事。我最终得到了这样的结果:

def date2ts(ts):
    return int((time.mktime(ts.timetuple()) * 1000) + (ts.microsecond / 1000))


def ts2date(ts):
    return datetime.datetime.fromtimestamp(ts / 1000) + datetime.timedelta(microseconds=(ts % 1000))

问题是,当我将数据保存到 mongodb 时,检索日期时间并使用我的函数将其转换回时间戳,但在毫秒内没有得到相同的结果。

我不明白为什么会这样。日期时间作为 ISODate 对象保存在 mongodb 中。我试图从 shell 查询它,确实有一秒或几毫秒的差异。

问题 1:有人知道为什么会这样吗?

但这还没有结束。我决定不使用 datetime 并直接保存时间戳。在此之前,我从集合中删除了所有数据。我很惊讶当我尝试保存相同的字段而不是日期时,它在 shell 中表示为 ISODate。当检索到时,仍然存在几毫秒的差异。

我试图删除集合和索引。当它没有帮助时,我试图删除整个数据库。当它没有帮助时,我尝试删除整个数据库并重新启动 mongod。在此之后,我猜它开始将其保存为 Long。

问题 2:有人知道为什么会这样吗?

谢谢!

【问题讨论】:

    标签: python mongodb datetime twisted pymongo


    【解决方案1】:

    可能是不同时区的情况。请使用下面提到的功能来纠正它。

    function time_format(d, offset) {
        // Set timezone
        utc = d.getTime() + (d.getTimezoneOffset() * 60000);
        nd = new Date(utc + (3600000*offset));
        return nd;
    }
    
    searchdate = time_format(searchdate, '+5.5');
    

    这里的'+5.5'是本地时间与格林威治标准时间的时差。

    【讨论】:

    • 嗨。这是可能的。但我认为情况并非如此。因为 mongo 和 app 在同一台服务器上,并且相差几秒甚至几分钟。看起来是精度问题。
    【解决方案2】:

    Python 的时间戳从 1970 年 1 月 1 日的 Unix 纪元开始以 为单位计算。另一方面,JavaScript(以及 MongoDB)中的时间戳以 毫秒为单位

    也就是说,如果您手头只有时间戳,您可以将 Python 值乘以 1000 以获得毫秒并将该值存储到 MongoDB 中。同样,您可以从 MongoDB 中获取值并将其除以 1000 以使其成为 Python 时间戳。请记住,Python 似乎只关心小数点后的两位有效数字而不是三位(因为它通常不关心毫秒),所以如果您仍然有

    通常我会建议使用元组来代替,但是每种语言的值范围的约定是不同的(JavaScript 不直观,因为它以 0 而不是 1 开始一个月的几天),并且可能会导致问题。

    【讨论】:

    • 我需要以毫秒为单位存储,以便按时间戳字段进行精确查询。我认为最简单的方法是尽可能长地存储时间戳。
    • "Python 的时间戳以秒为单位计算" datetime 有一个微秒字段,实际上可以存储毫秒时间戳。我猜 txmongo 驱动程序做错了。
    • 发现这条评论pymongo driver sources: datetime.datetime 实例保存时将四舍五入到最接近的毫秒
    • 让我们采取不同的方法:您到底想达到什么目标?您能解释一下需要“按时间戳字段进行精确查询”是什么意思吗?有了这些信息,我们可以帮助您得到一个不会出现舍入错误的答案。
    • 我的意思是我通过它的创建日期(和 author_id)来识别一些对象。创建日期必须以毫秒为单位,因此我可以或多或少自信地进行如下查询:db.content.remove({"author_id": author_id, "creation_date": ts }),并且我希望能够在同一 creation_date 字段上进行日期查询,例如 db.content.find({"creation_date": { $gt: start, $lt: end} })
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多