【问题标题】:MongoDB query Date field with the server timeMongoDB查询日期字段与服务器时间
【发布时间】:2017-12-19 13:12:06
【问题描述】:

我有 mongo 文档,其字段包含我使用 $currentDate 插入的日期,因此当我插入文档时该字段具有 mongo 服务器日期。 我想查询和过滤所有日期字段和服务器日期之间的差异超过10分钟的文档。

假设这个数据库:

{ "_id" : 1, "item" : "abc", "price" : 10, "fee" : 2, "discount" : 5, "date" : ISODate("2017-07-14T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "fee" : 1, "discount" : 2, "date" : ISODate("2017-07-14T08:05:00Z") }

假设我将在“2017-07-14T08:10:01Z”服务器日期运行查询, 我希望查询只返回第一项。

db.items.aggregate([
{$project : {lut : {$subtract: ["** server date **", "$date" ]}}}, 
{$match : { lut : {$gte : 10*60*1000 }}} ]);

我在运行查询时如何获取服务器日期? 我正在从我的 nodeJS 服务器运行查询,用 new Date() 替换服务器日期将获取节点服务器的日期,而不是 mongo 服务器的日期。

【问题讨论】:

    标签: node.js mongodb node-mongodb-native mongojs


    【解决方案1】:

    这比乍看之下要复杂得多。当涉及复制和分片时,很难保证所有 Mongo 实例上的时钟之间的完美同步。这就是开发团队 [on this ticket] 解释的未针对查询扩展 $currentDate 的原因。

    话虽如此,完美的解决方案并不存在,但我们可以考虑变通方法。 serverStatus 函数返回有关 Mongo 集群的信息,包括服务器时间。您可以在初始化客户端代码时调用此函数,并找到客户端时间和服务器时间之间的差异。有了这个差异,您可以根据客户时间的差异进行查询。这是一个 Python sn-p:

    import datetime
    import pymongo
    client = pymongo.MongoClient()
    db = client.test_Db
    server_time = db.command("serverStatus")['localTime']
    local_time = datetime.datetime.now()
    difference = server_time - local_time
    
    
    db.test_collection.find({'date': {'$lt': datetime.datetime.now() - datetime.timedelta(minutes=10) + difference}})
    

    请注意,在服务器上测量时间和在客户端测量时间之间存在误差。此错误受信息从服务器发送到客户端的持续时间的影响。根据您的用例,您可以从数据库返回更多或更少的文档。如果您先在客户端获取时间,然后在服务器上获取时间,您将收到早于 10 分钟 + 错误 的文档,因此您会错过一些文档。另一方面,如果您先在服务器上获取时间,然后在客户端上获取时间,您将收到早于 10 分钟 - 错误 的文档,因此您将获得一些额外的文档。任何一种情况是否可以接受,都可以接受。

    要考虑的另一件事是,仅设置一个限制,您将收到越来越多的文档,因为在超过 10 分钟的时间会有越来越多的文档更新。此外,您将一遍又一遍地收到相同的文件。您还应该考虑设置一个下限。

    【讨论】:

    • 谢谢,你能不能更新一下票,这是解决方法,但我必须调用服务器两次并保持同步手表,我想用测试和设置方法设置最后更新时间使用原子单一调用。
    【解决方案2】:

    mongodb 服务器允许使用 $currentDate 运算符对 update 字段,但我没有找到任何选项来使用日期作为查询过滤器。

    但是有一个选项可以使用“在服务器上存储 JavaScript 函数”https://docs.mongodb.com/manual/tutorial/store-javascript-function-on-server/ 并添加一个返回日期的函数。

    【讨论】:

    • 您可以在有更多信息时更新问题,而不是写答案。这样人们就可以在回答您的问题之前找到相关信息。
    猜你喜欢
    • 2016-07-10
    • 2018-05-31
    • 2016-07-09
    • 2013-04-19
    • 1970-01-01
    • 2020-12-01
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多