导航

mongodb的实践

Posted on 2015-05-16 09:36  八竿子打不着  阅读(204)  评论(0)    收藏  举报

1   mongodb中的utc时间问题:

  

今天遇到了这么一个需求,把北京时间今日零时到当前的所有记录都查找出来。

第一个反应就是这涉及到范围问题,只需要先把年、月、日按照当前的$match过滤一遍,然后再把小时按照从0到当前的滤一遍,就可以得到结果了。但是我的想法是错的,因为时间标准不统一,业务中的代码采用的是北京时间,而数据库中存储的是utc时间,中间差了8个小时。要知道,相差8个小时,不仅仅是相差了1天,还有可能相差了1年、1月,所以知道这点后我就写出了如下的代码:

【nodejs环境】

    // 将北京时间今日0点构造成utc时间
    var d0 = new Date();
    d0.setMinutes( 0 );
    d0.setSeconds( 0 );
    d0.setHours( d0.getHours() - 8 );

    // 将北京当前时间构造成utc时间
    var dn = new Date();
    dn.setHours( dn.getHours() - 8 );

         ………………
        // 只写管道中的代码

            {
                $project : {
                    year : {$year : "$date"},
                    month : {$month : "$date"},
                    day : {$dayOfMonth : "$date"},
                    hour : {$hour : "$date"},
                    err : 1,
                    date : 1
                }
            },
            {
                $match : {
                    year : {
                        $gte : d0.getFullYear(),
                        $lte : dn.getFullYear()
                    },
                    month : {
                        $gte : d0.getMonth() + 1,
                        $lte : dn.getMonth() + 1
                    },
                    day : {
                        $gte : d0.getDate(),
                        $lte : dn.getDate()
                    },
                    err : "bad request 400"
                }
            },
            {
                $group : {
                    _id : {
                        "year" : "$year",
                        "month" : "$month",
                        "day" : "$day",
                        "hour" : "$hour"
                    },
                    count : {
                        $sum : 1
                    }
                }
            }

可以看出来,当时我非常愚蠢的把年月日分别做比较,这样一来无端增添了不必要的代码。

晚上回家继续琢磨这个问题,思考有没有更好的解决方法,翻看《mongodb权威指南(第二版)》的时候,看到了类似这样的用法:$hour : "$date";

这提醒了我在调价中可以直接构造一个变量,然后mongodb会自动把这个变量转化成utc标准?实验了一下果然可以,代码少了不少。

 

    // 将北京时间今日0点构造成utc时间
    var d0 = new Date();
    d0.setMinutes( 0 );
    d0.setSeconds( 0 );
    d0.setHours( 0 );

        // 将北京当前时间构造成utc时间
    var dn = new Date();        

        ………………
        // 只写管道部分代码
            {
                $project : {
                    hour : {$hour : "$date"},
                    err : 1,
                    date : 1
                }
            },
            {
                $match : {
                    date : {
                        $gte : d0,
                        $lte : dn
                    },
                    err : "bad request 400"
                }
            },
            {
                $group : {
                    _id : {
                        "hour" : "$hour"
                    },
                    count : {
                        $sum : 1
                    }
                }
            }

 

可以看到代码明显精简了。

小结:可以在mongodb中进行比较,mongodb会自动把北京时间转换为utc时间,这点可以利用起来。