$dateDiff(集計)
定義
$dateDiff
バージョン 5.0 で追加
2 つの日付の差を返します。
$dateDiff
式の構文は次のとおりです。{ $dateDiff: { startDate: <Expression>, endDate: <Expression>, unit: <Expression>, timezone: <tzExpression>, startOfWeek: <String> } } endDate
からstartDate
を差し引きます。指定されたunit
で整数が返されます。フィールド必須/オプション説明startDate
必須endDate
必須unit
必須startDate
とendDate
の間の、時間測定のunit
。これは以下の文字列に変換される式です。year
quarter
week
month
day
hour
minute
second
millisecond
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" startOfWeek
任意単位が
week
と等しい場合に使用されます。デフォルトはSunday
です。startOfWeek
パラメータは、大文字と小文字を区別しない文字列に変換される式です。monday
(またはmon
)tuesday
(またはtue
)wednesday
(またはwed
)thursday
(またはthu
)friday
(またはfri
)saturday
(またはsat
)sunday
(またはsun
)
動作
分数単位なし
$dateDiff
式は、測定されたstartDate
とendDate
の差を、指定された units
の整数で返します。期間は、ユニット境界を通過した回数で測定されます。例、18 か月離れた 2 つの日付の場合、その差は 1.5 years
ではなく 1 year
で返されます。
週の開始
startOfWeek
パラメータによって変更されない限り、week
は Sunday
から始まります。指定された日の startDate
と endDate
の間に始まる週がカウントされます。週数は暦上の month
または year
によっては制限されません。
タイムゾーン
<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.orders.insertMany( [ { custId: 456, purchased: ISODate("2020-12-31"), delivered: ISODate("2021-01-05") }, { custId: 457, purchased: ISODate("2021-02-28"), delivered: ISODate("2021-03-07") }, { custId: 458, purchased: ISODate("2021-02-16"), delivered: ISODate("2021-02-18") } ] )
次の例:
配達にかかる平均日数を返します。
dateDiff
を使用してpurchased
の日付とdelivered
の日付の差を計算します。
db.orders.aggregate( [ { $group: { _id: null, averageTime: { $avg: { $dateDiff: { startDate: "$purchased", endDate: "$delivered", unit: "day" } } } } }, { $project: { _id: 0, numDays: { $trunc: [ "$averageTime", 1 ] } } } ] )
$group
ステージの$avg
アキュムレータでは、purchased
の日付からdelivered
の日付までの期間の取得に $dateDiff
を使用します。結果の値は averageTime
として返されます。
averageTime
の小数点以下の値は $project
ステージで切り捨てられ($trunc
)、下記のような出力が生成されます。
{ "numDays" : 4.6 }
結果の精度
サブスクリプションの開始日と終了日を指定してこのコレクションを作成します。
db.subscriptions.insertMany( [ { custId: 456, start: ISODate("2010-01-01"), end: ISODate("2011-01-01") }, { custId: 457, start: ISODate("2010-01-01"), end: ISODate("2011-06-31") }, { custId: 458, start: ISODate("2010-03-01"), end: ISODate("2010-04-30") } ] )
$dateDiff
式は、整数 units
で表された期間の差を返します。単位には小数部分はありません。たとえば years
でカウントする場合、半年の単位はありません。
この例では unit
を変更すると返される値の精度が変わることがわかります。
db.subscriptions.aggregate( [ { $project: { Start: "$start", End: "$end", years: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "year" } }, months: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "month" } }, days: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "day" } }, _id: 0 } } ] )
結果を次の表にまとめています。
始める | End | 年 | か月 | 日 |
---|---|---|---|---|
2010-01-01 | 2011-01-01 | 1 | 12 | 365 |
2010-01-01 | 2011-07-01 | 1 | 18 | 546 |
2010-03-01 | 2010-04-30 | 0 | 1 | 60 |
カウントは新しいunit
が開始されたときにのみ増加するため、2 行目では 18 か月が 1 年として報告され、3 行目では 60 日が 1 か月として報告されます。
1 か月あたりの週数
月のコレクションを作成します。
db.months.insertMany( [ { month: "January", start: ISODate("2021-01-01"), end: ISODate("2021-01-31") }, { month: "February", start: ISODate("2021-02-01"), end: ISODate("2021-02-28") }, { month: "March", start: ISODate("2021-03-01"), end: ISODate("2021-03-31") }, ] )
以下のコードを使用して、各週の始まりを変更した上で、各月の週数をカウントできます。
db.months.aggregate( [ { $project: { wks_default: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "week" } }, wks_monday: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "week", startOfWeek: "Monday" } }, wks_friday: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "week", startOfWeek: "fri" } }, _id: 0 } } ] )
結果を次の表にまとめています。
月 | Sunday | Monday | Friday |
---|---|---|---|
1月 | 5 | 4 | 4 |
2月 | 4 | 3 | 4 |
3月 | 4 | 4 | 4 |
結果より:
startOfWeek
が日曜日の場合、2021 年 1 月の第 5 週 (week
) は31日から始まります。31日は日曜日で、
startDate
からendDate
の間であるため、カウントに 1week
が追加されます。暦上の週が
endDate
以降、または暦上の次の期間内に終了する場合でも、week
カウントは増加します。