本篇介绍MongoDB数据库中常见的数据类型使用场景,并给出最佳实践引导。
不将数字作为字符存储
优势:
采用聚合函数时,可以直接计算,比如sum max函数
原因:
MonoDB中是严格区分数据类型的,如果用字符串存储数字,用纯数字int类型查询是查询不到结果的,反之也是一样。
对于聚合函数,字符串如何计算呢?用的时候就知道了,字符串有多别扭。
时间类型选择
不将时间作为字符存储
首先温习几个基础的时间概念
UTC 与 Unix时间戳
在计算机中看到的UTC时间都是从(1970年01月01日 0:00:00)开始计算秒数的。所看到的UTC时间那就是从>1970年这个时间点起到具体时间共有多少秒。 这个秒数就是Unix时间戳。
UTC 与本地时间
UTC + 时区差 = 本地时间
UTC时间 与 GMT时间
我们可以认为格林威治时间就是时间协调时间(GMT=UTC),格林威治时间和UTC时间均用秒数来计算的。
再次了解下MongoDB存储时间的简单原理
MongoDB存储时间
在MongoDB常见的数据类型中关于时间的存储有两个类型分别是
● Timestamp: 时间戳, 表示从1970-1-1到现在的总秒数
● Date: 存储当前⽇期或时间的UNIX时间格式
MongoDB存储时间类型数据时,如果是Date类型,都是先转换为UTC时间,然后存储到数据库中。
时间属性常见的存储格式如下:
time:ISODate("2000-10-10T20:55:36Z"),
优势:
1 可以采用时间范围查询
2 用可视化工具查询结果时,可以一目了然对应的时间,方便跟踪问题。
原因:
如果使用时间戳存储,操作者还得专门去做转化,有多麻烦,谁用谁知道。
那你可以说,我可以直接转化为格式化的时间字符串存储到数据库中,那样问题更大。有以下几种可能:
1》数据库存储的时间格式不一定是前端要真正展示的格式,必定会存在转化。转化存在转化效率问题。
2》格式化的时间字符串不是一个标准的形式,没有规范,12小时制,24小时制?年月日,年月日时分秒?时区问题?这几个都无法解决,都是后续程序BUG的根源。
系统之间如何处理时间,我的建议如下。
前端系统通过时间戳与后端业务系统做交互,业务系统之间传递使用时间戳做交互,涉及到数据库访问,在数据库访问层,将时间戳转化为数据库可以识别的数据类型,通过驱动与数据库做交互。
Date类型的存储虽然有上边描述的优点,也有不足,就是数据从数据库取出来到应用程序转化时有消耗。所以也有一部分开发人员推荐在MongoDB中使用时间戳存储时间数据。
官方文档中有相关的建议
Additionally, using proper types for your data also increases query flexibility: if you store date as a timestamp you can make date range queries, whereas it’s very difficult to compare two strings that represent dates. The same issue holds for numeric fields; storing numbers as strings requires more space and is difficult to query.
上边一段话的意思主要表达,如果使用时间戳存储时间数据,可以为查询和范围查找提供方便,字符存储数字也会遇到同样的问题,如果用字符存储数字,则计算,比较会是非常困难的。
以下是官方的关于日志的设计示例
{
_id: ObjectId('4f442120eb03305789000000'),
host: "127.0.0.1",
logname: null,
user: 'frank',
time: ISODate("2000-10-10T20:55:36Z"),
path: "/apache_pb.gif",
request: "GET /apache_pb.gif HTTP/1.0",
status: 200,
response_size: 2326,
referrer: "[http://www.example.com/start.html](http://www.example.com/start.html)",
user_agent: "Mozilla/4.08 [en] (Win98; I ;Nav)"
}
下面我们看看PHP中关于MongoDb时间的常用操作
环境YII2 MongoDB
MongoDB\BSON\UTCDateTime 来源于mongodb驱动包
```
use MongoDB\BSON\UTCDateTime;
```
```
/**
* 获取当前时间的utc时间
*
* @return utcTime
* */
public static function getCurrentUtcTime()
{
$timeStamp = TimeUtility::getCurrentTimeStamp();
return $currentTime = new UTCDatetime($timeStamp * 1000);
}
/**
* 根据时间获取utc时间
*
* @param $date 时间格式
*
* @return utcTime
*/
public static function getUtcTimeByTimeDate($date)
{
return $time = new UTCDatetime(strtotime($date) * 1000);
}
```
文章中的观点有不严谨之处,欢迎评论沟通。
学习MongoDb数据库的基本态度:边学习,边实践,边参考,边改进,在问题中成长。