날짜 빼기(집계)
정의
$dateSubtract
버전 5.0에 추가.
Date 객체 를 지정된 시간 단위만큼 감소시킵니다.
$dateSubtract
표현식의 구문은 다음과 같습니다.{ $dateSubtract: { startDate: <Expression>, unit: <Expression>, amount: <Expression>, timezone: <tzExpression> } } 날짜 를 반환합니다.
startDate
는 날짜, 타임스탬프 또는 ObjectId 유형으로 해석되는 모든 표현식일 수 있습니다. 어떤 데이터 유형이 입력으로 사용되든 반환되는 값은 Date 객체가 됩니다.필드필수/선택 사항설명startDate
필수 사항unit
필수 사항unit
은startDate
에서 뺀 시간의amount
를 측정하는 데 사용됩니다.unit
은 다음 문자열 중 하나로 리졸브되는 표현식입니다.year
quarter
week
month
day
hour
minute
second
millisecond
amount
필수 사항startDate
에서 뺀units
수.amount
는 정수 또는 long으로 해석되는 표현식입니다.amount
는 해당 값이 정밀도 손실 없이 long으로 변환될 수 있는 경우 정수/소수 또는 double로 해석될 수도 있습니다.timezone
옵션작업을 수행할 표준 시간대입니다. 은 Olson 표준 시간대
<tzExpression>
식별자 형식의 string 로 해석되는 유효한 표현식 이어야 합니다. 또는 UTC 오프셋 .timezone
이 제공되지 않으면 결과가UTC
에 표시됩니다.형식예시Olson 표준 시간대 ID"America/New_York" "Europe/London" "GMT" UTC 오프셋+/-[hh]:[mm], e.g. "+04:45" +/-[hh][mm], e.g. "-0530" +/-[hh], e.g. "+03" 표현식 및 유형에 대한 자세한 내용은 표현식 및 BSON types를 참조하세요.
행동
시간 측정
MongoDB는 일반적인 데이터베이스 사용법을 따르며 UTC 시간으로 작동합니다. dateSubtract
표현식은 항상 UTC로 startDate
를 취하고 결과를 UTC로 반환합니다. timezone
이 지정된 경우 지정된 timezone
을 사용하여 계산이 수행됩니다. 표준 시간대는 계산에 일광 절약 시간제(DST)가 포함될 때 특히 중요합니다.
unit
이 month
이상인 경우 해당 월의 마지막 날을 고려하도록 연산이 조정됩니다. 예를 들어 3월 마지막 날에 month
하나를 빼면 '당월 마지막 날짜' 조정이 나타납니다.
{ $dateSubtract: { startDate: ISODate("2021-03-31T12:10:05Z"), unit: "month", amount: 1 } }
2월이 3월보다 날짜 수가 적기 때문에 반환된 날짜 ISODate("2021-02-28T12:10:05Z")
은(는) 31일이 아니라 28일이라는 점에 유의하세요.
시간대
<timezone>
필드에서 Olson 표준 시간대 ID를 사용할 때 MongoDB는 지정된 시간대에 적용 가능한 경우 DST 오프셋을 적용합니다.
예를 들어 sales
다음 문서가 있는 컬렉션을 생각해 보겠습니다.
{ "_id" : 1, "item" : "abc", "price" : 20, "quantity" : 5, "date" : ISODate("2017-05-20T10:24:51.303Z") }
다음 집계는 MongoDB가 Olson 시간대 식별자에 대한 DST 오프셋을 처리하는 방법을 보여 줍니다. 이 예시에서는 $hour
및 $minute
연산자를 사용하여 date
필드의 해당 부분을 반환합니다.
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
을(를) 사용하여 logoutTime
을(를) 줄일 수 있습니다.
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
날짜 객체에서 각각 연도와 월을 추출합니다. 그런 다음 월과 연도가 선택 대상과 일치하는지 확인합니다. '1월'은 '1'로 인코딩되므로 연도와 월이 '2021' 및 '1'로 동일할($eq
) 경우, $expr
은 참이 됩니다.
$project
단계는 $dateSubtract
를 사용해 선택한 각 문서의 logoutTime
에서 3시간을 뺍니다.
마지막으로 $merge
단계에서는 collection을 업데이트하여 수정된 문서에 대해 새로운 logoutTime
을 작성합니다.
참고
$out
과 달리 $merge
컬렉션 단계에서는 일치하는 문서만 업데이트하고 나머지 컬렉션은 보존합니다. 자세한 내용은 $merge와 $out 비교를 참조하세요.
결과 문서는 다음과 같이 표시됩니다.
{ "_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
보다 큰 값을 사용하여 컬렉션을 필터링해 지난 주에 logoutTime
이 있었던 문서와 일치시킵니다.
$project
단계에서는 $dateToString
표현식을 사용하여 날짜를 더 읽기 쉬운 형식으로 변환합니다. 변환이 없으면 MongoDB는 날짜를 ISODate 형식으로 반환합니다. 출력에는 지난 주에 고객 두 명이 로그아웃한 것으로 표시됩니다.
{ "custId" : 459, "loggedOut" : "2021-02-17" } { "custId" : 460, "loggedOut" : "2021-02-18" }
서머타임에 맞게 조정하기
모든 날짜는 내부적으로 UTC 시간으로 저장됩니다. timezone
을 지정하면 $dateSubtract
는 현지 시간을 사용하여 계산을 수행합니다. 결과는 UTC로 표시됩니다.
고객이 여러 시간대에 있으며 day
또는 hour
을(를) 기준으로 청구할 경우 서머타임이 청구 기간에 어떤 영향을 주는지 확인하려고 합니다.
다음과 같은 연결 시간 컬렉션을 생성합니다.
db.billing.insertMany( [ { location: "America/New_York", login: ISODate("2021-03-14T10:00:00-0500"), logout: ISODate("2021-03-14T18:00:00-0500") }, { location: "America/Mexico_City", login: ISODate("2021-03-14T10:00:00-00:00"), logout: ISODate("2021-03-15T08:00:00-0500") } ] )
먼저 1일을 뺀 다음 각 문서의 login
날짜에서 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
표현식은 가독성을 위해 출력 형식을 다시 지정합니다. 결과는 다음과 같이 요약됩니다.
필드 | New York | 멕시코 시티 |
---|---|---|
시작하기 | 2021-03-14 15:00 | 2021-03-14 15:00 |
시작, TZ 정보 | 2021-03-14 11:00 | 2021-03-14 04:00 |
1일 | 2021-03-13 16:00 | 2021-03-13 15:00 |
1일, TZInfo | 2021-03-13 11:00 | 2021-03-13 09:00 |
24시간 | 2021-03-13 15:00 | 2021-03-13 15:00 |
24시간, TZInfo | 2021-03-13 10:00 | 2021-03-13 09:00 |
이 차트는 다음과 같은 요점 몇 가지를 몇 가지 요점을 강조해 보여줍니다.
형식이 지정되지 않은 날짜는 UTC로 반환됩니다. 뉴욕의
$login
은 UTC -5이지만start
,days
,hours
행은 시간을 UTC로 표시합니다.3월 14일에는 뉴욕에서 서머타임이 시작되지만, 멕시코에서는 그렇지 않습니다. 계산된 시간은 위치가 DST로 전환되고 한
day
에서 다음으로 넘어갈 때 조정됩니다.DST는
hour
이 아닌day
의 길이를 수정합니다.hours
관련 DST 변경 사항이 없습니다.unit
측정값이day
이상이고 계산이 지정된timezone
시간 변화와 교차하는 경우에만 DST를 조정할 수 있습니다.