MongoDB聚合运算符:$dateSubtract

文章目录

    • 语法
    • 使用
      • 时间测量
      • 时区
    • 举例
      • 减去固定的数量
      • 根据相对日期筛选
      • 调整夏令时

$dateSubtract聚合运算符将Date()对象按指定的时间单位递减。从版本5.0开始支持。

语法

{$dateSubtract: {startDate: <Expression>,unit: <Expression>,amount: <Expression>,timezone: <tzExpression>}
}

返回一个日期对象Date()startDate可以是任何能被解析为日期、时间戳或对象Id的表达式,这三种类型都会返回Date()对象。

参数字段说明:

|字段|是否必须|描述|
|-|-|
|startDate|是|开始日期(UTC),可以是日期、时间戳或对象Id表达式|
|unit|是|要增加的时间的单位,单位可以是能被解析为下列值的表达式:yearquarterweekmonthdayhourminutesecondmillisecond|
|amount|是|以units为单位,在startDate基础上的增量,amount是可以被解析为整数、小数或双精度数的表达式|
|timezone|否|执行操作的时区,<tzExpression>必须是能被解析为奥尔森时区标识符格式的字符串或UTC偏移量,如果timezone不指定,返回值显示为UTC|

使用

时间测量

MongoDB遵循流行的数据库用法,以UTC为时间单位工作。dateSubtract表达式总是以 UTC 为起始日期,并以 UTC 为结果返回。如果指定了时区,计算将使用指定的时区进行。当计算涉及夏令时(DST)时,时区尤为重要。

如果单位是一个月或更大,操作会根据该月的最后一天进行调整。例如,在 10 月的最后一天增加一个月,这就是 "月末最后一天 "调整。

{$dateSubtract:{startDate: ISODate("2021-03-31T12:10:05Z"),unit: "month",amount: 1}
}

注意:返回的日期ISODate("2020-11-30T12:10:05Z")是30日,而不是 31日,因为11月的天数比10月少。

时区

<timezone>字段中使用 Olson 时区标识符时,MongoDB 会应用 DST 偏移(如果适用于指定的时区)。

例如,包含以下文件的sales集合:

{"_id" : 1,"item" : "abc","price" : 20,"quantity" : 5,"date" : ISODate("2017-05-20T10:24:51.303Z")
}

下面的聚合说明了 MongoDB 如何处理 Olson 时区标识符的 DST 偏移量。示例使用$hour$minute操作符返回日期字段的相应部分:

db.sales.aggregate([
{$project: {"nycHour": {$hour: { date: "$date", timezone: "-05:00" }},"nycMinute": {$minute: { date: "$date", timezone: "-05:00" }},"gmtHour": {$hour: { date: "$date", timezone: "GMT" }},"gmtMinute": {$minute: { date: "$date", timezone: "GMT" } },"nycOlsonHour": {$hour: { date: "$date", timezone: "America/New_York" }},"nycOlsonMinute": {$minute: { date: "$date", timezone: "America/New_York" }}}
}])

操作返回以下结果:

{"_id": 1,"nycHour" : 5,"nycMinute" : 24,"gmtHour" : 10,"gmtMinute" : 24,"nycOlsonHour" : 6,"nycOlsonMinute" : 24
}

举例

减去固定的数量

下面是一组系统连接时间:

db.connectionTime.insertMany([{custId: 457,login: ISODate("2020-12-25T19:04:00"),logout: ISODate("2020-12-28T09:04:00")},{custId: 457,login: ISODate("2021-01-27T05:12:00"),logout: ISODate("2021-01-28T13:05:00")},{custId: 458,login: ISODate("2021-01-22T06:27:00"),logout: ISODate("2021-01-31T11:00:00")},{custId: 459,login: ISODate("2021-02-14T20:14:00"),logout: ISODate("2021-02-17T16:05:00")},{custId: 460,login: ISODate("2021-02-26T02:44:00"),logout: ISODate("2021-02-18T14:13:00")}]
)

由于服务问题,需要从2021年1月的每个注销时间中减去3个小时,可以在聚合管道中使用$dateSubtract来递减注销时间。

db.connectionTime.aggregate([{$match:{$expr:{$eq:[{ $year: "$logout" },2021]},$expr:{$eq:[{ $month: "$logout" },1]}}},{$project:{logoutTime:{$dateSubtract:{startDate: "$logout",unit: "hour",amount: 3}}}},{$merge: "connectionTime"}]
)

$match阶段进行了两次类似的比较,首先,$year$month操作符分别从logoutTime日期对象中提取年份和月份;然后检查月份和年份是否与选择目标相匹配;由于"January"被编码为"1",因此当年和月等于($eq)"2021"和 "1"时,$expr为真。

$project阶段使用$dateSubtract从每个选定文档的logoutTime中减去3个小时。

最后,$merge阶段会更新集合,为修改后的文档写入新的logoutTime

**注意:**与$out不同,$merge阶段只更新匹配的文档,并保留集合的其他部分。

结果文档如下:

{"_id" : ObjectId("603dd94b044b995ad331c0b5"),"custId" : 457,"login" : ISODate("2020-12-25T19:04:00Z"),"logout" : ISODate("2020-12-28T09:04:00Z")
}
{"_id" : ObjectId("603dd94b044b995ad331c0b6"),"custId" : 457,"login" : ISODate("2021-01-27T05:12:00Z"),"logout" : ISODate("2021-01-28T13:05:00Z"),"logoutTime" : ISODate("2021-01-28T10:05:00Z")
}
{"_id" : ObjectId("603dd94b044b995ad331c0b7"),"custId" : 458,"login" : ISODate("2021-01-22T06:27:00Z"),"logout" : ISODate("2021-01-31T11:00:00Z"),"logoutTime" : ISODate("2021-01-31T08:00:00Z")
}
{"_id" : ObjectId("603dd94b044b995ad331c0b8"),"custId" : 459,"login" : ISODate("2021-02-14T20:14:00Z"),"logout" : ISODate("2021-02-17T16:05:00Z")
}
{"_id" : ObjectId("603dd94b044b995ad331c0b9"),"custId" : 460,"login" : ISODate("2021-02-26T02:44:00Z"),"logout" : ISODate("2021-02-18T14:13:00Z")
}

根据相对日期筛选

假如要向过去一周内使用过服务的客户发送调查问卷,$dateSubtract表达式可以创建一个相对于查询执行时间的范围过滤器。:

db.connectionTime.aggregate([{$match:{$expr:{$gt:["$logoutTime",{$dateSubtract:{startDate: "$$NOW",unit: "week",amount: 1}}]}}},{$project:{_id: 0,custId: 1,loggedOut:{$dateToString:{format: "%Y-%m-%d",date: "$logoutTime"}}}}]
)

内置聚合变量$$NOW返回ISODate格式的当前日期时间,$match阶段使用$$NOW中的值获取今天的日期;然后,比较表达式 ($expr) 使用大于 ($gt)和$dateSubtract过滤集合,以匹配注销时间在过去一周内的文档。

$project阶段使用$dateToString表达式将日期转换为更易读的格式,如果不进行转换,MongoDB将以ISODate格式返回日期,输出结果显示上周有两名客户注销。

{ "custId" : 459, "loggedOut" : "2021-02-17" }
{ "custId" : 460, "loggedOut" : "2021-02-18" }

调整夏令时

所有日期在内部都以UTC时间存储。如果指定了时区,$dateSubtract将使用当地时间进行计算。计算结果以UTC显示。

本例假如客户分布在多个时区,按天或按小时计费,现在要了解夏令时对计费期的影响。

创建billing集合:

db.billing.insertMany([{location: "America/New_York",login: ISODate("2021-03-13T10:00:00-0500"),logout: ISODate("2021-03-14T18:00:00-0500")},{location: "America/Mexico_City",login: ISODate("2021-03-13T10:00:00-00:00"),logout: ISODate("2021-03-14T08:00:00-0500")}]
)

首先从每个文件的login日期中减去 1 天,然后再减去 24 小时。

db.billing.aggregate([{$project:{_id: 0,location: 1,start:{$dateToString:{format: "%Y-%m-%d %H:%M",date: "$login"}},days:{$dateToString:{format: "%Y-%m-%d %H:%M",date:{$dateSubtract:{startDate: "$login",unit: "day",amount: 1,timezone: "$location"}}}},hours:{$dateToString:{format: "%Y-%m-%d %H:%M",date:{$dateSubtract:{startDate: "$login",unit: "hour",amount: 24,timezone: "$location"}}}},startTZInfo:{$dateToString:{format: "%Y-%m-%d %H:%M",date: "$login",timezone: "$location"}},daysTZInfo:{$dateToString:{format: "%Y-%m-%d %H:%M",date:{$dateSubtract:{startDate: "$login",unit: "day",amount: 1,timezone: "$location"}},timezone: "$location"}},hoursTZInfo:{$dateToString:{format: "%Y-%m-%d %H:%M",date:{$dateSubtract:{startDate: "$login",unit: "hour",amount: 24,timezone: "$location"}},timezone: "$location"}},}}]
).pretty()

$dateToString表达式对输出进行了重新格式化,以提高可读性。结果汇总如下:

|字段|纽约|墨西哥城|
|-|-|
|start|2021-03-14 15:00|2021-03-14 15:00|
|Start, TZ Info|2021-03-14 11:00|2021-03-14 04:00|
|1 Day|2021-03-13 16:00|2021-03-13 15:00|
|1 Day, TZ Info|2021-03-13 11:00|2021-03-13 09:00|
|24 Hours|2021-03-13 15:00|2021-03-13 15:00|
|24 Hours, TZ Info|2021-03-13 10:00|2021-03-13 09:00|

上表强调了几点:

  • 未格式化的日期以 UTC 返回。纽约的$login是 UTC-5,但开始、天数和小时行显示的时间是 UTC 时间。

  • 3月14日是纽约的夏令时开始日,但不是墨西哥的夏令时开始日。当某地切换到DST并从某一天跨入下一天时,计算的时间会进行调整。

  • 夏令时改变的是一天的长度,而不是小时。夏令时不会改变小时数。只有当测量单位为日或更大且计算跨越指定时区的时钟变化时,才会对 DST 进行调整。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/722179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL 注入 - 二阶注入

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 一、二阶注入介绍 二次注入是一种常见于Web应用程序中的安全漏洞,也被称为SQL二阶注入。相对于一次注入漏洞,二次注入更不易被察觉,但却具有同样危险的攻击潜力。简而言之,二次…

SPI总线知识总结

1 SPI的时钟极性CPOL和时钟相位CPHA的设置 1.1 SPI数据传输位数 SPI传输数据过程中总是先发送或接收高字节数据&#xff0c;每个时钟周期接收器或发送器左移一位数据。对于小于16位的数据&#xff0c;在发送前必须左对齐&#xff0c;如果接收的数据小于16位&#xff0c;则采用软…

汽车碰撞与刮伤的实用维修技术,汽车的车身修复与涂装修补教学

一、教程描述 本套汽车维修技术教程&#xff0c;大小7.44G&#xff0c;共有60个文件。 二、教程目录 01-汽车车身修复教程01-安全规则&#xff08;共3课时&#xff09; 02-汽车车身修复教程02-汽车结构&#xff08;共3课时&#xff09; 03-汽车车身修复教程03-汽车修复所使…

session\cookie

一、session 1、基本使用 会话 在整个会话周期中任何servlet或者jsp页面都可以到会话的数据 设置数据 //将登录用户的信息存入到session中 HttpSession//获得session对象HttpSession session req.getSession();session.setAttribute("loginUser", loginUser); …

为什么Spring Cloud 应用程序中,应用程序的加载配置必须写在bootstrap.yaml这个配置文件中,是在哪里规定的?

在 Spring Cloud 应用程序中&#xff0c;bootstrap.yaml&#xff08;或bootstrap.properties&#xff09;的使用并非强制性的&#xff0c;但它扮演着一个特定的角色&#xff0c;主要是因为 Spring Cloud 的设计和工作流程。 背景和设计 Spring Cloud 构建在 Spring Boot 之上…

鸿蒙 Stage模型-应用组件-配置、UIAbility

前提&#xff1a;基于官网3.1/4.0文档。参考官网文档 基于Android开发体系来进行比较和思考。&#xff08;或有偏颇&#xff0c;自行斟酌&#xff09; 一、概念 可以看到分为运行期、编译器&#xff0c;主要关注UIAbility&#xff08;类似Activity&#xff0c;UI相关&#xff0…

2024年软考-官方最新考试安排出来了,软考新调整,很重要,但也很惹人气愤

官方最新通知&#xff0c;关于2024年度计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试工作计划 笔试改机考后&#xff0c;必然会迎来调整&#xff0c;但有点让人费解。 这次调整变动主要是每年考试的次数调整&#xff0c;很多改为了一年一考&#xff0c;具体…

Ansible playbook 简介 使用场景

Ansible playbook 简介 playbook 是 ansible 用于配置&#xff0c;部署&#xff0c;和管理被控节点的剧本。   通过 playbook 的详细描述&#xff0c;执行其中的一系列 tasks &#xff0c;可以让远端主机达到预期的状态。playbook 就像 Ansible 控制器给被控节点列出的的一系…

Claude 3 模型发布,压力来到OpenAI这边了~

Anthropic 发布了 Claude 3 系列&#xff0c;包含了三款模型 各具特色&#xff0c;旨在为用户提供更智能、更快速、更高效的选择&#xff0c;可以说是是迄今为止最快、最强大的人工模型&#xff01; Anthropic 一度是 OpenAI 最强力的竞争对手&#xff01; 随着 Claude3 的发…

云计算 3月5号 (DNS域名解析及部署)

DNS域名解析服务 1.DNS介绍 DNS 是域名系统 (Domain Name System) 的缩写&#xff0c;是因特网的一项核心服务&#xff0c;它作为可以将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便的访问互联网&#xff0c;而不用去记住能够被机器直接读取的IP数串。…

408专业课130+|我的备考经验和复盘

408的四门课任务量多到爆炸&#xff01;但难度不止于此。别忘了大部分选计算机的勇士们&#xff0c;是要考数学的&#xff01;直接起飞。 408数学无疑是王炸王炸&#xff0c;要想上岸就一定要把这两个大头一起拿下&#xff01; 作为一个成功上岸的非计算机专业跨考生&#xf…

linux系统ELK组件介绍

ELK组件介绍 ELK组件介绍Elasticsearch&#xff1a;Logstash:Kibana:Kafka&#xff1a; Filebeat: ELK 官网地址&#xff1a;https://www.elastic.co 官网搭建&#xff1a;https://www.elastic.co/guide/index.html 组件介绍 Elasticsearch&#xff1a; 是一个基于Lucene的搜…

CSS全局样式的设置,web开发交流

面试题 HTML 1&#xff0c;html5有哪些新特性&#xff1f; 2&#xff0c;html5移除了那些元素&#xff1f; 3&#xff0c;如何处理HTML5新标签的浏览器兼容问题 戳这里领取完整开源项目&#xff1a;【一线大厂前端面试题解析核心总结学习笔记Web真实项目实战最新讲解视频】…

【十一】【SQL】外连接(左外连接,右外连接)

数据库中的外连接&#xff08;Outer Join&#xff09;用于连接两个表&#xff0c;并包括两个表中的匹配行以及左表&#xff08;LEFT JOIN&#xff09;或右表&#xff08;RIGHT JOIN&#xff09;中未匹配的行。外连接分为两种主要类型&#xff1a; 左外连接&#xff08;LEFT OU…

如何用python实现Can总线通讯

今天去广交会参展, 里面关于工业, 有很多基于profinet、can等总线通讯协议的硬件网关, 好像总线协议一般都用于硬件嵌入式层面, 纯软方面很少涉及, 那如何使用python进行Can总线通讯呢? CAN(Controller Area Network)总线是一种常用于汽车和工业自动化中的通信协议。在…

day58 异常 IO流

异常 1异常处理机制 编译时错误 运行时错误 代码逻辑错误 2异常类结构图 java.lang.Throwable 所有异常的父类 只有它能剖出异常 java.lang.Error: extends Throwable 程序中的硬件严重问题不需要处理 java.lang.Exception extends Throwable 异常 指出要捕获的处理条件 3异常…

外贸独立站使用简站WordPress模板搭建的优势

在全球化的商业浪潮中&#xff0c;外贸独立站成为了企业走出国门、开拓国际市场的重要桥梁。而简站WordPress模板作为一种高效、便捷的建站工具&#xff0c;正受到越来越多外贸企业的青睐。本文将从多个方面分析使用简站WordPress模板搭建外贸独立站的优势。 一、快速搭建&…

深入理解现代JavaScript:从语言特性到应用实践

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 JavaScript作为一门动态、解释性脚本语言&…

网络工程师笔记8

华为VRP系统 设备管理方式 web管理方式 命令行管理方式 修改命令&#xff1a;undo 基础配置命令

001 概述

什么是API API&#xff08;Application Programming Interface,应用程序编程接口&#xff09;是一些预先定义的函数&#xff0c;目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力&#xff0c;而又无需访问源码&#xff0c;或理解内部工作机制的细节。为了…