Docs Menu
Docs Home
/
MongoDBマニュアル
/ / /

$dateSubtract(集計)

項目一覧

  • 定義
  • 動作
$dateSubtract

バージョン 5.0 で追加

指定された時間単位数で Date()オブジェクトを減算します。

$dateSubtract式の構文は次のとおりです。

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

Date() を返します。startDate は、Date 型、Timestamp 型、または ObjectId 型に変換される任意の式にできます。どのデータ型が入力に使用されるかにかかわらず、返される値は Date() オブジェクトになります。

フィールド
必須/オプション
説明

startDate

必須

減算演算の開始日(UTC)。startDate は、DateTimestamp、または ObjectId に変換される任意のにできます。

unit

必須

startDate から差し引かれた時間のamount を測定するために使用される unit です。unit は、次のいずれかの文字列に変換されるです。

  • year

  • quarter

  • week

  • month

  • day

  • hour

  • minute

  • second

  • millisecond

amount

必須

startDate から差し引かれた units の数。amount は、integer または long に変換されるです。amount は、その値が精度を失うことなく long に変換できる場合は、integer decimal または double に変換することもできます。

timezone

任意

操作を実行するタイムゾーン。 <tzExpression>は、 Olson タイムゾーン識別子 として形式された string に変換される有効な 式 である必要があります。 または UTC オフセット 。timezoneが指定されていない場合、結果はUTCに表示されます。

形式

Olson タイムゾーン識別子

"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) が含まれる場合、タイムゾーンは特に重要です。

unitmonth またはそれより大きい場合、操作は月の最終日を考慮して調整されます。たとえば、3 月の最終日に month を 1 つ引くと、「月末日」の調整が行われます。

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

2 月は 3 月よりも日数が少ないため、返される日付 ISODate("2021-02-28T12:10:05Z") は 31 日ではなく 28 日であることがわかります。

<timezone> フィールドで Olson タイムゾーン識別子を使用する際、指定されたタイムゾーンに該当する場合、MongoDB は DST オフセットを適用します。

たとえば、次のドキュメントを含む sales コレクションを考えます。

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

次の集計は、MongoDB がタイムゾーン識別子の 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 ステージでは同様の比較が 2 回行われます。まず、$year 演算子と $month 演算子は、logoutTime Date オブジェクトからそれぞれ年と月を抽出します。次に、月と年が選択対象と一致するかどうかをチェックします。"January" は "1" としてエンコードされるため、$expr は、年と月が "2021" と "1" に等しい($eq)場合、true です。

$project ステージでは、$dateSubtract を使用して、選択された各ドキュメントの logoutTime から 3 時間を差し引きます。

最後に、$merge ステージでコレクションが更新され、変更されたドキュメントの新しい logoutTime が書き込まれます。

注意

$out とは異なり、$merge ステージでは一致したドキュメントのみが更新され、コレクションの残りの部分は保持されます。詳細については、「$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")
}

過去 1 週間にサービスを利用したクライアントにアンケートを送ろうとしています。$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 を使用してコレクションをフィルタリングし、過去 1 週間に logoutTime があるドキュメントと一致させます。

$projectステージでは、 $dateToString式を使用して日付をより読みやすい形式に変換します。 変換を行わない場合、MongoDB は日付をISODate形式で返し、UTC タイムゾーンを想定します。

出力には、過去 1 週間に 2 人のカスタマーがログアウトしたことが示されています。

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

すべての日付は、内部的には UTC 時間でストアされます。timezone が指定されている場合、$dateSubtract はローカル タイムを使用して計算を実行します。結果は UTC で表示されます。

複数のタイムゾーンのカスタマーがいて、dayhour で請求した場合、夏時間が請求期間にどのような影響を与えるかを確認したい場合があります。

この接続時間のコレクションを作成します。

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")
}
]
)

まず各ドキュメントの 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 式は、読みやすいように出力を再フォーマットします。 結果の概要は次のとおりです。

フィールド
New York
メキシコシティ

始める

2021-03-14 15:00

2021-03-14 15:00

スタート、タイムゾーン情報

2021-03-14 11:00

2021-03-14 04:00

1 日

2021-03-13 16:00

2021-03-13 15:00

1 日、タイムゾーン情報

2021-03-13 11:00

2021-03-13 09:00

24 時間

2021-03-13 15:00

2021-03-13 15:00

24 時間、タイムゾーン情報

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 の変更はありません。DST の調整は、測定 unitday 以上で、計算が指定された timezone で時差が生じる場合にのみ行われます。

Tip

以下も参照してください。

戻る

$dateFromString

項目一覧